From 4f2bc9244ef2b29c60c542f71c19135276af7506 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 12 Feb 2024 16:55:50 +0500 Subject: [PATCH 01/13] =?UTF-8?q?=D0=9F=D0=BE=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=A0=D0=A2=D0=9A-=D0=BE=D1=82?= =?UTF-8?q?=D1=87=D0=B5=D1=82=D0=B0=20=D0=BD=D0=B0=20=D0=BE=D1=81=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=B4=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D1=85=20t=5Fdata=5Fsaub=5Fstat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/LimitingParameterDto.cs | 24 ++ .../Repositories/IDataSaubStatRepository.cs | 8 + AsbCloudApp/Requests/DataSaubStatRequest.cs | 33 ++ .../IProcessMapReportDataSaubStatService.cs | 26 ++ AsbCloudInfrastructure/DependencyInjection.cs | 2 + .../Repository/DataSaubStatRepository.cs | 13 + .../Services/LimitingParameterService.cs | 10 +- .../ProcessMapReportDataSaubStatService.cs | 318 ++++++++++++++++++ .../ProcessMapWellDrillingController.cs | 32 +- 9 files changed, 448 insertions(+), 18 deletions(-) create mode 100644 AsbCloudApp/Requests/DataSaubStatRequest.cs create mode 100644 AsbCloudApp/Services/ProcessMaps/WellDrilling/IProcessMapReportDataSaubStatService.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs diff --git a/AsbCloudApp/Data/LimitingParameterDto.cs b/AsbCloudApp/Data/LimitingParameterDto.cs index b4f43a09..73a8a5b7 100644 --- a/AsbCloudApp/Data/LimitingParameterDto.cs +++ b/AsbCloudApp/Data/LimitingParameterDto.cs @@ -8,6 +8,30 @@ namespace AsbCloudApp.Data /// public class LimitingParameterDto { + /// + /// Нет ограничения + /// + public static int NoLimit = 0; + + /// + /// МСП + /// + public static int RopPlan = 1; + + /// + /// Давление + /// + public static int Pressure = 2; + + /// + /// Осевая нагрузка + /// + public static int AxialLoad = 3; + + /// + /// Момент + /// + public static int RotorTorque = 4; /// /// Идентификатор скважины /// diff --git a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs index efab95b7..d03554ea 100644 --- a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs +++ b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs @@ -10,6 +10,14 @@ namespace AsbCloudApp.Repositories /// public interface IDataSaubStatRepository { + /// + /// Получение записей по ключу телеметрии + /// + /// ключ телеметрии + /// + /// + Task> GetAsync(int idTelemetry, CancellationToken token); + /// /// Получение последних по дате окончания бурения записей в разрезе телеметрий /// diff --git a/AsbCloudApp/Requests/DataSaubStatRequest.cs b/AsbCloudApp/Requests/DataSaubStatRequest.cs new file mode 100644 index 00000000..78bedc14 --- /dev/null +++ b/AsbCloudApp/Requests/DataSaubStatRequest.cs @@ -0,0 +1,33 @@ +namespace AsbCloudApp.Requests +{ + /// + /// Параметры запроса для построения отчёта + /// + public class DataSaubStatRequest + { + /// + /// Изменение уставки факт перепада давления от первого значения в начале интервала + /// + public double DeltaPressure { get; set; } + + /// + /// Изменение уставки факт осевой нагрузки от первого значения в начале интервала + /// + public double DeltaAxialLoad { get; set; } + + /// + /// Изменение уставки момента от первого значения в начале интервала + /// + public double DeltaRotorTorque { get; set; } + + /// + /// Изменение ограничения нагрузки от первого значения в начале интервала + /// + public double DeltaAxialLoadSp => 1.0; + + /// + /// Изменение ограничения момента от первого значения в начале интервала + /// + public double DeltaRotorTorqueSp => 5.0; + } +} diff --git a/AsbCloudApp/Services/ProcessMaps/WellDrilling/IProcessMapReportDataSaubStatService.cs b/AsbCloudApp/Services/ProcessMaps/WellDrilling/IProcessMapReportDataSaubStatService.cs new file mode 100644 index 00000000..d234cd2f --- /dev/null +++ b/AsbCloudApp/Services/ProcessMaps/WellDrilling/IProcessMapReportDataSaubStatService.cs @@ -0,0 +1,26 @@ +using AsbCloudApp.Data.ProcessMaps.Report; +using AsbCloudApp.Requests; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services.ProcessMaps.WellDrilling +{ + /// + /// Получить РТК-отчет по бурению + /// + public interface IProcessMapReportDataSaubStatService + { + /// + /// Получения строк РТК-отчёта + /// + /// ключ скважины + /// параметры запроса + /// + /// + Task> GetAsync(int idWell, DataSaubStatRequest request, CancellationToken token); + } +} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 5b131299..e940e12a 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -228,6 +228,8 @@ namespace AsbCloudInfrastructure IChangeLogRepository, ProcessMapPlanBaseRepository>(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs index 92a228d8..3e18e42e 100644 --- a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs +++ b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs @@ -40,6 +40,19 @@ namespace AsbCloudInfrastructure.Repository return result; } + public async Task> GetAsync(int idTelemetry, CancellationToken token) + { + var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours); + + var stats = await db.Set() + .Where(s => s.IdTelemetry == idTelemetry) + .ToArrayAsync(token); + + var result = stats.Select(s => ConvertToDto(s, timeSpan)); + + return result; + } + public async Task InsertRangeAsync(IEnumerable dataSaubStats, CancellationToken token) { var entities = dataSaubStats.Select(data => ConvertToEntity(data)); diff --git a/AsbCloudInfrastructure/Services/LimitingParameterService.cs b/AsbCloudInfrastructure/Services/LimitingParameterService.cs index 695321de..c4323597 100644 --- a/AsbCloudInfrastructure/Services/LimitingParameterService.cs +++ b/AsbCloudInfrastructure/Services/LimitingParameterService.cs @@ -17,11 +17,11 @@ namespace AsbCloudInfrastructure.Services private readonly IWellService wellService; private readonly Dictionary feedRegulatorData = new () { - { 0, "Нет ограничения" }, - { 1, "МСП" }, - { 2, "Давление" }, - { 3, "Осевая нагрузка" }, - { 4, "Момент" } + { LimitingParameterDto.NoLimit, "Нет ограничения" }, + { LimitingParameterDto.RopPlan, "МСП" }, + { LimitingParameterDto.Pressure, "Давление" }, + { LimitingParameterDto.AxialLoad, "Осевая нагрузка" }, + { LimitingParameterDto.RotorTorque, "Момент" } }; public LimitingParameterService(ILimitingParameterRepository limitingParameterRepository, diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs new file mode 100644 index 00000000..93751e36 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -0,0 +1,318 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMapPlan; +using AsbCloudApp.Data.ProcessMaps.Report; +using AsbCloudApp.Exceptions; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudApp.Services.ProcessMaps.WellDrilling; +using AsbCloudDb.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services.ProcessMaps.Report +{ + public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStatService + { + private readonly IWellService wellService; + private readonly IChangeLogRepository processMapPlanBaseRepository; + private readonly IDataSaubStatRepository dataSaubStatRepository; + private readonly IWellOperationRepository wellOperationRepository; + + public ProcessMapReportDataSaubStatService(IWellService wellService, + IChangeLogRepository processMapPlanBaseRepository, + IDataSaubStatRepository dataSaubStatRepository, + IWellOperationRepository wellOperationRepository + ) + { + this.wellService = wellService; + this.processMapPlanBaseRepository = processMapPlanBaseRepository; + this.dataSaubStatRepository = dataSaubStatRepository; + this.wellOperationRepository = wellOperationRepository; + } + + public async Task> GetAsync(int idWell, DataSaubStatRequest request, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(idWell, token) + ?? throw new ArgumentInvalidException(nameof(idWell), $"Скважина с Id: {idWell} не найдена"); + + if (!well.IdTelemetry.HasValue) + return Enumerable.Empty(); + + var requestProcessMapPlan = new ProcessMapPlanBaseRequestWithWell(idWell); + var processMapPlanWellDrillings = await processMapPlanBaseRepository.Get(requestProcessMapPlan, token); + + if (!processMapPlanWellDrillings.Any()) + return Enumerable.Empty(); + + var dataSaubStats = + (await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, token)).ToArray(); + + if (!dataSaubStats.Any()) + return Enumerable.Empty(); + + var requestWellOperationFact = new WellOperationRequest() + { + IdWell = idWell, + OperationType = WellOperation.IdOperationTypeFact + }; + var wellOperations = await wellOperationRepository + .GetAsync(requestWellOperationFact, token); + if (!wellOperations.Any()) + return Enumerable.Empty(); + + var timeZone = TimeSpan.FromHours(wellService.GetTimezone(idWell).Hours); + var result = CalcByIntervals(request, processMapPlanWellDrillings, dataSaubStats, wellOperations, timeZone); + + return result; + } + + private IEnumerable CalcByIntervals( + DataSaubStatRequest request, + IEnumerable processMapPlanWellDrillings, + Span dataSaubStats, + IEnumerable wellOperations, + TimeSpan timeZone + ) + { + var list = new List(); + var firstElemInInterval = dataSaubStats[0]; + + var indexStart = 0; + for (var i = 1; i < dataSaubStats.Length; i++) + { + var currentElem = dataSaubStats[i]; + if (IsNewInterval(currentElem, firstElemInInterval, request) || i == dataSaubStats.Length - 1) + { + var length = i - indexStart; + var elem = CalcStat(processMapPlanWellDrillings, dataSaubStats, indexStart, length, wellOperations, timeZone); + if (elem != null) + list.Add(elem); + + indexStart = i; + firstElemInInterval = currentElem; + } + } + return list; + } + + private ProcessMapReportDataSaubStatDto? CalcStat( + IEnumerable processMapPlanDrillingDtos, + Span dataSaubStats, + int indexStart, + int length, + IEnumerable wellOperations, + TimeSpan timeZone + ) + { + var span = dataSaubStats.Slice(indexStart, length); + var firstElemInInterval = span[0]; + var lastElemInInterval = span[^1]; + + var nearestOperation = wellOperations?.MinBy(o => firstElemInInterval.DateStart - o.DateStart); + if (nearestOperation is null) + return null; + + var processMapPlanFilteredByDepth = processMapPlanDrillingDtos + .Where(x => x.IdWellSectionType == nearestOperation.IdWellSectionType) + .Where(x => x.DepthStart >= firstElemInInterval.DepthStart) + .Where(x => x.DepthEnd <= lastElemInInterval.DepthEnd) + .ToArray(); + if (!processMapPlanFilteredByDepth.Any()) + return null; + + var deltaDepth = lastElemInInterval.DepthEnd - firstElemInInterval.DepthStart; + var drilledTime = (lastElemInInterval.DateEnd - firstElemInInterval.DateStart).TotalHours; + + var aggregatedValues = CalcAggregate(span); + + return new ProcessMapReportDataSaubStatDto() + { + DateStart = firstElemInInterval.DateStart.ToOffset(timeZone).DateTime, + WellSectionTypeName = nearestOperation.WellSectionTypeName ?? string.Empty, + DepthStart = firstElemInInterval.DepthStart, + DepthEnd = lastElemInInterval.DepthEnd, + DeltaDepth = deltaDepth, + DrilledTime = drilledTime, + DrillingMode = nearestOperation.CategoryName ?? string.Empty, + PressureDiff = new ProcessMapReportDataSaubStatParamsDto() + { + SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.DeltaPressurePlan), + SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.DeltaPressurePlan), + SetpointFact = firstElemInInterval.PressureSp - firstElemInInterval.PressureIdle, + FactWavg = aggregatedValues.Pressure, + Limit = processMapPlanFilteredByDepth.Max(p => p.DeltaPressureLimitMax), + SetpointUsage = aggregatedValues.SetpointUsagePressure + }, + AxialLoad = new ProcessMapReportDataSaubStatParamsDto() + { + SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.AxialLoadPlan), + SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.AxialLoadPlan), + SetpointFact = aggregatedValues.AxialLoadSp, + FactWavg = aggregatedValues.AxialLoad, + Limit = processMapPlanFilteredByDepth.Max(p => p.AxialLoadLimitMax), + SetpointUsage = aggregatedValues.SetpointUsageAxialLoad + }, + TopDriveTorque = new ProcessMapReportDataSaubStatParamsDto() + { + SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.TopDriveTorquePlan), + SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.TopDriveTorquePlan), + SetpointFact = aggregatedValues.RotorTorqueSp, + FactWavg = aggregatedValues.RotorTorque, + FactMax = aggregatedValues.RotorTorqueMax, + Limit = processMapPlanFilteredByDepth.Max(p => p.TopDriveTorqueLimitMax), + SetpointUsage = aggregatedValues.SetpointUsageRotorTorque + }, + SpeedLimit = new ProcessMapReportDataSaubStatParamsDto + { + SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.RopPlan), + SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.RopPlan), + SetpointFact = aggregatedValues.BlockSpeedSp, + FactWavg = deltaDepth / drilledTime, + SetpointUsage = aggregatedValues.SetpointUsageRopPlan + }, + Turnover = new ProcessMapReportDataSaubStatParamsDto + { + SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.TopDriveSpeedPlan), + SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.TopDriveSpeedPlan), + FactWavg = aggregatedValues.RotorSpeed, + FactMax = aggregatedValues.RotorSpeedMax + }, + Flow = new ProcessMapReportDataSaubStatParamsDto + { + SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.FlowPlan), + SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.FlowPlan), + FactWavg = aggregatedValues.MaxFlow, + Limit = processMapPlanFilteredByDepth.Max(p => p.FlowLimitMax), + }, + Rop = new PlanFactDto + { + Plan = CalcRopPlan(processMapPlanFilteredByDepth), + Fact = deltaDepth / drilledTime + }, + }; + } + + private ( + double Pressure, + double AxialLoadSp, + double AxialLoad, + double RotorTorqueSp, + double RotorTorque, + double RotorTorqueMax, + double BlockSpeedSp, + double RotorSpeed, + double RotorSpeedMax, + double MaxFlow, + double SetpointUsagePressure, + double SetpointUsageAxialLoad, + double SetpointUsageRotorTorque, + double SetpointUsageRopPlan + ) CalcAggregate(Span span) + { + var sumPressure = 0.0; + var sumAxialLoadSp = 0.0; + var sumAxialLoad = 0.0; + var sumRotorTorqueSp = 0.0; + var sumRotorTorque = 0.0; + var sumBlockSpeedSp = 0.0; + var sumRotorSpeed = 0.0; + var maxFlow = 0.0; + var maxRotorTorque = 0.0; + var maxRotorSpeed = 0.0; + var sumDiffDepthByPressure = 0.0; + var sumDiffDepthByAxialLoad = 0.0; + var sumDiffDepthByRotorTorque = 0.0; + var sumDiffDepthByRopPlan = 0.0; + + var diffDepthTotal = 0.0; + for (var i = 0; i < span.Length; i++) + { + var diffDepth = span[i].DepthEnd - span[i].DepthStart; + + sumPressure += diffDepth * span[i].Pressure; + sumAxialLoadSp += diffDepth * (span[i].AxialLoadSp ?? 0); + sumAxialLoad += diffDepth * span[i].AxialLoad; + sumRotorTorqueSp += diffDepth * (span[i].RotorTorqueSp ?? 0); + sumRotorTorque += diffDepth * span[i].RotorTorque; + sumBlockSpeedSp += diffDepth * (span[i].BlockSpeedSp ?? 0); + sumRotorSpeed += diffDepth * span[i].RotorSpeed; + maxFlow = span[i].Flow > maxFlow ? span[i].Flow : maxFlow; + maxRotorTorque = span[i].RotorTorque > maxRotorTorque ? span[i].RotorTorque : maxRotorTorque; + maxRotorSpeed = span[i].RotorSpeed > maxRotorSpeed ? span[i].RotorSpeed : maxRotorSpeed; + + if (span[i].IdFeedRegulator == LimitingParameterDto.Pressure) + sumDiffDepthByPressure += span[i].DepthEnd - span[i].DepthStart; + if (span[i].IdFeedRegulator == LimitingParameterDto.AxialLoad) + sumDiffDepthByAxialLoad += span[i].DepthEnd - span[i].DepthStart; + if (span[i].IdFeedRegulator == LimitingParameterDto.RotorTorque) + sumDiffDepthByRotorTorque += span[i].DepthEnd - span[i].DepthStart; + if (span[i].IdFeedRegulator == LimitingParameterDto.RopPlan) + sumDiffDepthByRopPlan += span[i].DepthEnd - span[i].DepthStart; + + diffDepthTotal += diffDepth; + + + } + return ( + Pressure: sumPressure / diffDepthTotal, + AxialLoadSp: sumAxialLoadSp / diffDepthTotal, + AxialLoad: sumAxialLoad / diffDepthTotal, + RotorTorqueSp: sumRotorTorqueSp / diffDepthTotal, + RotorTorque: sumRotorTorque / diffDepthTotal, + RotorTorqueMax: maxRotorTorque, + BlockSpeedSp: sumBlockSpeedSp / diffDepthTotal, + RotorSpeed: sumRotorSpeed / diffDepthTotal, + RotorSpeedMax: maxRotorSpeed, + MaxFlow: maxFlow, + SetpointUsagePressure: sumDiffDepthByPressure / diffDepthTotal, + SetpointUsageAxialLoad: sumDiffDepthByAxialLoad / diffDepthTotal, + SetpointUsageRotorTorque: sumDiffDepthByRotorTorque / diffDepthTotal, + SetpointUsageRopPlan: sumDiffDepthByRopPlan / diffDepthTotal + ); + } + + private double CalcRopPlan(ProcessMapPlanDrillingDto[] processMapPlanFilteredByDepth) + { + var sumRopPlan = 0.0; + var diffDepthTotal = 0.0; + + for (var i = 0; i < processMapPlanFilteredByDepth.Length; i++) + { + var diffDepth = processMapPlanFilteredByDepth[i].DepthEnd - processMapPlanFilteredByDepth[i].DepthStart; + sumRopPlan += diffDepth * processMapPlanFilteredByDepth[i].RopPlan; + diffDepthTotal += diffDepth; + } + return sumRopPlan / diffDepthTotal; + } + + private bool IsNewInterval(DataSaubStatDto currentElem, DataSaubStatDto firstElem, DataSaubStatRequest request) + { + bool isNewElemBySpeed(double currentSpeed, double firstSpeed) + { + //2. Изменение уставки скорости подачи от первого значения в начале интервала при условии: + //скорость > 80 м/ч => изменение уставки на ± 20 м/ч; + //скорость > 30 м/ч => изменение уставки на ± 15 м/ч; + //скорость <= 30 м/ч => изменение уставки на ± 5 м/ч; + if (firstSpeed > 80) + return Math.Abs(currentSpeed - firstSpeed) >= 20; + else if (firstSpeed > 30) + return Math.Abs(currentSpeed - firstSpeed) >= 15; + else + return Math.Abs(currentSpeed - firstSpeed) >= 5; + } + + var isNewElem = (currentElem.IdCategory != firstElem.IdCategory) + || (Math.Abs(currentElem.Pressure - firstElem.Pressure) >= request.DeltaPressure) + || (Math.Abs(currentElem.AxialLoad - firstElem.AxialLoad) >= request.DeltaAxialLoad) + || (Math.Abs(currentElem.RotorTorque - firstElem.RotorTorque) >= request.DeltaRotorTorque) + || (Math.Abs((currentElem.AxialLoadSp ?? 0) - (firstElem.AxialLoadSp ?? 0)) >= request.DeltaAxialLoadSp) + || (Math.Abs((currentElem.RotorTorqueSp ?? 0) - (firstElem.RotorTorqueSp ?? 0)) >= request.DeltaRotorTorqueSp) + || (isNewElemBySpeed(currentElem.Speed, firstElem.Speed)); + return isNewElem; + } + } +} diff --git a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapWellDrillingController.cs b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapWellDrillingController.cs index 538303a8..94f99db6 100644 --- a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapWellDrillingController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapWellDrillingController.cs @@ -1,11 +1,8 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using AsbCloudApp.Data; +using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMaps; +using AsbCloudApp.Data.ProcessMaps.Report; using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudApp.Services.ProcessMaps; using AsbCloudApp.Services.ProcessMaps.WellDrilling; @@ -14,6 +11,11 @@ using AsbCloudWebApi.SignalR.Clients; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Threading; +using System.Threading.Tasks; namespace AsbCloudWebApi.Controllers.ProcessMaps; @@ -23,6 +25,7 @@ namespace AsbCloudWebApi.Controllers.ProcessMaps; public class ProcessMapWellDrillingController : ProcessMapBaseController { private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingService; + private readonly IProcessMapReportDataSaubStatService processMapReportDataSaubStatService; private readonly IProcessMapReportWellDrillingExportService processMapReportWellDrillingExportService; private readonly IProcessMapPlanImportService processMapPlanImportService; @@ -33,7 +36,8 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController wellSectionRepository, IHubContext telemetryHubContext, ITelemetryService telemetryService, @@ -42,6 +46,7 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController /// Id + /// параметры запроса /// /// [HttpGet("report")] - [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - public async Task GetReportAsync(int idWell, CancellationToken cancellationToken) + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetReportAsync(int idWell, DataSaubStatRequest request, CancellationToken cancellationToken) { - var report = await processMapReportWellDrillingService.GetAsync(idWell, cancellationToken); + var report = await processMapReportDataSaubStatService.GetAsync(idWell, request, cancellationToken); return Ok(report); } @@ -89,9 +95,9 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController [HttpPost("import/{options}")] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - public async Task ImportAsync(int idWell, - int options, - [Required] IFormFile file, + public async Task ImportAsync(int idWell, + int options, + [Required] IFormFile file, CancellationToken cancellationToken) { await AssertUserHasAccessToEditProcessMapAsync(idWell, cancellationToken); From 0fdb1ede72342d6ffa0de14cdbb1d73d4edcd45f Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Tue, 13 Feb 2024 16:35:01 +0500 Subject: [PATCH 02/13] =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/LimitingParameterDto.cs | 10 +- .../Report/ProcessMapReportDataSaubStatDto.cs | 98 +++++++++++++++++ AsbCloudApp/Extensions/ChangeLogExtensions.cs | 32 ++++++ .../Repositories/IDataSaubStatRepository.cs | 4 +- AsbCloudApp/Requests/DataSaubStatRequest.cs | 20 +++- .../Repository/DataSaubStatRepository.cs | 4 +- .../ProcessMapReportDataSaubStatService.cs | 104 +++++++++++------- 7 files changed, 217 insertions(+), 55 deletions(-) create mode 100644 AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs create mode 100644 AsbCloudApp/Extensions/ChangeLogExtensions.cs diff --git a/AsbCloudApp/Data/LimitingParameterDto.cs b/AsbCloudApp/Data/LimitingParameterDto.cs index 73a8a5b7..19b182a5 100644 --- a/AsbCloudApp/Data/LimitingParameterDto.cs +++ b/AsbCloudApp/Data/LimitingParameterDto.cs @@ -11,27 +11,27 @@ namespace AsbCloudApp.Data /// /// Нет ограничения /// - public static int NoLimit = 0; + public const int NoLimit = 0; /// /// МСП /// - public static int RopPlan = 1; + public const int RopPlan = 1; /// /// Давление /// - public static int Pressure = 2; + public const int Pressure = 2; /// /// Осевая нагрузка /// - public static int AxialLoad = 3; + public const int AxialLoad = 3; /// /// Момент /// - public static int RotorTorque = 4; + public const int RotorTorque = 4; /// /// Идентификатор скважины /// diff --git a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs new file mode 100644 index 00000000..abcef62b --- /dev/null +++ b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs @@ -0,0 +1,98 @@ +using System; + +namespace AsbCloudApp.Data.ProcessMaps.Report; + +/// +/// Модель РТК +/// +public class ProcessMapReportDataSaubStatDto +{ + /// + /// Время, затраченное на бурение интервала, в часах + /// + public double DrilledTime { get; set; } = 0; + + /// + /// Идентификатор скважины + /// + public int IdWell { get; set; } + + /// + /// Id секции скважины + /// + public int IdWellSectionType { get; set; } + + /// + /// Название секции скважины + /// + public string WellSectionTypeName { get; set; } = null!; + + /// + /// Глубина по стволу от, м + /// + /// на начало интервала + /// + /// + public double DepthStart { get; set; } + + /// + /// Глубина по стволу до, м + /// + /// на конец интервала + /// + /// + public double DepthEnd { get; set; } + + /// + /// Дата/ время + /// + /// на начало интервала + /// + /// + public DateTime DateStart { get; set; } + + /// + /// Режим бурения (Ротор/слайд/ручной) + /// + public string DrillingMode { get; set; } = null!; + + /// + /// Проходка, м + /// + public double? DeltaDepth { get; set; } + + /// + /// Перепад давления, атм + /// + public ProcessMapReportDataSaubStatParamsDto PressureDiff { get; set; } = new(); + + /// + /// Нагрузка, т + /// + public ProcessMapReportDataSaubStatParamsDto AxialLoad { get; set; } = new(); + + /// + /// Момент на ВСП, кНхМ + /// + public ProcessMapReportDataSaubStatParamsDto TopDriveTorque { get; set; } = new(); + + /// + /// Ограничение скорости, м/ч + /// + public ProcessMapReportDataSaubStatParamsDto SpeedLimit { get; set; } = new(); + + /// + /// Обороты ВСП, об/мин + /// + public ProcessMapReportDataSaubStatParamsDto Turnover { get; set; } = new(); + + /// + /// Расход, л/с + /// + public ProcessMapReportDataSaubStatParamsDto Flow { get; set; } = new(); + + /// + /// Механическая скорость, м/ч + /// + public PlanFactDto Rop { get; set; } = new(); +} \ No newline at end of file diff --git a/AsbCloudApp/Extensions/ChangeLogExtensions.cs b/AsbCloudApp/Extensions/ChangeLogExtensions.cs new file mode 100644 index 00000000..c52e33dd --- /dev/null +++ b/AsbCloudApp/Extensions/ChangeLogExtensions.cs @@ -0,0 +1,32 @@ +using AsbCloudApp.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsbCloudApp.Extensions +{ + /// + /// Расширения для поиска в истории + /// + public static class ChangeLogExtensions + { + /// + /// Действительные на момент времени значения + /// + /// + /// + /// + /// + public static IEnumerable WhereActualAtMoment(this IEnumerable items, DateTimeOffset moment) + where T : ChangeLogAbstract + { + var actualItems = items + .Where(item => item.Creation >= moment) + .Where(item => item.Obsolete is null || item.Obsolete <= moment); + + return actualItems; + } + } +} diff --git a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs index d03554ea..941d6465 100644 --- a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs +++ b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs @@ -14,9 +14,11 @@ namespace AsbCloudApp.Repositories /// Получение записей по ключу телеметрии /// /// ключ телеметрии + /// начальная глубина + /// конечная глубина /// /// - Task> GetAsync(int idTelemetry, CancellationToken token); + Task> GetAsync(int idTelemetry, double geDepth, double leDepth, CancellationToken token); /// /// Получение последних по дате окончания бурения записей в разрезе телеметрий diff --git a/AsbCloudApp/Requests/DataSaubStatRequest.cs b/AsbCloudApp/Requests/DataSaubStatRequest.cs index 78bedc14..b4400f3e 100644 --- a/AsbCloudApp/Requests/DataSaubStatRequest.cs +++ b/AsbCloudApp/Requests/DataSaubStatRequest.cs @@ -1,4 +1,6 @@ -namespace AsbCloudApp.Requests +using System.ComponentModel.DataAnnotations; + +namespace AsbCloudApp.Requests { /// /// Параметры запроса для построения отчёта @@ -7,18 +9,24 @@ { /// /// Изменение уставки факт перепада давления от первого значения в начале интервала + /// Не менее 5 атм и не более 15(50) атм; /// - public double DeltaPressure { get; set; } + [Range(5, 15, ErrorMessage = "Изменение уставки факт перепада давления не может быть меньше 5 и больше 15 атм")] + public double DeltaPressure { get; set; } = 5d; /// - /// Изменение уставки факт осевой нагрузки от первого значения в начале интервала + /// Изменение уставки факт осевой нагрузки от первого значения в начале интервала + /// Не менее 1 т и не более 5(20) т; /// - public double DeltaAxialLoad { get; set; } + [Range(1, 5, ErrorMessage = "Изменение уставки факт осевой нагрузки не может быть меньше 1 и больше 5 т")] + public double DeltaAxialLoad { get; set; } = 1d; /// - /// Изменение уставки момента от первого значения в начале интервала + /// Изменение уставки момента от первого значения в начале интервала + /// Не менее 5 кН*м и не более 10(20) кН*м. /// - public double DeltaRotorTorque { get; set; } + [Range(5, 10, ErrorMessage = "Изменение уставки момента не может быть меньше 5 и больше 10 кН*м")] + public double DeltaRotorTorque { get; set; } = 5d; /// /// Изменение ограничения нагрузки от первого значения в начале интервала diff --git a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs index 3e18e42e..72737a0b 100644 --- a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs +++ b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs @@ -40,12 +40,14 @@ namespace AsbCloudInfrastructure.Repository return result; } - public async Task> GetAsync(int idTelemetry, CancellationToken token) + public async Task> GetAsync(int idTelemetry, double geDepth, double leDepth, CancellationToken token) { var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours); var stats = await db.Set() .Where(s => s.IdTelemetry == idTelemetry) + .Where(s => s.DepthStart >= geDepth) + .Where(s => s.DepthEnd <= leDepth) .ToArrayAsync(token); var result = stats.Select(s => ConvertToDto(s, timeSpan)); diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 93751e36..35bf06a8 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -2,6 +2,7 @@ using AsbCloudApp.Data.ProcessMapPlan; using AsbCloudApp.Data.ProcessMaps.Report; using AsbCloudApp.Exceptions; +using AsbCloudApp.Extensions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; @@ -48,24 +49,30 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report if (!processMapPlanWellDrillings.Any()) return Enumerable.Empty(); - var dataSaubStats = - (await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, token)).ToArray(); - - if (!dataSaubStats.Any()) - return Enumerable.Empty(); + var geDepth = processMapPlanWellDrillings.Min(p => p.DepthStart); + var leDepth = processMapPlanWellDrillings.Max(p => p.DepthEnd); var requestWellOperationFact = new WellOperationRequest() { IdWell = idWell, - OperationType = WellOperation.IdOperationTypeFact + OperationType = WellOperation.IdOperationTypeFact, + GeDepth = geDepth, + LeDepth = leDepth }; var wellOperations = await wellOperationRepository .GetAsync(requestWellOperationFact, token); if (!wellOperations.Any()) return Enumerable.Empty(); - var timeZone = TimeSpan.FromHours(wellService.GetTimezone(idWell).Hours); - var result = CalcByIntervals(request, processMapPlanWellDrillings, dataSaubStats, wellOperations, timeZone); + var dataSaubStats = + (await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, geDepth, leDepth, token)).ToArray(); + + if (!dataSaubStats.Any()) + return Enumerable.Empty(); + + var wellOperationCategories = wellOperationRepository.GetCategories(false); + + var result = CalcByIntervals(request, processMapPlanWellDrillings, dataSaubStats, wellOperations, wellOperationCategories); return result; } @@ -75,7 +82,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report IEnumerable processMapPlanWellDrillings, Span dataSaubStats, IEnumerable wellOperations, - TimeSpan timeZone + IEnumerable wellOperationCategories ) { var list = new List(); @@ -88,56 +95,66 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report if (IsNewInterval(currentElem, firstElemInInterval, request) || i == dataSaubStats.Length - 1) { var length = i - indexStart; - var elem = CalcStat(processMapPlanWellDrillings, dataSaubStats, indexStart, length, wellOperations, timeZone); - if (elem != null) - list.Add(elem); + + var span = dataSaubStats.Slice(indexStart, length); indexStart = i; firstElemInInterval = currentElem; + + var firstElemInSpan = span[0]; + var lastElemInISpan = span[^1]; + + var nearestOperation = wellOperations.MinBy(o => firstElemInSpan.DateStart - o.DateStart); + if (nearestOperation is null) + continue; + + var processMapPlanFilteredByDepth = processMapPlanWellDrillings + .Where(x => x.IdWellSectionType == nearestOperation.IdWellSectionType) + .Where(x => x.DepthStart >= firstElemInSpan.DepthStart) + .Where(x => x.DepthEnd <= lastElemInISpan.DepthEnd) + .WhereActualAtMoment(DateTimeOffset.Now) + .ToArray(); + + if (!processMapPlanFilteredByDepth.Any()) + continue; + + var wellOperationCategoryName = wellOperationCategories. + Where(c => c.Id == currentElem.IdCategory) + .FirstOrDefault() + ?.Name ?? string.Empty; + + var elem = CalcStat(processMapPlanFilteredByDepth, span, nearestOperation, wellOperationCategoryName); + if (elem is not null) + list.Add(elem); } } return list; } private ProcessMapReportDataSaubStatDto? CalcStat( - IEnumerable processMapPlanDrillingDtos, - Span dataSaubStats, - int indexStart, - int length, - IEnumerable wellOperations, - TimeSpan timeZone + ProcessMapPlanDrillingDto[] processMapPlanFilteredByDepth, + Span span, + WellOperationDto nearestOperation, + string wellOperationCategoryName ) { - var span = dataSaubStats.Slice(indexStart, length); var firstElemInInterval = span[0]; var lastElemInInterval = span[^1]; - var nearestOperation = wellOperations?.MinBy(o => firstElemInInterval.DateStart - o.DateStart); - if (nearestOperation is null) - return null; - - var processMapPlanFilteredByDepth = processMapPlanDrillingDtos - .Where(x => x.IdWellSectionType == nearestOperation.IdWellSectionType) - .Where(x => x.DepthStart >= firstElemInInterval.DepthStart) - .Where(x => x.DepthEnd <= lastElemInInterval.DepthEnd) - .ToArray(); - if (!processMapPlanFilteredByDepth.Any()) - return null; - var deltaDepth = lastElemInInterval.DepthEnd - firstElemInInterval.DepthStart; - var drilledTime = (lastElemInInterval.DateEnd - firstElemInInterval.DateStart).TotalHours; + var aggregatedValues = CalcAggregate(span); return new ProcessMapReportDataSaubStatDto() { - DateStart = firstElemInInterval.DateStart.ToOffset(timeZone).DateTime, + DateStart = firstElemInInterval.DateStart.DateTime, WellSectionTypeName = nearestOperation.WellSectionTypeName ?? string.Empty, DepthStart = firstElemInInterval.DepthStart, DepthEnd = lastElemInInterval.DepthEnd, DeltaDepth = deltaDepth, - DrilledTime = drilledTime, - DrillingMode = nearestOperation.CategoryName ?? string.Empty, + DrilledTime = aggregatedValues.DrilledTime, + DrillingMode = wellOperationCategoryName, PressureDiff = new ProcessMapReportDataSaubStatParamsDto() { SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.DeltaPressurePlan), @@ -171,7 +188,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.RopPlan), SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.RopPlan), SetpointFact = aggregatedValues.BlockSpeedSp, - FactWavg = deltaDepth / drilledTime, + FactWavg = deltaDepth / aggregatedValues.DrilledTime, SetpointUsage = aggregatedValues.SetpointUsageRopPlan }, Turnover = new ProcessMapReportDataSaubStatParamsDto @@ -191,7 +208,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report Rop = new PlanFactDto { Plan = CalcRopPlan(processMapPlanFilteredByDepth), - Fact = deltaDepth / drilledTime + Fact = deltaDepth / aggregatedValues.DrilledTime }, }; } @@ -210,7 +227,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report double SetpointUsagePressure, double SetpointUsageAxialLoad, double SetpointUsageRotorTorque, - double SetpointUsageRopPlan + double SetpointUsageRopPlan, + double DrilledTime ) CalcAggregate(Span span) { var sumPressure = 0.0; @@ -229,11 +247,13 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report var sumDiffDepthByRopPlan = 0.0; var diffDepthTotal = 0.0; + var drilledTime = 0.0; + for (var i = 0; i < span.Length; i++) { var diffDepth = span[i].DepthEnd - span[i].DepthStart; - sumPressure += diffDepth * span[i].Pressure; + sumPressure += diffDepth * ((span[i].PressureIdle ?? 0) - span[i].Pressure); sumAxialLoadSp += diffDepth * (span[i].AxialLoadSp ?? 0); sumAxialLoad += diffDepth * span[i].AxialLoad; sumRotorTorqueSp += diffDepth * (span[i].RotorTorqueSp ?? 0); @@ -254,8 +274,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report sumDiffDepthByRopPlan += span[i].DepthEnd - span[i].DepthStart; diffDepthTotal += diffDepth; - - + drilledTime += (span[i].DateEnd - span[i].DateStart).TotalHours; } return ( Pressure: sumPressure / diffDepthTotal, @@ -271,7 +290,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report SetpointUsagePressure: sumDiffDepthByPressure / diffDepthTotal, SetpointUsageAxialLoad: sumDiffDepthByAxialLoad / diffDepthTotal, SetpointUsageRotorTorque: sumDiffDepthByRotorTorque / diffDepthTotal, - SetpointUsageRopPlan: sumDiffDepthByRopPlan / diffDepthTotal + SetpointUsageRopPlan: sumDiffDepthByRopPlan / diffDepthTotal, + DrilledTime: drilledTime ); } From f9d95c4431a112bba15114058cd961a4c2b3ed65 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Tue, 13 Feb 2024 16:42:42 +0500 Subject: [PATCH 03/13] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0=20Pro?= =?UTF-8?q?cessMapReportDataSaubStatParamsDto=20=D0=B2=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B5=D0=BA=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProcessMapReportDataSaubStatParamsDto.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatParamsDto.cs diff --git a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatParamsDto.cs b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatParamsDto.cs new file mode 100644 index 00000000..2029b805 --- /dev/null +++ b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatParamsDto.cs @@ -0,0 +1,42 @@ +namespace AsbCloudApp.Data.ProcessMaps.Report; + +/// +/// Параметры РТК +/// +public class ProcessMapReportDataSaubStatParamsDto +{ + /// + /// Уставка план (максимум) + /// + public double? SetpointPlanMax { get; set; } + + /// + /// Уставка план (минимум) + /// + public double? SetpointPlanMin { get; set; } + + /// + /// Уставка факт + /// + public double? SetpointFact { get; set; } + + /// + /// Факт (средневзвешенное) + /// + public double? FactWavg { get; set; } + + /// + /// Факт (максимум) + /// + public double? FactMax { get; set; } + + /// + /// Ограничение + /// + public double? Limit { get; set; } + + /// + /// Процент бурения по уставке, % + /// + public double? SetpointUsage { get; set; } +} \ No newline at end of file From 3a978bddc57856073965eb323ef800b34d1f0dd6 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 13 Feb 2024 17:29:20 +0500 Subject: [PATCH 04/13] draft 1 --- .../ProcessMapReportDataSaubStatService.cs | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 35bf06a8..b25f2eb8 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -22,17 +22,20 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report private readonly IChangeLogRepository processMapPlanBaseRepository; private readonly IDataSaubStatRepository dataSaubStatRepository; private readonly IWellOperationRepository wellOperationRepository; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; public ProcessMapReportDataSaubStatService(IWellService wellService, IChangeLogRepository processMapPlanBaseRepository, IDataSaubStatRepository dataSaubStatRepository, - IWellOperationRepository wellOperationRepository + IWellOperationRepository wellOperationRepository, + IWellOperationCategoryRepository wellOperationCategoryRepository ) { this.wellService = wellService; this.processMapPlanBaseRepository = processMapPlanBaseRepository; this.dataSaubStatRepository = dataSaubStatRepository; this.wellOperationRepository = wellOperationRepository; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; } public async Task> GetAsync(int idWell, DataSaubStatRequest request, CancellationToken token) @@ -81,19 +84,37 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report DataSaubStatRequest request, IEnumerable processMapPlanWellDrillings, Span dataSaubStats, - IEnumerable wellOperations, - IEnumerable wellOperationCategories + IEnumerable wellOperations ) { var list = new List(); var firstElemInInterval = dataSaubStats[0]; + int GetSection(DataSaubStatDto data) + => wellOperations.MinBy(o => data.DateStart - o.DateStart)!.IdWellSectionType; + + ProcessMapPlanDrillingDto? GetProcessMapPlan(int idWellSectionType, DataSaubStatDto data) + => processMapPlanWellDrillings + .Where(p => p.IdWellSectionType == idWellSectionType) + .Where(p => p.DepthStart <= data.DepthStart) + .Where(p => p.DepthEnd >= data.DepthStart) + .Where(p => IsModeMatchOperationCategory(p.IdMode, data.IdCategory)) + .WhereActualAtMoment(data.DateStart) + .FirstOrDefault(); + + var idWellSectionType = GetSection(firstElemInInterval); + var prevProcessMapPlan = GetProcessMapPlan(idWellSectionType, firstElemInInterval); var indexStart = 0; + for (var i = 1; i < dataSaubStats.Length; i++) { var currentElem = dataSaubStats[i]; - if (IsNewInterval(currentElem, firstElemInInterval, request) || i == dataSaubStats.Length - 1) + idWellSectionType = GetSection(currentElem); + var processMapPlan = GetProcessMapPlan(idWellSectionType, currentElem); + + if (IsNewInterval(currentElem, firstElemInInterval, request) || i == dataSaubStats.Length - 1 || processMapPlan != prevProcessMapPlan) { + prevProcessMapPlan = processMapPlan; var length = i - indexStart; var span = dataSaubStats.Slice(indexStart, length); @@ -104,26 +125,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report var firstElemInSpan = span[0]; var lastElemInISpan = span[^1]; - var nearestOperation = wellOperations.MinBy(o => firstElemInSpan.DateStart - o.DateStart); - if (nearestOperation is null) - continue; - - var processMapPlanFilteredByDepth = processMapPlanWellDrillings - .Where(x => x.IdWellSectionType == nearestOperation.IdWellSectionType) - .Where(x => x.DepthStart >= firstElemInSpan.DepthStart) - .Where(x => x.DepthEnd <= lastElemInISpan.DepthEnd) - .WhereActualAtMoment(DateTimeOffset.Now) - .ToArray(); - - if (!processMapPlanFilteredByDepth.Any()) - continue; - - var wellOperationCategoryName = wellOperationCategories. - Where(c => c.Id == currentElem.IdCategory) - .FirstOrDefault() - ?.Name ?? string.Empty; - - var elem = CalcStat(processMapPlanFilteredByDepth, span, nearestOperation, wellOperationCategoryName); + var elem = CalcStat(processMapPlan, idWellSectionType, span); if (elem is not null) list.Add(elem); } @@ -131,11 +133,15 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report return list; } + private bool IsModeMatchOperationCategory(int idMode, int idCategory) + { + throw new NotImplementedException(); + } + private ProcessMapReportDataSaubStatDto? CalcStat( - ProcessMapPlanDrillingDto[] processMapPlanFilteredByDepth, - Span span, - WellOperationDto nearestOperation, - string wellOperationCategoryName + ProcessMapPlanDrillingDto? processMapPlanFilteredByDepth, + int idWellSectionType, + Span span ) { var firstElemInInterval = span[0]; @@ -149,7 +155,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report return new ProcessMapReportDataSaubStatDto() { DateStart = firstElemInInterval.DateStart.DateTime, - WellSectionTypeName = nearestOperation.WellSectionTypeName ?? string.Empty, + WellSectionTypeName = nearestOperation.WellSectionTypeName ?? string.Empty, DepthStart = firstElemInInterval.DepthStart, DepthEnd = lastElemInInterval.DepthEnd, DeltaDepth = deltaDepth, @@ -157,7 +163,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report DrillingMode = wellOperationCategoryName, PressureDiff = new ProcessMapReportDataSaubStatParamsDto() { - SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.DeltaPressurePlan), + SetpointPlanMax = processMapPlanFilteredByDepth?.DeltaPressurePlan, SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.DeltaPressurePlan), SetpointFact = firstElemInInterval.PressureSp - firstElemInInterval.PressureIdle, FactWavg = aggregatedValues.Pressure, From df0b3555b3161ae1194ed6b51bbeebeb5701116b Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Wed, 14 Feb 2024 10:51:20 +0500 Subject: [PATCH 05/13] =?UTF-8?q?=D0=9C=D0=B8=D0=BD=D0=B8-=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Report/ProcessMapReportDataSaubStatService.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 35bf06a8..27d914a6 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -253,7 +253,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report { var diffDepth = span[i].DepthEnd - span[i].DepthStart; - sumPressure += diffDepth * ((span[i].PressureIdle ?? 0) - span[i].Pressure); + sumPressure += diffDepth * (span[i].Pressure - (span[i].PressureIdle ?? 0.0)); sumAxialLoadSp += diffDepth * (span[i].AxialLoadSp ?? 0); sumAxialLoad += diffDepth * span[i].AxialLoad; sumRotorTorqueSp += diffDepth * (span[i].RotorTorqueSp ?? 0); @@ -265,13 +265,13 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report maxRotorSpeed = span[i].RotorSpeed > maxRotorSpeed ? span[i].RotorSpeed : maxRotorSpeed; if (span[i].IdFeedRegulator == LimitingParameterDto.Pressure) - sumDiffDepthByPressure += span[i].DepthEnd - span[i].DepthStart; + sumDiffDepthByPressure += diffDepth; if (span[i].IdFeedRegulator == LimitingParameterDto.AxialLoad) - sumDiffDepthByAxialLoad += span[i].DepthEnd - span[i].DepthStart; + sumDiffDepthByAxialLoad += diffDepth; if (span[i].IdFeedRegulator == LimitingParameterDto.RotorTorque) - sumDiffDepthByRotorTorque += span[i].DepthEnd - span[i].DepthStart; + sumDiffDepthByRotorTorque += diffDepth; if (span[i].IdFeedRegulator == LimitingParameterDto.RopPlan) - sumDiffDepthByRopPlan += span[i].DepthEnd - span[i].DepthStart; + sumDiffDepthByRopPlan += diffDepth; diffDepthTotal += diffDepth; drilledTime += (span[i].DateEnd - span[i].DateStart).TotalHours; From d5d97acb7d10e80034f875ee5493a7d920a63112 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Wed, 14 Feb 2024 11:33:35 +0500 Subject: [PATCH 06/13] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20-?= =?UTF-8?q?=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProcessMapReportDataSaubStatParamsDto.cs | 9 +-- .../ProcessMapReportDataSaubStatService.cs | 61 +++++++++++-------- .../ProcessMapWellDrillingController.cs | 2 +- 3 files changed, 40 insertions(+), 32 deletions(-) diff --git a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatParamsDto.cs b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatParamsDto.cs index 2029b805..1ed34027 100644 --- a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatParamsDto.cs +++ b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatParamsDto.cs @@ -6,14 +6,9 @@ public class ProcessMapReportDataSaubStatParamsDto { /// - /// Уставка план (максимум) + /// Уставка план /// - public double? SetpointPlanMax { get; set; } - - /// - /// Уставка план (минимум) - /// - public double? SetpointPlanMin { get; set; } + public double? SetpointPlan { get; set; } /// /// Уставка факт diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 2f26c594..cc958a01 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -73,9 +73,16 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report if (!dataSaubStats.Any()) return Enumerable.Empty(); - var wellOperationCategories = wellOperationRepository.GetCategories(false); + var wellOperationCategories = wellOperationCategoryRepository.Get(false); + var wellSectionTypes = wellOperationRepository.GetSectionTypes(); - var result = CalcByIntervals(request, processMapPlanWellDrillings, dataSaubStats, wellOperations, wellOperationCategories); + var result = CalcByIntervals( + request, + processMapPlanWellDrillings, + dataSaubStats, + wellOperations, + wellOperationCategories, + wellSectionTypes); return result; } @@ -84,7 +91,9 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report DataSaubStatRequest request, IEnumerable processMapPlanWellDrillings, Span dataSaubStats, - IEnumerable wellOperations + IEnumerable wellOperations, + IEnumerable wellOperationCategories, + IEnumerable wellSectionTypes ) { var list = new List(); @@ -98,7 +107,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report .Where(p => p.IdWellSectionType == idWellSectionType) .Where(p => p.DepthStart <= data.DepthStart) .Where(p => p.DepthEnd >= data.DepthStart) - .Where(p => IsModeMatchOperationCategory(p.IdMode, data.IdCategory)) + //.Where(p => IsModeMatchOperationCategory(p.IdMode, data.IdCategory)) .WhereActualAtMoment(data.DateStart) .FirstOrDefault(); @@ -125,7 +134,15 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report var firstElemInSpan = span[0]; var lastElemInISpan = span[^1]; - var elem = CalcStat(processMapPlan, idWellSectionType, span); + var wellOperationCategoryName = wellOperationCategories + .Where(c => c.Id == firstElemInSpan.IdCategory) + .FirstOrDefault()?.Name ?? string.Empty; + + var wellSectionTypeName = wellSectionTypes + .Where(c => c.Id == idWellSectionType) + .FirstOrDefault()?.Caption ?? string.Empty; + + var elem = CalcStat(processMapPlan, span, idWellSectionType, wellOperationCategoryName, wellSectionTypeName); if (elem is not null) list.Add(elem); } @@ -140,8 +157,10 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report private ProcessMapReportDataSaubStatDto? CalcStat( ProcessMapPlanDrillingDto? processMapPlanFilteredByDepth, + Span span, int idWellSectionType, - Span span + string wellOperationCategoryName, + string wellSectionTypeName ) { var firstElemInInterval = span[0]; @@ -155,7 +174,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report return new ProcessMapReportDataSaubStatDto() { DateStart = firstElemInInterval.DateStart.DateTime, - WellSectionTypeName = nearestOperation.WellSectionTypeName ?? string.Empty, + WellSectionTypeName = wellSectionTypeName, DepthStart = firstElemInInterval.DepthStart, DepthEnd = lastElemInInterval.DepthEnd, DeltaDepth = deltaDepth, @@ -163,57 +182,51 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report DrillingMode = wellOperationCategoryName, PressureDiff = new ProcessMapReportDataSaubStatParamsDto() { - SetpointPlanMax = processMapPlanFilteredByDepth?.DeltaPressurePlan, - SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.DeltaPressurePlan), + SetpointPlan = processMapPlanFilteredByDepth?.DeltaPressurePlan, SetpointFact = firstElemInInterval.PressureSp - firstElemInInterval.PressureIdle, FactWavg = aggregatedValues.Pressure, - Limit = processMapPlanFilteredByDepth.Max(p => p.DeltaPressureLimitMax), + Limit = processMapPlanFilteredByDepth?.DeltaPressureLimitMax, SetpointUsage = aggregatedValues.SetpointUsagePressure }, AxialLoad = new ProcessMapReportDataSaubStatParamsDto() { - SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.AxialLoadPlan), - SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.AxialLoadPlan), + SetpointPlan = processMapPlanFilteredByDepth?.AxialLoadPlan, SetpointFact = aggregatedValues.AxialLoadSp, FactWavg = aggregatedValues.AxialLoad, - Limit = processMapPlanFilteredByDepth.Max(p => p.AxialLoadLimitMax), + Limit = processMapPlanFilteredByDepth?.AxialLoadLimitMax, SetpointUsage = aggregatedValues.SetpointUsageAxialLoad }, TopDriveTorque = new ProcessMapReportDataSaubStatParamsDto() { - SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.TopDriveTorquePlan), - SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.TopDriveTorquePlan), + SetpointPlan = processMapPlanFilteredByDepth?.TopDriveTorquePlan, SetpointFact = aggregatedValues.RotorTorqueSp, FactWavg = aggregatedValues.RotorTorque, FactMax = aggregatedValues.RotorTorqueMax, - Limit = processMapPlanFilteredByDepth.Max(p => p.TopDriveTorqueLimitMax), + Limit = processMapPlanFilteredByDepth?.TopDriveTorqueLimitMax, SetpointUsage = aggregatedValues.SetpointUsageRotorTorque }, SpeedLimit = new ProcessMapReportDataSaubStatParamsDto { - SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.RopPlan), - SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.RopPlan), + SetpointPlan = processMapPlanFilteredByDepth?.RopPlan, SetpointFact = aggregatedValues.BlockSpeedSp, FactWavg = deltaDepth / aggregatedValues.DrilledTime, SetpointUsage = aggregatedValues.SetpointUsageRopPlan }, Turnover = new ProcessMapReportDataSaubStatParamsDto { - SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.TopDriveSpeedPlan), - SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.TopDriveSpeedPlan), + SetpointPlan = processMapPlanFilteredByDepth?.TopDriveSpeedPlan, FactWavg = aggregatedValues.RotorSpeed, FactMax = aggregatedValues.RotorSpeedMax }, Flow = new ProcessMapReportDataSaubStatParamsDto { - SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.FlowPlan), - SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.FlowPlan), + SetpointPlan = processMapPlanFilteredByDepth?.FlowPlan, FactWavg = aggregatedValues.MaxFlow, - Limit = processMapPlanFilteredByDepth.Max(p => p.FlowLimitMax), + Limit = processMapPlanFilteredByDepth?.FlowLimitMax, }, Rop = new PlanFactDto { - Plan = CalcRopPlan(processMapPlanFilteredByDepth), + //Plan = CalcRopPlan(processMapPlanFilteredByDepth), Fact = deltaDepth / aggregatedValues.DrilledTime }, }; diff --git a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapWellDrillingController.cs b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapWellDrillingController.cs index 94f99db6..857e4a68 100644 --- a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapWellDrillingController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapWellDrillingController.cs @@ -57,7 +57,7 @@ public class ProcessMapWellDrillingController : ProcessMapBaseControllerпараметры запроса /// /// - [HttpGet("report")] + [HttpPost("report")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] public async Task GetReportAsync(int idWell, DataSaubStatRequest request, CancellationToken cancellationToken) { From 08e0a4fb38c326da466af051bd3558b61c024d2c Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Wed, 14 Feb 2024 13:12:25 +0500 Subject: [PATCH 07/13] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20-?= =?UTF-8?q?=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Report/ProcessMapReportDataSaubStatService.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index cc958a01..0dfbf755 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -107,7 +107,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report .Where(p => p.IdWellSectionType == idWellSectionType) .Where(p => p.DepthStart <= data.DepthStart) .Where(p => p.DepthEnd >= data.DepthStart) - //.Where(p => IsModeMatchOperationCategory(p.IdMode, data.IdCategory)) + .Where(p => IsModeMatchOperationCategory(p.IdMode, data.IdCategory)) .WhereActualAtMoment(data.DateStart) .FirstOrDefault(); @@ -142,7 +142,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report .Where(c => c.Id == idWellSectionType) .FirstOrDefault()?.Caption ?? string.Empty; - var elem = CalcStat(processMapPlan, span, idWellSectionType, wellOperationCategoryName, wellSectionTypeName); + var elem = CalcStat(processMapPlan, span, wellOperationCategoryName, wellSectionTypeName); if (elem is not null) list.Add(elem); } @@ -152,13 +152,12 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report private bool IsModeMatchOperationCategory(int idMode, int idCategory) { - throw new NotImplementedException(); + return (idMode == 1 && idCategory == 5003) || (idMode == 2 && idCategory == 5002); } private ProcessMapReportDataSaubStatDto? CalcStat( ProcessMapPlanDrillingDto? processMapPlanFilteredByDepth, Span span, - int idWellSectionType, string wellOperationCategoryName, string wellSectionTypeName ) @@ -226,7 +225,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report }, Rop = new PlanFactDto { - //Plan = CalcRopPlan(processMapPlanFilteredByDepth), + Plan = processMapPlanFilteredByDepth?.RopPlan, Fact = deltaDepth / aggregatedValues.DrilledTime }, }; From 5eede46b31819531149cbdf4b1a346c5ad3760ba Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 14 Feb 2024 13:43:19 +0500 Subject: [PATCH 08/13] nit fixes --- .../Report/ProcessMapReportDataSaubStatDto.cs | 2 +- .../ProcessMapReportDataSaubStatService.cs | 612 +++++++++--------- 2 files changed, 299 insertions(+), 315 deletions(-) diff --git a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs index abcef62b..06e1f3c4 100644 --- a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs +++ b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs @@ -84,7 +84,7 @@ public class ProcessMapReportDataSaubStatDto /// /// Обороты ВСП, об/мин /// - public ProcessMapReportDataSaubStatParamsDto Turnover { get; set; } = new(); + public ProcessMapReportDataSaubStatParamsDto TopDriveSpeed { get; set; } = new(); /// /// Расход, л/с diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 0dfbf755..466a82d0 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -14,343 +14,327 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.ProcessMaps.Report +namespace AsbCloudInfrastructure.Services.ProcessMaps.Report; + +public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStatService { - public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStatService + private readonly IWellService wellService; + private readonly IChangeLogRepository processMapPlanBaseRepository; + private readonly IDataSaubStatRepository dataSaubStatRepository; + private readonly IWellOperationRepository wellOperationRepository; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; + + public ProcessMapReportDataSaubStatService(IWellService wellService, + IChangeLogRepository processMapPlanBaseRepository, + IDataSaubStatRepository dataSaubStatRepository, + IWellOperationRepository wellOperationRepository, + IWellOperationCategoryRepository wellOperationCategoryRepository + ) { - private readonly IWellService wellService; - private readonly IChangeLogRepository processMapPlanBaseRepository; - private readonly IDataSaubStatRepository dataSaubStatRepository; - private readonly IWellOperationRepository wellOperationRepository; - private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; + this.wellService = wellService; + this.processMapPlanBaseRepository = processMapPlanBaseRepository; + this.dataSaubStatRepository = dataSaubStatRepository; + this.wellOperationRepository = wellOperationRepository; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + } - public ProcessMapReportDataSaubStatService(IWellService wellService, - IChangeLogRepository processMapPlanBaseRepository, - IDataSaubStatRepository dataSaubStatRepository, - IWellOperationRepository wellOperationRepository, - IWellOperationCategoryRepository wellOperationCategoryRepository - ) + public async Task> GetAsync(int idWell, DataSaubStatRequest request, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(idWell, token) + ?? throw new ArgumentInvalidException(nameof(idWell), $"Скважина с Id: {idWell} не найдена"); + + if (!well.IdTelemetry.HasValue) + return Enumerable.Empty(); + + var requestProcessMapPlan = new ProcessMapPlanBaseRequestWithWell(idWell); + var processMapPlanWellDrillings = await processMapPlanBaseRepository.Get(requestProcessMapPlan, token); + + if (!processMapPlanWellDrillings.Any()) + return Enumerable.Empty(); + + var geDepth = processMapPlanWellDrillings.Min(p => p.DepthStart); + var leDepth = processMapPlanWellDrillings.Max(p => p.DepthEnd); + + var requestWellOperationFact = new WellOperationRequest() { - this.wellService = wellService; - this.processMapPlanBaseRepository = processMapPlanBaseRepository; - this.dataSaubStatRepository = dataSaubStatRepository; - this.wellOperationRepository = wellOperationRepository; - this.wellOperationCategoryRepository = wellOperationCategoryRepository; - } + IdWell = idWell, + OperationType = WellOperation.IdOperationTypeFact, + GeDepth = geDepth, + LeDepth = leDepth + }; + var wellOperations = await wellOperationRepository + .GetAsync(requestWellOperationFact, token); + if (!wellOperations.Any()) + return Enumerable.Empty(); - public async Task> GetAsync(int idWell, DataSaubStatRequest request, CancellationToken token) + var dataSaubStats = + (await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, geDepth, leDepth, token)).ToArray(); + + if (!dataSaubStats.Any()) + return Enumerable.Empty(); + + var wellOperationCategories = wellOperationCategoryRepository.Get(false); + var wellSectionTypes = wellOperationRepository.GetSectionTypes(); + + var result = CalcByIntervals( + request, + processMapPlanWellDrillings, + dataSaubStats, + wellOperations, + wellOperationCategories, + wellSectionTypes); + + return result; + } + + private IEnumerable CalcByIntervals( + DataSaubStatRequest request, + IEnumerable processMapPlanWellDrillings, + Span dataSaubStats, + IEnumerable wellOperations, + IEnumerable wellOperationCategories, + IEnumerable wellSectionTypes + ) + { + var list = new List(); + var firstElemInInterval = dataSaubStats[0]; + + int GetSection(DataSaubStatDto data) + => wellOperations.MinBy(o => data.DateStart - o.DateStart)!.IdWellSectionType; + + ProcessMapPlanDrillingDto? GetProcessMapPlan(int idWellSectionType, DataSaubStatDto data) + => processMapPlanWellDrillings + .Where(p => p.IdWellSectionType == idWellSectionType) + .Where(p => p.DepthStart <= data.DepthStart) + .Where(p => p.DepthEnd >= data.DepthStart) + .Where(p => IsModeMatchOperationCategory(p.IdMode, data.IdCategory)) + .WhereActualAtMoment(data.DateStart) + .FirstOrDefault(); + + var idWellSectionType = GetSection(firstElemInInterval); + var prevProcessMapPlan = GetProcessMapPlan(idWellSectionType, firstElemInInterval); + var indexStart = 0; + + for (var i = 1; i < dataSaubStats.Length; i++) { - var well = await wellService.GetOrDefaultAsync(idWell, token) - ?? throw new ArgumentInvalidException(nameof(idWell), $"Скважина с Id: {idWell} не найдена"); + var currentElem = dataSaubStats[i]; + idWellSectionType = GetSection(currentElem); + var processMapPlan = GetProcessMapPlan(idWellSectionType, currentElem); - if (!well.IdTelemetry.HasValue) - return Enumerable.Empty(); - - var requestProcessMapPlan = new ProcessMapPlanBaseRequestWithWell(idWell); - var processMapPlanWellDrillings = await processMapPlanBaseRepository.Get(requestProcessMapPlan, token); - - if (!processMapPlanWellDrillings.Any()) - return Enumerable.Empty(); - - var geDepth = processMapPlanWellDrillings.Min(p => p.DepthStart); - var leDepth = processMapPlanWellDrillings.Max(p => p.DepthEnd); - - var requestWellOperationFact = new WellOperationRequest() + if (IsNewInterval(currentElem, firstElemInInterval, request) || i == dataSaubStats.Length - 1 || processMapPlan != prevProcessMapPlan) { - IdWell = idWell, - OperationType = WellOperation.IdOperationTypeFact, - GeDepth = geDepth, - LeDepth = leDepth - }; - var wellOperations = await wellOperationRepository - .GetAsync(requestWellOperationFact, token); - if (!wellOperations.Any()) - return Enumerable.Empty(); + prevProcessMapPlan = processMapPlan; + var length = i - indexStart; - var dataSaubStats = - (await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, geDepth, leDepth, token)).ToArray(); + var span = dataSaubStats.Slice(indexStart, length); - if (!dataSaubStats.Any()) - return Enumerable.Empty(); + indexStart = i; + firstElemInInterval = currentElem; - var wellOperationCategories = wellOperationCategoryRepository.Get(false); - var wellSectionTypes = wellOperationRepository.GetSectionTypes(); + var firstElemInSpan = span[0]; + var lastElemInISpan = span[^1]; - var result = CalcByIntervals( - request, - processMapPlanWellDrillings, - dataSaubStats, - wellOperations, - wellOperationCategories, - wellSectionTypes); + var wellOperationCategoryName = wellOperationCategories + .Where(c => c.Id == firstElemInSpan.IdCategory) + .FirstOrDefault()?.Name ?? string.Empty; - return result; - } + var wellSectionTypeName = wellSectionTypes + .Where(c => c.Id == idWellSectionType) + .FirstOrDefault()?.Caption ?? string.Empty; - private IEnumerable CalcByIntervals( - DataSaubStatRequest request, - IEnumerable processMapPlanWellDrillings, - Span dataSaubStats, - IEnumerable wellOperations, - IEnumerable wellOperationCategories, - IEnumerable wellSectionTypes - ) - { - var list = new List(); - var firstElemInInterval = dataSaubStats[0]; - - int GetSection(DataSaubStatDto data) - => wellOperations.MinBy(o => data.DateStart - o.DateStart)!.IdWellSectionType; - - ProcessMapPlanDrillingDto? GetProcessMapPlan(int idWellSectionType, DataSaubStatDto data) - => processMapPlanWellDrillings - .Where(p => p.IdWellSectionType == idWellSectionType) - .Where(p => p.DepthStart <= data.DepthStart) - .Where(p => p.DepthEnd >= data.DepthStart) - .Where(p => IsModeMatchOperationCategory(p.IdMode, data.IdCategory)) - .WhereActualAtMoment(data.DateStart) - .FirstOrDefault(); - - var idWellSectionType = GetSection(firstElemInInterval); - var prevProcessMapPlan = GetProcessMapPlan(idWellSectionType, firstElemInInterval); - var indexStart = 0; - - for (var i = 1; i < dataSaubStats.Length; i++) - { - var currentElem = dataSaubStats[i]; - idWellSectionType = GetSection(currentElem); - var processMapPlan = GetProcessMapPlan(idWellSectionType, currentElem); - - if (IsNewInterval(currentElem, firstElemInInterval, request) || i == dataSaubStats.Length - 1 || processMapPlan != prevProcessMapPlan) - { - prevProcessMapPlan = processMapPlan; - var length = i - indexStart; - - var span = dataSaubStats.Slice(indexStart, length); - - indexStart = i; - firstElemInInterval = currentElem; - - var firstElemInSpan = span[0]; - var lastElemInISpan = span[^1]; - - var wellOperationCategoryName = wellOperationCategories - .Where(c => c.Id == firstElemInSpan.IdCategory) - .FirstOrDefault()?.Name ?? string.Empty; - - var wellSectionTypeName = wellSectionTypes - .Where(c => c.Id == idWellSectionType) - .FirstOrDefault()?.Caption ?? string.Empty; - - var elem = CalcStat(processMapPlan, span, wellOperationCategoryName, wellSectionTypeName); - if (elem is not null) - list.Add(elem); - } + var elem = CalcStat(processMapPlan, span, wellOperationCategoryName, wellSectionTypeName); + if (elem is not null) + list.Add(elem); } - return list; } + return list; + } - private bool IsModeMatchOperationCategory(int idMode, int idCategory) + private static bool IsModeMatchOperationCategory(int idMode, int idCategory) + { + return (idMode == 1 && idCategory == 5003) || (idMode == 2 && idCategory == 5002); + } + + private ProcessMapReportDataSaubStatDto? CalcStat( + ProcessMapPlanDrillingDto? processMapPlanFilteredByDepth, + Span span, + string wellOperationCategoryName, + string wellSectionTypeName + ) + { + var firstElemInInterval = span[0]; + var lastElemInInterval = span[^1]; + + var deltaDepth = lastElemInInterval.DepthEnd - firstElemInInterval.DepthStart; + + var aggregatedValues = CalcAggregate(span); + + return new ProcessMapReportDataSaubStatDto() { - return (idMode == 1 && idCategory == 5003) || (idMode == 2 && idCategory == 5002); - } - - private ProcessMapReportDataSaubStatDto? CalcStat( - ProcessMapPlanDrillingDto? processMapPlanFilteredByDepth, - Span span, - string wellOperationCategoryName, - string wellSectionTypeName - ) - { - var firstElemInInterval = span[0]; - var lastElemInInterval = span[^1]; - - var deltaDepth = lastElemInInterval.DepthEnd - firstElemInInterval.DepthStart; - - - var aggregatedValues = CalcAggregate(span); - - return new ProcessMapReportDataSaubStatDto() + DateStart = firstElemInInterval.DateStart.DateTime, + WellSectionTypeName = wellSectionTypeName, + DepthStart = firstElemInInterval.DepthStart, + DepthEnd = lastElemInInterval.DepthEnd, + DeltaDepth = deltaDepth, + DrilledTime = aggregatedValues.DrilledTime, + DrillingMode = wellOperationCategoryName, + PressureDiff = new ProcessMapReportDataSaubStatParamsDto() { - DateStart = firstElemInInterval.DateStart.DateTime, - WellSectionTypeName = wellSectionTypeName, - DepthStart = firstElemInInterval.DepthStart, - DepthEnd = lastElemInInterval.DepthEnd, - DeltaDepth = deltaDepth, - DrilledTime = aggregatedValues.DrilledTime, - DrillingMode = wellOperationCategoryName, - PressureDiff = new ProcessMapReportDataSaubStatParamsDto() - { - SetpointPlan = processMapPlanFilteredByDepth?.DeltaPressurePlan, - SetpointFact = firstElemInInterval.PressureSp - firstElemInInterval.PressureIdle, - FactWavg = aggregatedValues.Pressure, - Limit = processMapPlanFilteredByDepth?.DeltaPressureLimitMax, - SetpointUsage = aggregatedValues.SetpointUsagePressure - }, - AxialLoad = new ProcessMapReportDataSaubStatParamsDto() - { - SetpointPlan = processMapPlanFilteredByDepth?.AxialLoadPlan, - SetpointFact = aggregatedValues.AxialLoadSp, - FactWavg = aggregatedValues.AxialLoad, - Limit = processMapPlanFilteredByDepth?.AxialLoadLimitMax, - SetpointUsage = aggregatedValues.SetpointUsageAxialLoad - }, - TopDriveTorque = new ProcessMapReportDataSaubStatParamsDto() - { - SetpointPlan = processMapPlanFilteredByDepth?.TopDriveTorquePlan, - SetpointFact = aggregatedValues.RotorTorqueSp, - FactWavg = aggregatedValues.RotorTorque, - FactMax = aggregatedValues.RotorTorqueMax, - Limit = processMapPlanFilteredByDepth?.TopDriveTorqueLimitMax, - SetpointUsage = aggregatedValues.SetpointUsageRotorTorque - }, - SpeedLimit = new ProcessMapReportDataSaubStatParamsDto - { - SetpointPlan = processMapPlanFilteredByDepth?.RopPlan, - SetpointFact = aggregatedValues.BlockSpeedSp, - FactWavg = deltaDepth / aggregatedValues.DrilledTime, - SetpointUsage = aggregatedValues.SetpointUsageRopPlan - }, - Turnover = new ProcessMapReportDataSaubStatParamsDto - { - SetpointPlan = processMapPlanFilteredByDepth?.TopDriveSpeedPlan, - FactWavg = aggregatedValues.RotorSpeed, - FactMax = aggregatedValues.RotorSpeedMax - }, - Flow = new ProcessMapReportDataSaubStatParamsDto - { - SetpointPlan = processMapPlanFilteredByDepth?.FlowPlan, - FactWavg = aggregatedValues.MaxFlow, - Limit = processMapPlanFilteredByDepth?.FlowLimitMax, - }, - Rop = new PlanFactDto - { - Plan = processMapPlanFilteredByDepth?.RopPlan, - Fact = deltaDepth / aggregatedValues.DrilledTime - }, - }; - } - - private ( - double Pressure, - double AxialLoadSp, - double AxialLoad, - double RotorTorqueSp, - double RotorTorque, - double RotorTorqueMax, - double BlockSpeedSp, - double RotorSpeed, - double RotorSpeedMax, - double MaxFlow, - double SetpointUsagePressure, - double SetpointUsageAxialLoad, - double SetpointUsageRotorTorque, - double SetpointUsageRopPlan, - double DrilledTime - ) CalcAggregate(Span span) - { - var sumPressure = 0.0; - var sumAxialLoadSp = 0.0; - var sumAxialLoad = 0.0; - var sumRotorTorqueSp = 0.0; - var sumRotorTorque = 0.0; - var sumBlockSpeedSp = 0.0; - var sumRotorSpeed = 0.0; - var maxFlow = 0.0; - var maxRotorTorque = 0.0; - var maxRotorSpeed = 0.0; - var sumDiffDepthByPressure = 0.0; - var sumDiffDepthByAxialLoad = 0.0; - var sumDiffDepthByRotorTorque = 0.0; - var sumDiffDepthByRopPlan = 0.0; - - var diffDepthTotal = 0.0; - var drilledTime = 0.0; - - for (var i = 0; i < span.Length; i++) + SetpointPlan = processMapPlanFilteredByDepth?.DeltaPressurePlan, + SetpointFact = firstElemInInterval.PressureSp - firstElemInInterval.PressureIdle, + FactWavg = aggregatedValues.Pressure, + Limit = processMapPlanFilteredByDepth?.DeltaPressureLimitMax, + SetpointUsage = aggregatedValues.SetpointUsagePressure + }, + AxialLoad = new ProcessMapReportDataSaubStatParamsDto() { - var diffDepth = span[i].DepthEnd - span[i].DepthStart; - - sumPressure += diffDepth * (span[i].Pressure - (span[i].PressureIdle ?? 0.0)); - sumAxialLoadSp += diffDepth * (span[i].AxialLoadSp ?? 0); - sumAxialLoad += diffDepth * span[i].AxialLoad; - sumRotorTorqueSp += diffDepth * (span[i].RotorTorqueSp ?? 0); - sumRotorTorque += diffDepth * span[i].RotorTorque; - sumBlockSpeedSp += diffDepth * (span[i].BlockSpeedSp ?? 0); - sumRotorSpeed += diffDepth * span[i].RotorSpeed; - maxFlow = span[i].Flow > maxFlow ? span[i].Flow : maxFlow; - maxRotorTorque = span[i].RotorTorque > maxRotorTorque ? span[i].RotorTorque : maxRotorTorque; - maxRotorSpeed = span[i].RotorSpeed > maxRotorSpeed ? span[i].RotorSpeed : maxRotorSpeed; - - if (span[i].IdFeedRegulator == LimitingParameterDto.Pressure) - sumDiffDepthByPressure += diffDepth; - if (span[i].IdFeedRegulator == LimitingParameterDto.AxialLoad) - sumDiffDepthByAxialLoad += diffDepth; - if (span[i].IdFeedRegulator == LimitingParameterDto.RotorTorque) - sumDiffDepthByRotorTorque += diffDepth; - if (span[i].IdFeedRegulator == LimitingParameterDto.RopPlan) - sumDiffDepthByRopPlan += diffDepth; - - diffDepthTotal += diffDepth; - drilledTime += (span[i].DateEnd - span[i].DateStart).TotalHours; - } - return ( - Pressure: sumPressure / diffDepthTotal, - AxialLoadSp: sumAxialLoadSp / diffDepthTotal, - AxialLoad: sumAxialLoad / diffDepthTotal, - RotorTorqueSp: sumRotorTorqueSp / diffDepthTotal, - RotorTorque: sumRotorTorque / diffDepthTotal, - RotorTorqueMax: maxRotorTorque, - BlockSpeedSp: sumBlockSpeedSp / diffDepthTotal, - RotorSpeed: sumRotorSpeed / diffDepthTotal, - RotorSpeedMax: maxRotorSpeed, - MaxFlow: maxFlow, - SetpointUsagePressure: sumDiffDepthByPressure / diffDepthTotal, - SetpointUsageAxialLoad: sumDiffDepthByAxialLoad / diffDepthTotal, - SetpointUsageRotorTorque: sumDiffDepthByRotorTorque / diffDepthTotal, - SetpointUsageRopPlan: sumDiffDepthByRopPlan / diffDepthTotal, - DrilledTime: drilledTime - ); - } - - private double CalcRopPlan(ProcessMapPlanDrillingDto[] processMapPlanFilteredByDepth) - { - var sumRopPlan = 0.0; - var diffDepthTotal = 0.0; - - for (var i = 0; i < processMapPlanFilteredByDepth.Length; i++) + SetpointPlan = processMapPlanFilteredByDepth?.AxialLoadPlan, + SetpointFact = aggregatedValues.AxialLoadSp, + FactWavg = aggregatedValues.AxialLoad, + Limit = processMapPlanFilteredByDepth?.AxialLoadLimitMax, + SetpointUsage = aggregatedValues.SetpointUsageAxialLoad + }, + TopDriveTorque = new ProcessMapReportDataSaubStatParamsDto() { - var diffDepth = processMapPlanFilteredByDepth[i].DepthEnd - processMapPlanFilteredByDepth[i].DepthStart; - sumRopPlan += diffDepth * processMapPlanFilteredByDepth[i].RopPlan; - diffDepthTotal += diffDepth; - } - return sumRopPlan / diffDepthTotal; - } - - private bool IsNewInterval(DataSaubStatDto currentElem, DataSaubStatDto firstElem, DataSaubStatRequest request) - { - bool isNewElemBySpeed(double currentSpeed, double firstSpeed) + SetpointPlan = processMapPlanFilteredByDepth?.TopDriveTorquePlan, + SetpointFact = aggregatedValues.RotorTorqueSp, + FactWavg = aggregatedValues.RotorTorque, + FactMax = aggregatedValues.RotorTorqueMax, + Limit = processMapPlanFilteredByDepth?.TopDriveTorqueLimitMax, + SetpointUsage = aggregatedValues.SetpointUsageRotorTorque + }, + SpeedLimit = new ProcessMapReportDataSaubStatParamsDto { - //2. Изменение уставки скорости подачи от первого значения в начале интервала при условии: - //скорость > 80 м/ч => изменение уставки на ± 20 м/ч; - //скорость > 30 м/ч => изменение уставки на ± 15 м/ч; - //скорость <= 30 м/ч => изменение уставки на ± 5 м/ч; - if (firstSpeed > 80) - return Math.Abs(currentSpeed - firstSpeed) >= 20; - else if (firstSpeed > 30) - return Math.Abs(currentSpeed - firstSpeed) >= 15; - else - return Math.Abs(currentSpeed - firstSpeed) >= 5; - } + SetpointPlan = processMapPlanFilteredByDepth?.RopPlan, + SetpointFact = aggregatedValues.BlockSpeedSp, + FactWavg = deltaDepth / aggregatedValues.DrilledTime, + SetpointUsage = aggregatedValues.SetpointUsageRopPlan + }, + TopDriveSpeed = new ProcessMapReportDataSaubStatParamsDto + { + SetpointPlan = processMapPlanFilteredByDepth?.TopDriveSpeedPlan, + FactWavg = aggregatedValues.RotorSpeed, + FactMax = aggregatedValues.RotorSpeedMax + }, + Flow = new ProcessMapReportDataSaubStatParamsDto + { + SetpointPlan = processMapPlanFilteredByDepth?.FlowPlan, + FactWavg = aggregatedValues.MaxFlow, + Limit = processMapPlanFilteredByDepth?.FlowLimitMax, + }, + Rop = new PlanFactDto + { + Plan = processMapPlanFilteredByDepth?.RopPlan, + Fact = deltaDepth / aggregatedValues.DrilledTime + }, + }; + } - var isNewElem = (currentElem.IdCategory != firstElem.IdCategory) - || (Math.Abs(currentElem.Pressure - firstElem.Pressure) >= request.DeltaPressure) - || (Math.Abs(currentElem.AxialLoad - firstElem.AxialLoad) >= request.DeltaAxialLoad) - || (Math.Abs(currentElem.RotorTorque - firstElem.RotorTorque) >= request.DeltaRotorTorque) - || (Math.Abs((currentElem.AxialLoadSp ?? 0) - (firstElem.AxialLoadSp ?? 0)) >= request.DeltaAxialLoadSp) - || (Math.Abs((currentElem.RotorTorqueSp ?? 0) - (firstElem.RotorTorqueSp ?? 0)) >= request.DeltaRotorTorqueSp) - || (isNewElemBySpeed(currentElem.Speed, firstElem.Speed)); - return isNewElem; + private ( + double Pressure, + double AxialLoadSp, + double AxialLoad, + double RotorTorqueSp, + double RotorTorque, + double RotorTorqueMax, + double BlockSpeedSp, + double RotorSpeed, + double RotorSpeedMax, + double MaxFlow, + double SetpointUsagePressure, + double SetpointUsageAxialLoad, + double SetpointUsageRotorTorque, + double SetpointUsageRopPlan, + double DrilledTime + ) CalcAggregate(Span span) + { + var sumPressure = 0.0; + var sumAxialLoadSp = 0.0; + var sumAxialLoad = 0.0; + var sumRotorTorqueSp = 0.0; + var sumRotorTorque = 0.0; + var sumBlockSpeedSp = 0.0; + var sumRotorSpeed = 0.0; + var maxFlow = 0.0; + var maxRotorTorque = 0.0; + var maxRotorSpeed = 0.0; + var sumDiffDepthByPressure = 0.0; + var sumDiffDepthByAxialLoad = 0.0; + var sumDiffDepthByRotorTorque = 0.0; + var sumDiffDepthByRopPlan = 0.0; + + var diffDepthTotal = 0.0; + var drilledTime = 0.0; + + for (var i = 0; i < span.Length; i++) + { + var diffDepth = span[i].DepthEnd - span[i].DepthStart; + + sumPressure += diffDepth * (span[i].Pressure - (span[i].PressureIdle ?? 0.0)); + sumAxialLoadSp += diffDepth * (span[i].AxialLoadSp ?? 0); + sumAxialLoad += diffDepth * span[i].AxialLoad; + sumRotorTorqueSp += diffDepth * (span[i].RotorTorqueSp ?? 0); + sumRotorTorque += diffDepth * span[i].RotorTorque; + sumBlockSpeedSp += diffDepth * (span[i].BlockSpeedSp ?? 0); + sumRotorSpeed += diffDepth * span[i].RotorSpeed; + maxFlow = span[i].Flow > maxFlow ? span[i].Flow : maxFlow; + maxRotorTorque = span[i].RotorTorque > maxRotorTorque ? span[i].RotorTorque : maxRotorTorque; + maxRotorSpeed = span[i].RotorSpeed > maxRotorSpeed ? span[i].RotorSpeed : maxRotorSpeed; + + if (span[i].IdFeedRegulator == LimitingParameterDto.Pressure) + sumDiffDepthByPressure += diffDepth; + if (span[i].IdFeedRegulator == LimitingParameterDto.AxialLoad) + sumDiffDepthByAxialLoad += diffDepth; + if (span[i].IdFeedRegulator == LimitingParameterDto.RotorTorque) + sumDiffDepthByRotorTorque += diffDepth; + if (span[i].IdFeedRegulator == LimitingParameterDto.RopPlan) + sumDiffDepthByRopPlan += diffDepth; + + diffDepthTotal += diffDepth; + drilledTime += (span[i].DateEnd - span[i].DateStart).TotalHours; } + return ( + Pressure: sumPressure / diffDepthTotal, + AxialLoadSp: sumAxialLoadSp / diffDepthTotal, + AxialLoad: sumAxialLoad / diffDepthTotal, + RotorTorqueSp: sumRotorTorqueSp / diffDepthTotal, + RotorTorque: sumRotorTorque / diffDepthTotal, + RotorTorqueMax: maxRotorTorque, + BlockSpeedSp: sumBlockSpeedSp / diffDepthTotal, + RotorSpeed: sumRotorSpeed / diffDepthTotal, + RotorSpeedMax: maxRotorSpeed, + MaxFlow: maxFlow, + SetpointUsagePressure: sumDiffDepthByPressure / diffDepthTotal, + SetpointUsageAxialLoad: sumDiffDepthByAxialLoad / diffDepthTotal, + SetpointUsageRotorTorque: sumDiffDepthByRotorTorque / diffDepthTotal, + SetpointUsageRopPlan: sumDiffDepthByRopPlan / diffDepthTotal, + DrilledTime: drilledTime + ); + } + + private bool IsNewInterval(DataSaubStatDto currentElem, DataSaubStatDto firstElem, DataSaubStatRequest request) + { + bool isNewElemBySpeed(double currentSpeed, double firstSpeed) + { + //2. Изменение уставки скорости подачи от первого значения в начале интервала при условии: + //скорость > 80 м/ч => изменение уставки на ± 20 м/ч; + //скорость > 30 м/ч => изменение уставки на ± 15 м/ч; + //скорость <= 30 м/ч => изменение уставки на ± 5 м/ч; + if (firstSpeed > 80) + return Math.Abs(currentSpeed - firstSpeed) >= 20; + else if (firstSpeed > 30) + return Math.Abs(currentSpeed - firstSpeed) >= 15; + else + return Math.Abs(currentSpeed - firstSpeed) >= 5; + } + + var isNewElem = (currentElem.IdCategory != firstElem.IdCategory) + || (Math.Abs(currentElem.Pressure - firstElem.Pressure) >= request.DeltaPressure) + || (Math.Abs(currentElem.AxialLoad - firstElem.AxialLoad) >= request.DeltaAxialLoad) + || (Math.Abs(currentElem.RotorTorque - firstElem.RotorTorque) >= request.DeltaRotorTorque) + || (Math.Abs((currentElem.AxialLoadSp ?? 0) - (firstElem.AxialLoadSp ?? 0)) >= request.DeltaAxialLoadSp) + || (Math.Abs((currentElem.RotorTorqueSp ?? 0) - (firstElem.RotorTorqueSp ?? 0)) >= request.DeltaRotorTorqueSp) + || (isNewElemBySpeed(currentElem.Speed, firstElem.Speed)); + return isNewElem; } } From 0f93c637e0114df2a007187416dfdb37f2792b35 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Wed, 14 Feb 2024 15:28:37 +0500 Subject: [PATCH 09/13] =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D1=8C=D1=82=D1=80=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81=D1=82=D0=B8=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D0=B4=D0=B0=D1=82=D0=B5,=20=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D0=BF=D0=BE=20=D0=B3=D0=BB=D1=83=D0=B1=D0=B8=D0=BD?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Repositories/IDataSaubStatRepository.cs | 7 ++++--- .../Repository/DataSaubStatRepository.cs | 6 +++--- .../Report/ProcessMapReportDataSaubStatService.cs | 4 +++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs index 941d6465..9dfa351c 100644 --- a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs +++ b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -14,11 +15,11 @@ namespace AsbCloudApp.Repositories /// Получение записей по ключу телеметрии /// /// ключ телеметрии - /// начальная глубина - /// конечная глубина + /// начальная дата + /// конечная дата /// /// - Task> GetAsync(int idTelemetry, double geDepth, double leDepth, CancellationToken token); + Task> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token); /// /// Получение последних по дате окончания бурения записей в разрезе телеметрий diff --git a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs index 72737a0b..f4783356 100644 --- a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs +++ b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs @@ -40,14 +40,14 @@ namespace AsbCloudInfrastructure.Repository return result; } - public async Task> GetAsync(int idTelemetry, double geDepth, double leDepth, CancellationToken token) + public async Task> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token) { var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours); var stats = await db.Set() .Where(s => s.IdTelemetry == idTelemetry) - .Where(s => s.DepthStart >= geDepth) - .Where(s => s.DepthEnd <= leDepth) + .Where(s => s.DateStart >= geDate) + .Where(s => s.DateEnd <= leDate) .ToArrayAsync(token); var result = stats.Select(s => ConvertToDto(s, timeSpan)); diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 0dfbf755..ae90510e 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -67,8 +67,10 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report if (!wellOperations.Any()) return Enumerable.Empty(); + var geDate = wellOperations.Min(p => p.DateStart).ToUniversalTime(); + var leDate = wellOperations.Max(p => (p.DateStart.AddHours(p.DurationHours))).ToUniversalTime(); var dataSaubStats = - (await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, geDepth, leDepth, token)).ToArray(); + (await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, geDate, leDate, token)).ToArray(); if (!dataSaubStats.Any()) return Enumerable.Empty(); From 53af712750637b63130d98aca72d5f604f487d23 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Thu, 15 Feb 2024 10:52:18 +0500 Subject: [PATCH 10/13] =?UTF-8?q?=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=B0=D1=82=20=D0=BA=20UT?= =?UTF-8?q?=D0=A1-=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D1=83=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=BB=D0=B6=D0=BD=D0=BE=20=D0=BE=D1=81=D1=83=D1=89=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=BB=D1=8F=D1=82=D1=8C=D1=81=D1=8F=20=D0=B2?= =?UTF-8?q?=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs | 6 ++++-- .../Report/ProcessMapReportDataSaubStatService.cs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs index f4783356..23eba5f9 100644 --- a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs +++ b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs @@ -43,11 +43,13 @@ namespace AsbCloudInfrastructure.Repository public async Task> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token) { var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours); + var geDateUtc = geDate.ToUniversalTime(); + var leDateUtc = leDate.ToUniversalTime(); var stats = await db.Set() .Where(s => s.IdTelemetry == idTelemetry) - .Where(s => s.DateStart >= geDate) - .Where(s => s.DateEnd <= leDate) + .Where(s => s.DateStart >= geDateUtc) + .Where(s => s.DateEnd <= leDateUtc) .ToArrayAsync(token); var result = stats.Select(s => ConvertToDto(s, timeSpan)); diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 86733960..3404a1d7 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -67,8 +67,8 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat if (!wellOperations.Any()) return Enumerable.Empty(); - var geDate = wellOperations.Min(p => p.DateStart).ToUniversalTime(); - var leDate = wellOperations.Max(p => (p.DateStart.AddHours(p.DurationHours))).ToUniversalTime(); + var geDate = wellOperations.Min(p => p.DateStart); + var leDate = wellOperations.Max(p => (p.DateStart.AddHours(p.DurationHours))); var dataSaubStats = (await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, geDate, leDate, token)).ToArray(); From c19defe529e5c6169dae1e412c6eb14acdcbb2fe Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 15 Feb 2024 12:09:33 +0500 Subject: [PATCH 11/13] ProcessMapReportDataSaubStatService apply compiller recommendations --- .../Report/ProcessMapReportDataSaubStatService.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 3404a1d7..7c8e344d 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -89,7 +89,7 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat return result; } - private IEnumerable CalcByIntervals( + private static IEnumerable CalcByIntervals( DataSaubStatRequest request, IEnumerable processMapPlanWellDrillings, Span dataSaubStats, @@ -157,7 +157,7 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat return (idMode == 1 && idCategory == 5003) || (idMode == 2 && idCategory == 5002); } - private ProcessMapReportDataSaubStatDto? CalcStat( + private static ProcessMapReportDataSaubStatDto? CalcStat( ProcessMapPlanDrillingDto? processMapPlanFilteredByDepth, Span span, string wellOperationCategoryName, @@ -232,7 +232,7 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat }; } - private ( + private static ( double Pressure, double AxialLoadSp, double AxialLoad, @@ -314,9 +314,9 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat ); } - private bool IsNewInterval(DataSaubStatDto currentElem, DataSaubStatDto firstElem, DataSaubStatRequest request) + private static bool IsNewInterval(DataSaubStatDto currentElem, DataSaubStatDto firstElem, DataSaubStatRequest request) { - bool isNewElemBySpeed(double currentSpeed, double firstSpeed) + static bool IsNewElemBySpeed(double currentSpeed, double firstSpeed) { //2. Изменение уставки скорости подачи от первого значения в начале интервала при условии: //скорость > 80 м/ч => изменение уставки на ± 20 м/ч; @@ -336,7 +336,7 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat || (Math.Abs(currentElem.RotorTorque - firstElem.RotorTorque) >= request.DeltaRotorTorque) || (Math.Abs((currentElem.AxialLoadSp ?? 0) - (firstElem.AxialLoadSp ?? 0)) >= request.DeltaAxialLoadSp) || (Math.Abs((currentElem.RotorTorqueSp ?? 0) - (firstElem.RotorTorqueSp ?? 0)) >= request.DeltaRotorTorqueSp) - || (isNewElemBySpeed(currentElem.Speed, firstElem.Speed)); + || (IsNewElemBySpeed(currentElem.Speed, firstElem.Speed)); return isNewElem; } } From 10a15f1c771f2552fb03c15dcb0b19f243e16c9b Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 15 Feb 2024 15:59:34 +0500 Subject: [PATCH 12/13] ProcessMapReportDataSaubStatService Add test and fix. --- AsbCloudApp/Data/DataSaubStatDto.cs | 2 +- .../Report/ProcessMapReportDataSaubStatDto.cs | 5 - AsbCloudApp/Extensions/ChangeLogExtensions.cs | 4 +- .../ProcessMapReportDataSaubStatService.cs | 14 +- .../Services/DailyReportServiceTest.cs | 2 +- ...ProcessMapReportDataSaubStatServiceTest.cs | 292 ++++++++++++++++++ 6 files changed, 304 insertions(+), 15 deletions(-) create mode 100644 AsbCloudWebApi.Tests/Services/ProcessMaps/ProcessMapReportDataSaubStatServiceTest.cs diff --git a/AsbCloudApp/Data/DataSaubStatDto.cs b/AsbCloudApp/Data/DataSaubStatDto.cs index 639154df..a3b80a5d 100644 --- a/AsbCloudApp/Data/DataSaubStatDto.cs +++ b/AsbCloudApp/Data/DataSaubStatDto.cs @@ -2,7 +2,7 @@ namespace AsbCloudApp.Data { - public class DataSaubStatDto + public class DataSaubStatDto:IId { /// /// diff --git a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs index 06e1f3c4..6255726f 100644 --- a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs +++ b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs @@ -12,11 +12,6 @@ public class ProcessMapReportDataSaubStatDto /// public double DrilledTime { get; set; } = 0; - /// - /// Идентификатор скважины - /// - public int IdWell { get; set; } - /// /// Id секции скважины /// diff --git a/AsbCloudApp/Extensions/ChangeLogExtensions.cs b/AsbCloudApp/Extensions/ChangeLogExtensions.cs index c52e33dd..83f28fbe 100644 --- a/AsbCloudApp/Extensions/ChangeLogExtensions.cs +++ b/AsbCloudApp/Extensions/ChangeLogExtensions.cs @@ -23,8 +23,8 @@ namespace AsbCloudApp.Extensions where T : ChangeLogAbstract { var actualItems = items - .Where(item => item.Creation >= moment) - .Where(item => item.Obsolete is null || item.Obsolete <= moment); + .Where(item => item.Creation <= moment) + .Where(item => item.Obsolete is null || item.Obsolete >= moment); return actualItems; } diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs index 7c8e344d..9ad31d53 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDataSaubStatService.cs @@ -140,11 +140,11 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat .Where(c => c.Id == firstElemInSpan.IdCategory) .FirstOrDefault()?.Name ?? string.Empty; - var wellSectionTypeName = wellSectionTypes + var wellSectionType = wellSectionTypes .Where(c => c.Id == idWellSectionType) - .FirstOrDefault()?.Caption ?? string.Empty; + .First(); - var elem = CalcStat(processMapPlan, span, wellOperationCategoryName, wellSectionTypeName); + var elem = CalcStat(processMapPlan, span, wellOperationCategoryName, wellSectionType); if (elem is not null) list.Add(elem); } @@ -161,7 +161,7 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat ProcessMapPlanDrillingDto? processMapPlanFilteredByDepth, Span span, string wellOperationCategoryName, - string wellSectionTypeName + WellSectionTypeDto wellSectionType ) { var firstElemInInterval = span[0]; @@ -171,10 +171,11 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat var aggregatedValues = CalcAggregate(span); - return new ProcessMapReportDataSaubStatDto() + var result = new ProcessMapReportDataSaubStatDto() { + IdWellSectionType = wellSectionType.Id, DateStart = firstElemInInterval.DateStart.DateTime, - WellSectionTypeName = wellSectionTypeName, + WellSectionTypeName = wellSectionType.Caption, DepthStart = firstElemInInterval.DepthStart, DepthEnd = lastElemInInterval.DepthEnd, DeltaDepth = deltaDepth, @@ -230,6 +231,7 @@ public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStat Fact = deltaDepth / aggregatedValues.DrilledTime }, }; + return result; } private static ( diff --git a/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs b/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs index d9665e4d..52b2044d 100644 --- a/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs @@ -275,7 +275,7 @@ public class DailyReportServiceTest wellOperationRepositoryMock.GetSectionTypes() .ReturnsForAnyArgs(new[] { fakeSectionType }); - detectedOperationServiceMock.GetAsync(Arg.Any(), Arg.Any()) + detectedOperationServiceMock.GetAsync(Arg.Any(), Arg.Any()) .ReturnsForAnyArgs(fakeWellOperationSlipsTime); subsystemServiceMock.GetStatAsync(Arg.Any(), Arg.Any()) diff --git a/AsbCloudWebApi.Tests/Services/ProcessMaps/ProcessMapReportDataSaubStatServiceTest.cs b/AsbCloudWebApi.Tests/Services/ProcessMaps/ProcessMapReportDataSaubStatServiceTest.cs new file mode 100644 index 00000000..6054c135 --- /dev/null +++ b/AsbCloudWebApi.Tests/Services/ProcessMaps/ProcessMapReportDataSaubStatServiceTest.cs @@ -0,0 +1,292 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMapPlan; +using AsbCloudApp.Data.ProcessMaps; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; +using AsbCloudInfrastructure.Services.ProcessMaps; +using AsbCloudInfrastructure.Services.ProcessMaps.Report; +using DocumentFormat.OpenXml.Bibliography; +using DocumentFormat.OpenXml.Spreadsheet; +using NSubstitute; +using Xunit; + +namespace AsbCloudWebApi.Tests.Services.ProcessMaps; + +public class ProcessMapReportDataSaubStatServiceTest +{ + + + private IWellService wellService + = Substitute.For(); + + private IChangeLogRepository processMapPlanBaseRepository + = Substitute.For>(); + + private IWellOperationRepository wellOperationRepository + = Substitute.For(); + + private IWellOperationCategoryRepository wellOperationCategoryRepository + = Substitute.For(); + + private IDataSaubStatRepository dataSaubStatRepository + = Substitute.For(); + + private ProcessMapReportDataSaubStatService service; + + private readonly static SimpleTimezoneDto timezone = new() { Hours = 2 }; + private static readonly DateTimeOffset dateStart = new (2024, 01, 01, 00, 11, 11, timezone.Offset); + private readonly static WellDto well = new() + { + Id = 1, + IdTelemetry = 1, + Timezone = timezone + }; + private readonly static IEnumerable processMapPlan = new List() + { + new() { + DepthStart = 0, + DepthEnd = 100, + IdMode = 1, + IdWell = well.Id, + IdWellSectionType = 1, + AxialLoadPlan = 0.2, + AxialLoadLimitMax = 0.3, + DeltaPressurePlan = 0.4, + DeltaPressureLimitMax = 0.5, + TopDriveTorquePlan = 0.6, + TopDriveTorqueLimitMax = 0.7, + TopDriveSpeedPlan = 0.8, + TopDriveSpeedLimitMax = 0.9, + FlowPlan = 0.10, + FlowLimitMax = 0.11, + RopPlan = 0.12, + UsageSaub = 0.12, + UsageSpin = 0.14, + Comment = "r", + }, + new() { + DepthStart = 0, + DepthEnd = 100, + IdMode = 2, + IdWell = well.Id, + IdWellSectionType = 1, + AxialLoadPlan = 0.12, + AxialLoadLimitMax = 0.13, + DeltaPressurePlan = 0.14, + DeltaPressureLimitMax = 0.15, + TopDriveTorquePlan = 0.16, + TopDriveTorqueLimitMax = 0.17, + TopDriveSpeedPlan = 0.18, + TopDriveSpeedLimitMax = 0.19, + FlowPlan = 0.110, + FlowLimitMax = 0.111, + RopPlan = 0.112, + UsageSaub = 0.112, + UsageSpin = 0.114, + Comment = "s", + }, + new() { + DepthStart = 100, + DepthEnd = 200, + IdMode = 1, + IdWell = well.Id, + IdWellSectionType = 1, + AxialLoadPlan = 0.22, + AxialLoadLimitMax = 0.23, + DeltaPressurePlan = 0.24, + DeltaPressureLimitMax = 0.25, + TopDriveTorquePlan = 0.26, + TopDriveTorqueLimitMax = 0.27, + TopDriveSpeedPlan = 0.28, + TopDriveSpeedLimitMax = 0.29, + FlowPlan = 0.210, + FlowLimitMax = 0.211, + RopPlan = 0.212, + UsageSaub = 0.212, + UsageSpin = 0.214, + Comment = "r", + }, + new() { + DepthStart = 100, + DepthEnd = 200, + IdMode = 2, + IdWell = well.Id, + IdWellSectionType = 1, + AxialLoadPlan = 0.32, + AxialLoadLimitMax = 0.33, + DeltaPressurePlan = 0.34, + DeltaPressureLimitMax = 0.35, + TopDriveTorquePlan = 0.36, + TopDriveTorqueLimitMax = 0.37, + TopDriveSpeedPlan = 0.38, + TopDriveSpeedLimitMax = 0.39, + FlowPlan = 0.310, + FlowLimitMax = 0.311, + RopPlan = 0.312, + UsageSaub = 0.312, + UsageSpin = 0.314, + Comment = "s", + }, + }; + private readonly static IEnumerable operations = new List() + { + new() + { + Id = 1, + IdWell = well.Id, + IdWellSectionType = 1, + IdCategory = WellOperationCategory.IdRotor, + IdParentCategory = WellOperationCategory.IdMechanicalDrilling, + IdType = WellOperation.IdOperationTypeFact, + DepthStart = 0, + DepthEnd = 10, + DateStart = dateStart, + DurationHours = 1, + }, + new() + { + Id = 1, + IdWell = well.Id, + IdWellSectionType = 2, + IdCategory = WellOperationCategory.IdRotor, + IdParentCategory = WellOperationCategory.IdMechanicalDrilling, + IdType = WellOperation.IdOperationTypeFact, + DepthStart = 50, + DepthEnd = 100, + DateStart = dateStart, + DurationHours = 1, + } + }; + private readonly static IEnumerable operationCategories = new List() + { + new(){Id = WellOperationCategory.IdRotor, IdParent = WellOperationCategory.IdMechanicalDrilling, Name = "РОТОР"}, + new(){Id = WellOperationCategory.IdSlide, IdParent = WellOperationCategory.IdMechanicalDrilling, Name = "СЛАЙД"}, + }; + private readonly static IEnumerable sectionTypes = new List() { + new(){ Id = 1, Caption = "Секция 1"}, + new(){ Id = 2, Caption = "Секция 2"}, + new(){ Id = 3, Caption = "Секция 3"}, + new(){ Id = 4, Caption = "Секция 4"}, + }; + private readonly static IEnumerable dataSaubStat = new List() { + new(){ + Id = 1, + IdTelemetry = 1, + IdCategory = WellOperationCategory.IdRotor, + DateStart = dateStart, + DateEnd = dateStart.AddHours(3.25), + DepthStart = 0, + DepthEnd = 20, + Speed = 0.1, + BlockSpeedSp = 0.2, + Pressure = 0.3, + PressureIdle = 0.4, + PressureSp = 0.5, + AxialLoad = 0.6, + AxialLoadSp = 0.7, + AxialLoadLimitMax = 0.8, + RotorTorque = 0.9, + RotorTorqueSp = 0.11, + RotorTorqueLimitMax = 0.12, + RotorSpeed = 0.14, + Flow = 0.17, + IdFeedRegulator = LimitingParameterDto.AxialLoad, + EnabledSubsystems = 15, + HasOscillation = false, + }, + new(){ + Id = 1, + IdTelemetry = 1, + IdCategory = WellOperationCategory.IdRotor, + DateStart = dateStart.AddHours(3.25), + DateEnd = dateStart.AddHours(4.25), + DepthStart = 20, + DepthEnd = 190, + Speed = 0.21, + BlockSpeedSp = 0.22, + Pressure = 0.23, + PressureIdle = 0.24, + PressureSp = 0.25, + AxialLoad = 0.26, + AxialLoadSp = 0.27, + AxialLoadLimitMax = 0.28, + RotorTorque = 0.29, + RotorTorqueSp = 0.211, + RotorTorqueLimitMax = 0.212, + RotorSpeed = 0.214, + Flow = 0.217, + IdFeedRegulator = LimitingParameterDto.AxialLoad, + EnabledSubsystems = 15, + HasOscillation = false, + }, + new(){ + Id = 1, + IdTelemetry = 1, + IdCategory = WellOperationCategory.IdRotor, + DateStart = dateStart.AddHours(4.25), + DateEnd = dateStart.AddHours(16), + DepthStart = 190, + DepthEnd = 290, + Speed = 0.31, + BlockSpeedSp = 0.32, + Pressure = 0.33, + PressureIdle = 0.34, + PressureSp = 0.35, + AxialLoad = 0.36, + AxialLoadSp = 0.37, + AxialLoadLimitMax = 0.38, + RotorTorque = 0.39, + RotorTorqueSp = 0.231, + RotorTorqueLimitMax = 0.232, + RotorSpeed = 0.234, + Flow = 0.237, + IdFeedRegulator = LimitingParameterDto.AxialLoad, + EnabledSubsystems = 15, + HasOscillation = false, + } + }; + + public ProcessMapReportDataSaubStatServiceTest() + { + wellService.GetOrDefaultAsync(Arg.Any(), Arg.Any()) + .Returns(well); + + processMapPlanBaseRepository.Get(Arg.Any(), Arg.Any()) + .Returns(processMapPlan); + + wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) + .Returns(operations); + + wellOperationRepository.GetSectionTypes() + .Returns(sectionTypes); + + wellOperationCategoryRepository.Get(Arg.Any()) + .Returns(operationCategories); + + dataSaubStatRepository.GetAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + .Returns(dataSaubStat); + + service = new ProcessMapReportDataSaubStatService(wellService, processMapPlanBaseRepository, dataSaubStatRepository, wellOperationRepository, wellOperationCategoryRepository); + } + + [Fact] + public async Task GetAsync_return_data() + { + // arrange + DataSaubStatRequest request = new() { }; + + // act + var result = await service.GetAsync(well.Id, request, CancellationToken.None); + + // assert + Assert.NotEmpty(result); + } +} From aa002488fe8afdb8cd2f88393a863ab46e3406ba Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Fri, 16 Feb 2024 11:24:03 +0500 Subject: [PATCH 13/13] =?UTF-8?q?SetpointsRequestDto=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B0=D1=82=D1=80=D0=B8=D0=B1=D1=83?= =?UTF-8?q?=D1=82=20=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=B8=20=D1=83=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D0=B5=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=BE?= =?UTF-8?q?=D1=82=2010=D0=BC=D0=B8=D0=BD=20=D0=B4=D0=BE=204=D1=87=D0=B0?= =?UTF-8?q?=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs | 3 ++- AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs | 7 ------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs b/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs index 5ecb4932..ed81c0ef 100644 --- a/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs +++ b/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs @@ -39,7 +39,8 @@ namespace AsbCloudApp.Data.SAUB /// время в секундах актуальности этого запроса /// [Required] - public int ObsolescenceSec { get; set; } + [Range(10 * 60, 4 * 60 * 60)] + public int ObsolescenceSec { get; set; } = 10 * 60; /// /// набор уставок: {"название переменной панели"; "рекомендуемое значение"} diff --git a/AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs b/AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs index 996c8298..59711fa3 100644 --- a/AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs @@ -18,8 +18,6 @@ namespace AsbCloudWebApi.Controllers.SAUB { private readonly ISetpointsService setpointsService; private readonly IWellService wellService; - private const int ObsolescenceSecMin = 30; - private const int ObsolescenceSecMax = 6 * 60 * 60; public SetpointsController(ISetpointsService setpointsService, IWellService wellService) { @@ -68,11 +66,6 @@ namespace AsbCloudWebApi.Controllers.SAUB setpoints.IdWell = idWell; setpoints.IdState = 1; - if (setpoints is null - || setpoints.ObsolescenceSec > ObsolescenceSecMax - || setpoints.ObsolescenceSec < ObsolescenceSecMin) - return this.ValidationBadRequest(nameof(setpoints.ObsolescenceSec), "Wrong ObsolescenceSec"); - if (!setpoints.Setpoints.Any()) return this.ValidationBadRequest(nameof(setpoints.Setpoints), "Wrong setpoints count");