diff --git a/AsbCloudApp/Services/IOperationsStatService.cs b/AsbCloudApp/Services/IOperationsStatService.cs
index 6ceb76e1..a92d0553 100644
--- a/AsbCloudApp/Services/IOperationsStatService.cs
+++ b/AsbCloudApp/Services/IOperationsStatService.cs
@@ -16,7 +16,7 @@ namespace AsbCloudApp.Services
///
///
///
- Task GetRopStatAsync(int idWell, CancellationToken token);
+ Task GetOrDefaultRopStatAsync(int idWell, CancellationToken token);
///
/// Получить статистику по скважинам куста, которые доступны компании
@@ -25,7 +25,7 @@ namespace AsbCloudApp.Services
///
///
///
- Task GetStatClusterAsync(int idCluster, int idCompany, CancellationToken token = default);
+ Task GetOrDefaultStatClusterAsync(int idCluster, int idCompany, CancellationToken token);
///
/// получить статистику по скважине
@@ -33,7 +33,7 @@ namespace AsbCloudApp.Services
///
///
///
- Task GetWellStatAsync(int idWell, CancellationToken token = default);
+ Task GetOrDefaultWellStatAsync(int idWell, CancellationToken token);
///
/// Получить данные для графика TVD
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
index ddebda4b..af16e2a1 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
@@ -43,7 +43,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
.Where(t => t.BlockPosition > 0.0001)
.Where(t => t.WellDepth > 0.0001)
.Where(t => t.Mode != null)
- .Where(t => modes.Contains(t.Mode.Value))
+ .Where(t => modes.Contains(t.Mode!.Value))
.Where(t => t.WellDepth - t.BitDepth < 0.01)
.GroupBy(t => new {
t.DateTime.Hour,
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
index 1e1dd035..68368e63 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
@@ -7,12 +7,12 @@ using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Numerics;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.WellOperationService
{
+#nullable enable
public class OperationsStatService : IOperationsStatService
{
private readonly IAsbCloudDbContext db;
@@ -26,8 +26,15 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
this.wellService = wellService;
}
- public async Task GetStatClusterAsync(int idCluster, int idCompany, CancellationToken token = default)
+ public async Task GetOrDefaultStatClusterAsync(int idCluster, int idCompany, CancellationToken token)
{
+ var cluster = (await memoryCache
+ .GetOrCreateBasicAsync(db.Set(), token))
+ .FirstOrDefault(c => c.Id == idCluster);
+
+ if (cluster is null)
+ return null;
+
var allWellsByCompany = await wellService.GetAsync(new() { IdCompany = idCompany }, token).ConfigureAwait(false);
var idWellsByCompany = allWellsByCompany.Select(w => w.Id).Distinct();
@@ -41,9 +48,6 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
var statsWells = await GetWellsStatAsync(wells, token).ConfigureAwait(false);
- var cluster = (await memoryCache
- .GetOrCreateBasicAsync(db.Set(), token))
- .FirstOrDefault(c => c.Id == idCluster);
var statClusterDto = new StatClusterDto
{
Id = idCluster,
@@ -71,7 +75,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return statsWells;
}
- public async Task GetWellStatAsync(int idWell,
+ public async Task GetOrDefaultWellStatAsync(int idWell,
CancellationToken token = default)
{
var well = await db.Wells
@@ -79,11 +83,14 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.FirstOrDefaultAsync(w => w.Id == idWell, token)
.ConfigureAwait(false);
+ if(well is null)
+ return null;
+
var statWellDto = await CalcWellStatAsync(well, token);
return statWellDto;
}
- public async Task GetRopStatAsync(int idWell, CancellationToken token)
+ public async Task GetOrDefaultRopStatAsync(int idWell, CancellationToken token)
{
var clusterWellsIds = await wellService.GetClusterWellsIdsAsync(idWell, token)
.ConfigureAwait(false);
@@ -110,13 +117,15 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ToListAsync(token)
.ConfigureAwait(false);
- var statsList = clusterWellsIds.Select(clusterWellId =>
+ var statsList = new List(clusterWellsIds.Count());
+ foreach (var clusterWellId in clusterWellsIds)
{
var currentWellOps = operations.Where(o => o.IdWell == clusterWellId);
- var timezoneOffsetH = wellService.GetTimezone(clusterWellId).Hours;
- var stat = CalcStat(currentWellOps, timezoneOffsetH);
- return stat;
- }).Where(c => c is not null);
+ var timezoneOffsetHours = wellService.GetTimezone(clusterWellId).Hours;
+ var stat = CalcStat(currentWellOps, timezoneOffsetHours);
+ if(stat is not null)
+ statsList.Add(stat);
+ };
if (!statsList.Any())
return null;
@@ -130,7 +139,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return clusterRops;
}
- private async Task CalcWellStatAsync(Well well, CancellationToken token = default)
+ private async Task CalcWellStatAsync(Well well, CancellationToken token)
{
var wellType = (await memoryCache
.GetOrCreateBasicAsync(db.Set(), token))
@@ -164,7 +173,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return statWellDto;
}
- private double CalcTvdLagDays(IOrderedEnumerable wellOperations)
+ private static double CalcTvdLagDays(IOrderedEnumerable wellOperations)
{
var operationsOrdered = wellOperations
.OrderBy(o => o.DateStart);
@@ -178,9 +187,13 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
if (lastCorrespondingFactOperation is null)
return 0d;
- var lastCorrespondingPlanOperation = wellOperations.FirstOrDefault(o => o.Id == lastCorrespondingFactOperation.IdPlan);
+ var lastCorrespondingPlanOperation = wellOperations
+ .FirstOrDefault(o => o.Id == lastCorrespondingFactOperation.IdPlan);
- var lastFactOperation = factOperations.LastOrDefault();
+ if (lastCorrespondingPlanOperation is null)
+ return 0d;
+
+ var lastFactOperation = factOperations.Last();
var remainingPlanOperations = operationsOrdered
.Where(o => o.IdType == WellOperation.IdOperationTypePlan)
@@ -240,27 +253,27 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return section;
}
- private static StatOperationsDto CalcSectionStat(IEnumerable operations, int idSectionType, double timezoneOffsetH)
+ private static StatOperationsDto? CalcSectionStat(IEnumerable operations, int idSectionType, double timezoneOffsetHours)
{
var sectionOperations = operations
.Where(o => o.IdWellSectionType == idSectionType)
.OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthStart);
- return CalcStat(sectionOperations, timezoneOffsetH);
+ return CalcStat(sectionOperations, timezoneOffsetHours);
}
- private static StatOperationsDto CalcStat(IEnumerable operations, double timezoneOffsetH)
+ private static StatOperationsDto? CalcStat(IEnumerable operations, double timezoneOffsetHours)
{
if (!operations.Any())
return null;
- var races = GetCompleteRaces(operations, timezoneOffsetH);
+ var races = GetCompleteRaces(operations, timezoneOffsetHours);
var section = new StatOperationsDto
{
- Start = operations.FirstOrDefault()?.DateStart.ToRemoteDateTime(timezoneOffsetH),
- End = operations.Max(o => o.DateStart.ToRemoteDateTime(timezoneOffsetH).AddHours(o.DurationHours)),
+ Start = operations.FirstOrDefault()?.DateStart.ToRemoteDateTime(timezoneOffsetHours),
+ End = operations.Max(o => o.DateStart.ToRemoteDateTime(timezoneOffsetHours).AddHours(o.DurationHours)),
WellDepthStart = operations.Min(o => o.DepthStart),
WellDepthEnd = operations.Max(o => o.DepthStart),
Rop = CalcROP(operations),
@@ -356,7 +369,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
{
var dDepth = 0d;
var dHours = 0d;
- foreach (var race in races)
+ foreach (Race race in races)
{
dDepth += race.StartWellDepth;
for (var i = 0; i < race.Operations.Count; i++)
@@ -417,78 +430,71 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
var tzOffsetHours = wellService.GetTimezone(idWell).Hours;
- if (!wellOperationsPlan.Any())
- return null;
-
- var merged = MergeArraysBySections(sectionsIds, wellOperationsPlan, wellOperationsFact);
+ var merged = MergeArraysBySections(sectionsIds, wellOperationsPlan, wellOperationsFact).ToList();
var tvd = new List>(merged.Count);
- var firstPoint = merged.First();
- var dateStart = firstPoint.Item1?.DateStart ?? firstPoint.Item2.DateStart;
- int iLastMatch = 0;
+ var (Plan, Fact) = merged.First();
+ var dateStart = Plan?.DateStart ?? Fact!.DateStart;
+ int? iLastMatch = null;
int iLastFact = 0;
var nptHours = 0d;
for (int i = 0; i < merged.Count; i++)
{
var item = merged[i];
- var plan = item.Item1;
- var fact = item.Item2;
+ var plan = item.Plan;
+ var fact = item.Fact;
- if (fact is not null && WellOperationCategory.NonProductiveTimeSubIds.Contains(fact.IdCategory))
+ var planFactPredict = new PlanFactPredictBase();
+ if (plan is not null)
{
- nptHours += fact.DurationHours;
+ planFactPredict.Plan = Convert(plan, tzOffsetHours);
+ planFactPredict.Plan.Day = (planFactPredict.Plan.DateStart - dateStart).TotalDays;
+ if (fact is not null)
+ iLastMatch = i;
}
- var planFactPredict = new PlanFactPredictBase
+ if (fact is not null)
{
- Plan = Convert(plan, tzOffsetHours),
- Fact = Convert(fact, tzOffsetHours),
- Predict = null,
- };
+ if(WellOperationCategory.NonProductiveTimeSubIds.Contains(fact.IdCategory))
+ nptHours += fact.DurationHours;
- if (planFactPredict.Plan is not null)
- planFactPredict.Plan.Day = (planFactPredict.Plan.DateStart - dateStart).TotalDays;
-
- if (planFactPredict.Fact is not null)
- {
+ planFactPredict.Fact = Convert(fact, tzOffsetHours);
planFactPredict.Fact.Day = (planFactPredict.Fact.DateStart - dateStart).TotalDays;
planFactPredict.Fact.NptHours = nptHours;
+ iLastFact = i;
}
- tvd.Add(planFactPredict);
- if ((plan is not null) && (fact is not null))
- iLastMatch = i;
- if (fact is not null)
- iLastFact = i;
+ tvd.Add(planFactPredict);
}
- if (iLastMatch == 0 || iLastMatch == merged.Count - 1)
+ if (iLastMatch is null || iLastMatch == merged.Count - 1)
return tvd;
- var lastMatchPlan = merged[iLastMatch].Item1;
+ var lastMatchPlan = merged[iLastMatch.Value].Plan!;
var lastMatchPlanOperationEnd = lastMatchPlan.DateStart.AddHours(lastMatchPlan.DurationHours);
- var lastFact = merged[iLastFact].Item2;
+ var lastFact = merged[iLastFact].Fact!;
var lastFactDateEnd = lastFact.DateStart.AddHours(lastFact.DurationHours);
var startOffset = lastFactDateEnd - lastMatchPlanOperationEnd;
- for (int i = iLastMatch + 1; i < merged.Count; i++)
+ for (int i = iLastMatch.Value + 1; i < merged.Count; i++)
{
- if (merged[i].Item1 is null)
+ if (merged[i].Plan is null)
continue;
- tvd[i].Predict = Convert(merged[i].Item1, tzOffsetHours);
- tvd[i].Predict.IdType = 2;
- tvd[i].Predict.DateStart = tvd[i].Predict.DateStart + startOffset;
- tvd[i].Predict.Day = (tvd[i].Predict.DateStart - dateStart).TotalDays;
+ var predict = Convert(merged[i].Plan!, tzOffsetHours);
+ predict.IdType = 2;
+ predict.DateStart = predict.DateStart + startOffset;
+ predict.Day = (predict.DateStart - dateStart).TotalDays;
+ tvd[i].Predict = predict;
}
return tvd;
}
- private static List> MergeArraysBySections(
+ private static IEnumerable<(WellOperation? Plan, WellOperation? Fact)> MergeArraysBySections(
IEnumerable sectionsIds,
IOrderedEnumerable wellOperationsPlan,
IOrderedEnumerable wellOperationsFact)
{
- var merged = new List>(wellOperationsPlan.Count());
+ var merged = new List<(WellOperation? Plan, WellOperation? Fact)>(wellOperationsPlan.Count());
foreach (var sectionId in sectionsIds)
{
var sectionOperationsPlan = wellOperationsPlan
@@ -501,46 +507,38 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return merged;
}
- private static List> MergeArrays(IEnumerable operationsPlan, IEnumerable operationsFact)
+ private static IEnumerable<(WellOperation? Plan, WellOperation? Fact)> MergeArrays(IEnumerable operationsPlan, IEnumerable operationsFact)
{
- var result = new List>();
+ var operationsFactWithNoPlan = operationsFact.Where(x => x.IdPlan == null).ToArray();
+ var operationsFactWithPlan = operationsFact.Where(x => x.IdPlan != null).ToArray();
- var oparationsFactWithNoPlan = operationsFact
- .Where(x => x.IdPlan == null)
- .Select(x => new Tuple(null, x));
+ var idsPlanWithFact = operationsFact.Where(x => x.IdPlan is not null).Select(x => x.IdPlan).Distinct();
+ var operationsPlanWithNoFact = operationsPlan.Where(x => !idsPlanWithFact.Contains(x.IdPlan)).ToArray();
- var oparationsFactWithPlan = operationsFact
- .Where(x => x.IdPlan != null)
- .Select(x => new Tuple(x.OperationPlan, x));
+ var result = new List<(WellOperation? Plan, WellOperation? Fact)>(operationsFactWithNoPlan.Length + operationsFactWithPlan.Length + operationsPlanWithNoFact.Length);
- var idsPlanWithFact = operationsFact
- .Where(x => x.IdPlan is not null)
- .Select(x => x.IdPlan)
- .Distinct();
- var oparationsPlanWithNoFact = operationsPlan
- .Where(x => !idsPlanWithFact.Contains(x.IdPlan))
- .Select(x => new Tuple(x, null));
+ foreach (var operation in operationsFactWithPlan)
+ result.Add((operation.OperationPlan, operation));
- result.AddRange(oparationsFactWithNoPlan);
- result.AddRange(oparationsFactWithPlan);
- result.AddRange(oparationsPlanWithNoFact);
+ foreach (var operation in operationsFactWithNoPlan)
+ result.Add((null, operation));
- result = result
- .OrderBy(x => x.Item1?.DateStart)
- .ThenBy(x => x.Item2?.DateStart)
- .ToList();
- return result;
+ foreach (var operation in operationsPlanWithNoFact)
+ result.Add((operation, null));
+
+ return result
+ .OrderBy(x => x.Plan?.DateStart)
+ .ThenBy(x => x.Fact?.DateStart);
}
private static WellOperationDto Convert(WellOperation source, double tzOffsetHours)
{
- if (source is null)
- return null;
- var dest = source.Adapt();
- dest.CategoryName = source.OperationCategory?.Name;
- dest.WellSectionTypeName = source.WellSectionType?.Caption;
- dest.DateStart = source.DateStart.ToRemoteDateTime(tzOffsetHours);
- return dest;
+ var destination = source.Adapt();
+ destination.CategoryName = source.OperationCategory?.Name;
+ destination.WellSectionTypeName = source.WellSectionType?.Caption;
+ destination.DateStart = source.DateStart.ToRemoteDateTime(tzOffsetHours);
+ return destination;
}
}
+#nullable disable
}
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/Race.cs b/AsbCloudInfrastructure/Services/WellOperationService/Race.cs
index e279111d..182ac88d 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/Race.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationService/Race.cs
@@ -1,6 +1,7 @@
using AsbCloudDb.Model;
using System;
using System.Collections.Generic;
+using System.Linq;
namespace AsbCloudInfrastructure.Services.WellOperationService
{
@@ -60,7 +61,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
///
/// Список операций за рейс
///
- public List? Operations { get; internal set; }
+ public List Operations { get; internal set; } = new List();
}
#nullable disable
}
diff --git a/AsbCloudWebApi/Controllers/OperationStatController.cs b/AsbCloudWebApi/Controllers/OperationStatController.cs
index cce509fb..d32ea4b7 100644
--- a/AsbCloudWebApi/Controllers/OperationStatController.cs
+++ b/AsbCloudWebApi/Controllers/OperationStatController.cs
@@ -9,6 +9,7 @@ using System.Threading.Tasks;
namespace AsbCloudWebApi.Controllers
{
+#nullable enable
///
/// Статистика по операциям (заведенным вручную) на скважине
///
@@ -41,7 +42,7 @@ namespace AsbCloudWebApi.Controllers
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
return Forbid();
- var result = await operationsStatService.GetRopStatAsync(
+ var result = await operationsStatService.GetOrDefaultRopStatAsync(
idWell, token).ConfigureAwait(false);
return Ok(result);
@@ -64,7 +65,7 @@ namespace AsbCloudWebApi.Controllers
if (idWell is null)
return NoContent();
- var result = await operationsStatService.GetRopStatAsync(
+ var result = await operationsStatService.GetOrDefaultRopStatAsync(
(int)idWell, token).ConfigureAwait(false);
return Ok(result);
@@ -87,7 +88,7 @@ namespace AsbCloudWebApi.Controllers
if (idCompany is null)
return Forbid();
- var result = await operationsStatService.GetStatClusterAsync(idCluster, idCompany.Value, token)
+ var result = await operationsStatService.GetOrDefaultStatClusterAsync(idCluster, idCompany.Value, token)
.ConfigureAwait(false);
return Ok(result);
}
@@ -132,7 +133,7 @@ namespace AsbCloudWebApi.Controllers
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
return Forbid();
- var result = await operationsStatService.GetWellStatAsync(idWell, token)
+ var result = await operationsStatService.GetOrDefaultWellStatAsync(idWell, token)
.ConfigureAwait(false);
return Ok(result);
}
@@ -165,4 +166,5 @@ namespace AsbCloudWebApi.Controllers
idWell, token).ConfigureAwait(false);
}
}
+#nullable disable
}
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index ae1943a6..c5174f2c 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -378,7 +378,7 @@ namespace AsbCloudWebApi.Controllers
[Route("template")]
[AllowAnonymous]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
- public IActionResult GetTamplate()
+ public IActionResult GetTemplate()
{
var stream = wellOperationImportService.GetExcelTemplateStream();
var fileName = "ЕЦП_шаблон_файла_операций.xlsx";
diff --git a/AsbCloudWebApi/Rest/OperationStat.http b/AsbCloudWebApi/Rest/OperationStat.http
new file mode 100644
index 00000000..975f54b5
--- /dev/null
+++ b/AsbCloudWebApi/Rest/OperationStat.http
@@ -0,0 +1,46 @@
+@baseUrl = http://127.0.0.1:5000
+@contentType = application/json
+@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE
+
+@uid = 20210910_012752700
+@idCluster = 1
+@idWell = 1
+#295
+
+# https://marketplace.visualstudio.com/items?itemName=humao.rest-client
+
+###
+GET {{baseUrl}}/api/well/{{idWell}}/ropStat
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+###
+GET {{baseUrl}}/api/telemetry/{{uid}}/ropStat
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+###
+GET {{baseUrl}}/api/cluster/{{idCluster}}/stat
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+###
+GET {{baseUrl}}/api/wellsStats?idWells=1&idWells={{idWell}}
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+###
+GET {{baseUrl}}/api/well/{{idWell}}/stat
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+###
+GET {{baseUrl}}/api/well/{{idWell}}/tvd
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}