From e9bd1e478941818293f4b0662db2ef216d7801a6 Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Wed, 14 Dec 2022 08:41:19 +0500 Subject: [PATCH 01/13] #7987467 report --- .../Services/IProcessMapReportService.cs | 20 +++++++ .../AsbCloudInfrastructure.csproj | 2 + AsbCloudInfrastructure/DependencyInjection.cs | 2 + .../ProcessMap/ProcessMapReportService.cs | 55 ++++++++++++++++++ .../ProcessMap/ProcessMapReportTemplate.xlsx | Bin 0 -> 9885 bytes .../Controllers/ProcessMapController.cs | 24 ++++++-- 6 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 AsbCloudApp/Services/IProcessMapReportService.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportTemplate.xlsx diff --git a/AsbCloudApp/Services/IProcessMapReportService.cs b/AsbCloudApp/Services/IProcessMapReportService.cs new file mode 100644 index 00000000..a4bf783b --- /dev/null +++ b/AsbCloudApp/Services/IProcessMapReportService.cs @@ -0,0 +1,20 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services +{ + /// + /// Сервис формирования РТК. + /// + public interface IProcessMapReportService + { + /// + /// Сформировать. + /// + /// + /// + /// + Task MakeReportAsync(int idWell, CancellationToken token = default); + } +} diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj index 622173cc..4b79f7df 100644 --- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj +++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj @@ -12,6 +12,7 @@ + @@ -28,6 +29,7 @@ + diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 34311da8..905dbb0e 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -12,6 +12,7 @@ using AsbCloudInfrastructure.Services; using AsbCloudInfrastructure.Services.DailyReport; using AsbCloudInfrastructure.Services.DetectOperations; using AsbCloudInfrastructure.Services.DrillingProgram; +using AsbCloudInfrastructure.Services.ProcessMap; using AsbCloudInfrastructure.Services.SAUB; using AsbCloudInfrastructure.Services.Subsystems; using AsbCloudInfrastructure.Services.WellOperationService; @@ -134,6 +135,7 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); // admin crud services: services.AddTransient, CrudCacheRepositoryBase>(s => diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs new file mode 100644 index 00000000..4f371642 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs @@ -0,0 +1,55 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using ClosedXML.Excel; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services.ProcessMap +{ + public class ProcessMapReportService : IProcessMapReportService + { + private readonly IAsbCloudDbContext context; + private readonly IProcessMapRepository processMapRepository; + + public ProcessMapReportService(IAsbCloudDbContext context, IProcessMapRepository processMapRepository) + { + this.context = context; + this.processMapRepository = processMapRepository; + } + + public async Task MakeReportAsync(int idWell, CancellationToken token) + { + var dtos = (await processMapRepository.GetByIdWellAsync(idWell, token)) + .GroupBy(x => x.IdWellSectionType); + var stream = GetExcelTemplateStream(); + using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled); + + FillProcessMapToWorkbook(workbook, dtos); + + MemoryStream memoryStream = new MemoryStream(); + workbook.SaveAs(memoryStream, new SaveOptions { }); + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + + private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable> dto) + { + var sheet = workbook.Worksheets.FirstOrDefault(); + if (sheet is null) + return; + + + } + + private Stream GetExcelTemplateStream() + { + var stream = System.Reflection.Assembly.GetExecutingAssembly() + .GetManifestResourceStream("AsbCloudInfrastructure.Services.ProcessMap.ProcessMapReportTemplate.xlsx"); + return stream; + } + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportTemplate.xlsx b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportTemplate.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..52e91ccc430913b57a85bdb42eaadb9bfa7227d4 GIT binary patch literal 9885 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 q0N@`k@>lrZ4b5NStJHsi|890v6_8-N3jm { private readonly ITelemetryService telemetryService; + private readonly IProcessMapReportService processMapReportService; - public ProcessMapController(IWellService wellService, IProcessMapRepository service, + public ProcessMapController(IWellService wellService, IProcessMapRepository repository, IProcessMapReportService processMapReportService, ITelemetryService telemetryService) - : base(wellService, service) + : base(wellService, repository) { this.telemetryService = telemetryService; + this.processMapReportService = processMapReportService; } /// @@ -77,14 +79,28 @@ namespace AsbCloudWebApi.Controllers /// Выгрузка расширенной РТК /// /// + /// /// /// /// [HttpGet] [Route("getReportFile/{wellId}")] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] - public Task GetReportFileAsync(int wellId) + public async Task GetReportFileAsync(int wellId, CancellationToken token) { - throw new NotImplementedException(); + var stream = await processMapReportService.MakeReportAsync(wellId, token); + if (stream != null) + { + var well = await wellService.GetOrDefaultAsync(wellId, token); + if (well is null) + return NoContent(); + else + { + var fileName = $"РТК по скважине {well.Caption} куст {well.Cluster}.xlsx"; + return File(stream, "application/octet-stream", fileName); + } + } + else + return NoContent(); } /// From bfc9376733db657efca8ecbb46af00a496dddfbc Mon Sep 17 00:00:00 2001 From: "ai.astrakhantsev" Date: Tue, 27 Dec 2022 14:30:52 +0500 Subject: [PATCH 02/13] #7987467 + --- .../Data/{ => ProcessMap}/ProcessMapDto.cs | 2 +- .../Data/ProcessMap/ProcessMapReportDto.cs | 62 +++++++ .../ProcessMap/ProcessMapReportParamsDto.cs | 41 +++++ .../Data/ProcessMap/ProcessMapReportRowDto.cs | 51 ++++++ AsbCloudApp/Services/IProcessMapRepository.cs | 2 +- AsbCloudApp/Services/IProcessMapService.cs | 24 +++ AsbCloudApp/Services/IWellOperationService.cs | 8 + AsbCloudDb/Model/WellOperationCategory.cs | 1 - AsbCloudInfrastructure/DependencyInjection.cs | 1 + .../Repository/ProcessMapRepository.cs | 1 + .../.~lock.ProcessMapReportTemplate.xlsx# | 1 + .../ProcessMap/ProcessMapReportService.cs | 49 +++++- .../Services/ProcessMap/ProcessMapService.cs | 159 ++++++++++++++++++ .../WellOperationService.cs | 37 ++++ .../Validators/ProcessMapValidator.cs | 2 +- .../Controllers/ProcessMapController.cs | 2 +- 16 files changed, 431 insertions(+), 12 deletions(-) rename AsbCloudApp/Data/{ => ProcessMap}/ProcessMapDto.cs (98%) create mode 100644 AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs create mode 100644 AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs create mode 100644 AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs create mode 100644 AsbCloudApp/Services/IProcessMapService.cs create mode 100644 AsbCloudInfrastructure/Services/ProcessMap/.~lock.ProcessMapReportTemplate.xlsx# create mode 100644 AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs diff --git a/AsbCloudApp/Data/ProcessMapDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapDto.cs similarity index 98% rename from AsbCloudApp/Data/ProcessMapDto.cs rename to AsbCloudApp/Data/ProcessMap/ProcessMapDto.cs index 72990b03..9a460acb 100644 --- a/AsbCloudApp/Data/ProcessMapDto.cs +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapDto.cs @@ -1,6 +1,6 @@ using System; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data.ProcessMap { #nullable enable /// diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs new file mode 100644 index 00000000..51e77911 --- /dev/null +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs @@ -0,0 +1,62 @@ +using System; + +namespace AsbCloudApp.Data.ProcessMap +{ +#nullable enable + /// + /// Модель РТК + /// + public class ProcessMapReportDto + { + /// + /// Идентификатор скважины + /// + public int IdWell { get; set; } + + /// + /// Глубина по стволу, м + /// + public double Depth { get; set; } + + /// + /// Дата/ время + /// + public DateTimeOffset Date { get; set; } + + /// + /// Т мех бурения, ч + /// + public double MechDrillingTime { get; set; } + + /// + /// Слайд + /// + public ProcessMapReportRowDto Slide { get; set; } = null!; + + /// + /// Ротор + /// + public ProcessMapReportRowDto Rotor { get; set; } = null!; + + /// + /// название секции скважины + /// + public string? WellSectionTypeName { get; set; } + + /// + /// название секции скважины + /// + public int? IdWellSectionType { get; set; } + + /// + /// Категория + /// + public string? Category { get; set; } + + /// + /// Идентификатор категории + /// + public int? IdCategory { get; set; } + } +#nullable disable +} diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs new file mode 100644 index 00000000..6136d144 --- /dev/null +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsbCloudApp.Data.ProcessMap +{ +#nullable enable + /// + /// Параметры РТК + /// + public class ProcessMapReportParamsDto + { + /// + /// Уставка план + /// + public double SetPointPlan { get; set; } + + /// + /// Уставка факт + /// + public double? SetPointFact { get; set; } + + /// + /// Факт + /// + public double? Fact { get; set; } + + /// + /// Ограничение + /// + public double? Limit { get; set; } + + /// + /// Процент бурения по уставке ,% + /// + public double? PercDrillingSetPoint { get; set; } + } +#nullable disable +} diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs new file mode 100644 index 00000000..6b4e942d --- /dev/null +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsbCloudApp.Data.ProcessMap +{ +#nullable enable + /// + /// Строки РТК + /// + public class ProcessMapReportRowDto + { + /// + /// Перепад давления, атм + /// + public ProcessMapReportParamsDto PressureDrop { get; set; } = null!; + + /// + /// Нагрузка, т + /// + public ProcessMapReportParamsDto Load { get; set; } = null!; + + /// + /// Момент на ВСП, кНхМ + /// + public ProcessMapReportParamsDto TopDriveTorque { get; set; } = null!; + + /// + /// Ограничение скорости, м/ч + /// + public ProcessMapReportParamsDto SpeedL​imit { get; set; } = null!; + + /// + /// Процент использования системы АПД, % + /// + public double PercentageADFSystemUsage { get; set; } + + /// + /// Фактическая механическая скорость, м/ч + /// + public double ActualMechanicalSpeed { get; set; } + + /// + /// Проходка, м + /// + public double? SectionPenetration { get; set; } + } +#nullable disable +} diff --git a/AsbCloudApp/Services/IProcessMapRepository.cs b/AsbCloudApp/Services/IProcessMapRepository.cs index a898fa4a..8c9ab6f0 100644 --- a/AsbCloudApp/Services/IProcessMapRepository.cs +++ b/AsbCloudApp/Services/IProcessMapRepository.cs @@ -1,4 +1,4 @@ -using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMap; using System; using System.Collections.Generic; using System.Threading; diff --git a/AsbCloudApp/Services/IProcessMapService.cs b/AsbCloudApp/Services/IProcessMapService.cs new file mode 100644 index 00000000..3d2eeff4 --- /dev/null +++ b/AsbCloudApp/Services/IProcessMapService.cs @@ -0,0 +1,24 @@ +using AsbCloudApp.Data.ProcessMap; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services +{ +#nullable enable + /// + /// Сервис формирования РТК + /// + public interface IProcessMapService + { + /// + /// Получение моделей РТК + /// + /// + /// + /// + Task> GetProcessMapAsync(int idWell, CancellationToken token); + } +#nullable disable +} diff --git a/AsbCloudApp/Services/IWellOperationService.cs b/AsbCloudApp/Services/IWellOperationService.cs index ea1aa9b0..b4ac83d4 100644 --- a/AsbCloudApp/Services/IWellOperationService.cs +++ b/AsbCloudApp/Services/IWellOperationService.cs @@ -121,5 +121,13 @@ namespace AsbCloudApp.Services /// /// DateTimeOffset? FirstOperationDate(int idWell); + + /// + /// Получение операций по идентификатору скважины + /// + /// + /// + /// + Task> GetOperationsByIdWellAsync(int idWell, CancellationToken token); } } diff --git a/AsbCloudDb/Model/WellOperationCategory.cs b/AsbCloudDb/Model/WellOperationCategory.cs index 4cafa51e..3781a9e6 100644 --- a/AsbCloudDb/Model/WellOperationCategory.cs +++ b/AsbCloudDb/Model/WellOperationCategory.cs @@ -2,7 +2,6 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; -using System; namespace AsbCloudDb.Model { diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 905dbb0e..c9fe96ea 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -136,6 +136,7 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); // admin crud services: services.AddTransient, CrudCacheRepositoryBase>(s => diff --git a/AsbCloudInfrastructure/Repository/ProcessMapRepository.cs b/AsbCloudInfrastructure/Repository/ProcessMapRepository.cs index eb2eadac..f24ce61d 100644 --- a/AsbCloudInfrastructure/Repository/ProcessMapRepository.cs +++ b/AsbCloudInfrastructure/Repository/ProcessMapRepository.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMap; using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; diff --git a/AsbCloudInfrastructure/Services/ProcessMap/.~lock.ProcessMapReportTemplate.xlsx# b/AsbCloudInfrastructure/Services/ProcessMap/.~lock.ProcessMapReportTemplate.xlsx# new file mode 100644 index 00000000..8c2b057a --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMap/.~lock.ProcessMapReportTemplate.xlsx# @@ -0,0 +1 @@ +,ASB/andas,asb,19.12.2022 11:39,file:///C:/Users/andas/AppData/Roaming/LibreOffice/4; \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs index 4f371642..fa80efe4 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs @@ -1,6 +1,7 @@ -using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMap; using AsbCloudApp.Services; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.DailyReport; using ClosedXML.Excel; using System.Collections.Generic; using System.IO; @@ -10,25 +11,35 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.ProcessMap { +#nullable enable public class ProcessMapReportService : IProcessMapReportService { private readonly IAsbCloudDbContext context; private readonly IProcessMapRepository processMapRepository; + private readonly IProcessMapService processMapService; - public ProcessMapReportService(IAsbCloudDbContext context, IProcessMapRepository processMapRepository) + public ProcessMapReportService(IAsbCloudDbContext context, IProcessMapRepository processMapRepository, IProcessMapService processMapService) { this.context = context; this.processMapRepository = processMapRepository; + this.processMapService = processMapService; } public async Task MakeReportAsync(int idWell, CancellationToken token) { - var dtos = (await processMapRepository.GetByIdWellAsync(idWell, token)) - .GroupBy(x => x.IdWellSectionType); var stream = GetExcelTemplateStream(); using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled); - FillProcessMapToWorkbook(workbook, dtos); + var data = processMapService.GetProcessMapAsync(idWell, token); + + //var dtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false); + //if (dtos is not null) + //{ + // var processMapReportDto = await processMapService.GetProcessMapAsync(dtos, token).ConfigureAwait(false); + // FillProcessMapToWorkbook(workbook, processMapReportDto); + //} + + FillProcessMapToWorkbook(workbook, new List()); MemoryStream memoryStream = new MemoryStream(); workbook.SaveAs(memoryStream, new SaveOptions { }); @@ -36,20 +47,44 @@ namespace AsbCloudInfrastructure.Services.ProcessMap return memoryStream; } - private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable> dto) + private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable dto) { + var rowsCount = 4; + var columnCount = 2; + var countMerge = 27; + var sheet = workbook.Worksheets.FirstOrDefault(); if (sheet is null) return; + sheet.Row(rowsCount).Cell(columnCount).Value = "saddadasdasdasds"; + sheet.Range(rowsCount, columnCount, rowsCount, countMerge).Row(1).Merge(); + SetBorder(sheet.Row(rowsCount).Cell(columnCount).Style); + + rowsCount++; + sheet.Row(rowsCount).Cell(columnCount).Value = 2; + sheet.Row(rowsCount).Cell(columnCount).Value = 3; + columnCount++; + sheet.Row(rowsCount).Cell(columnCount).Value = 4; } private Stream GetExcelTemplateStream() { var stream = System.Reflection.Assembly.GetExecutingAssembly() .GetManifestResourceStream("AsbCloudInfrastructure.Services.ProcessMap.ProcessMapReportTemplate.xlsx"); - return stream; + return stream!; + } + + private static IXLStyle SetBorder(IXLStyle style) + { + style.Border.RightBorder = XLBorderStyleValues.Medium; + style.Border.LeftBorder = XLBorderStyleValues.Medium; + style.Border.TopBorder = XLBorderStyleValues.Medium; + style.Border.BottomBorder = XLBorderStyleValues.Medium; + style.Border.InsideBorder = XLBorderStyleValues.Medium; + return style; } } +#nullable disable } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs new file mode 100644 index 00000000..180b6ba1 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs @@ -0,0 +1,159 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMap; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using DocumentFormat.OpenXml.Bibliography; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services.ProcessMap +{ +#nullable enable + public class ProcessMapService : IProcessMapService + { + private readonly IWellOperationService wellOperationService; + private readonly IProcessMapRepository processMapRepository; + + public ProcessMapService(IWellOperationService wellOperationService, + IProcessMapRepository processMapRepository) + { + this.wellOperationService = wellOperationService; + this.processMapRepository = processMapRepository; + } + + public async Task> GetProcessMapAsync(int idWell, CancellationToken token) + { + var categoryIds = new int[] { WellOperationCategory.IdSlide, WellOperationCategory.IdRotor }; + var allOperations = (await wellOperationService.GetOperationsByIdWellAsync(idWell, token).ConfigureAwait(false)) + .Where(x => categoryIds.Contains(x.IdCategory)) + .Where(x => x.IdType == 1) + .OrderBy(x => x.IdWellSectionType) + .ThenBy(x => x.DateStart) + .ToList(); + var processMapDtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false); + + var result = allOperations + .GroupBy(x => x.IdWellSectionType) + .SelectMany(x => handleSections(allOperations, processMapDtos!, x)) + .ToList(); + + return result; + } + + private static List handleSections(IEnumerable allWellOperation, IEnumerable processMap, IEnumerable wellOperation) + { + var result = new List(); + var minDepth = wellOperation.Min(o => o.DepthStart); + var maxDepth = wellOperation.Max(o => o.DepthEnd); + + for (var depth = minDepth; depth <= maxDepth; depth += 100) + { + var currentDepth = result.Count() > 0 ? depth + (100 - depth % 100) : depth; + var operation = allWellOperation.First(x => x.DepthEnd >= currentDepth); + var minDate = operation.DateStart; + var maxDate = operation.DateStart.AddHours(operation.DurationHours); + var currentDate = GetDate(currentDepth, minDepth, maxDepth, minDate, maxDate); + var currentHours = GetHourse(currentDepth, minDepth, maxDepth, operation.DurationHours); + var processMapData = processMap.FirstOrDefault(x => x.IdWellSectionType == operation.IdWellSectionType); + + var dto = GetRecord(currentDepth, currentDate, currentHours, operation, processMap); + + if (operation.DepthStart < currentDepth) + { + var prevOperation = allWellOperation.FirstOrDefault(x => x.DepthEnd == operation.DepthStart); + if (prevOperation is not null) + { + var prevDepth = currentDepth - prevOperation.DepthEnd; + var prevMinDate = prevOperation.DateStart; + var prevMaxDate = operation.DateStart.AddHours(operation.DurationHours); + var prevDate = GetDate(prevDepth, prevOperation.DepthStart, prevOperation.DepthEnd, minDate, maxDate); + var prevHours = GetHourse(currentDepth, prevOperation.DepthStart, prevOperation.DepthEnd, prevOperation.DurationHours); + + if (dto.IdCategory != prevOperation.IdCategory) + FillRecordRow(prevDepth, prevHours, dto, prevOperation.IdCategory, processMap); + + dto.MechDrillingTime = currentHours + prevHours; + } + } + + result.Add(dto); + } + + return result; + } + + private static ProcessMapReportDto GetRecord(double depth, DateTimeOffset sate, double hours, WellOperationDto operation, IEnumerable processMap) + { + var dto = new ProcessMapReportDto + { + IdWell = operation.IdWell, + Depth = depth, + Date = sate, + MechDrillingTime = hours, + Category = operation.IdCategory == WellOperationCategory.IdSlide ? "Слайд" : "Ротор", + IdCategory = operation.IdCategory, + IdWellSectionType = operation.IdWellSectionType, + WellSectionTypeName = operation.WellSectionTypeName + }; + FillRecordRow(depth, hours, dto, operation.IdCategory, processMap); + + return dto; + } + + private static void FillRecordRow(double depth, double hours, ProcessMapReportDto dto, int idCategory, IEnumerable processMap) + { + var row = new ProcessMapReportRowDto { + SectionPenetration = depth, + ActualMechanicalSpeed = depth / hours, + PercentageADFSystemUsage = dto.Depth / depth * 100 + }; + + var processMapData = processMap.FirstOrDefault(x => x.IdWell == dto.IdWell && x.IdWellSectionType == dto.IdWellSectionType); + if (processMapData is not null) + { + row.PressureDrop = new ProcessMapReportParamsDto + { + SetPointPlan = processMapData.Pressure.Plan + }; + row.Load = new ProcessMapReportParamsDto + { + SetPointPlan = processMapData.AxialLoad.Plan + }; + row.TopDriveTorque = new ProcessMapReportParamsDto + { + SetPointPlan = processMapData.TopDriveTorque.Plan + }; + row.SpeedL​imit = new ProcessMapReportParamsDto + { + + }; + } + + if (idCategory == WellOperationCategory.IdSlide) + dto.Slide = row; + else + dto.Rotor = row; + } + + private static DateTimeOffset GetDate(double depth, double deptStart, double deptEnd, DateTimeOffset dateStart, DateTimeOffset dateEnd) + { + var a = depth - deptStart; + var b = deptEnd - deptStart; + var c = dateEnd - dateStart; + var result = dateStart + (a / b) * c; + return result; + } + + private static double GetHourse(double depth, double deptStart, double deptEnd, double hourse) + { + var a = depth - deptStart; + var b = deptEnd - deptStart; + var result = 0 + (a / b) * hourse; + return result; + } + } +#nullable disable +} diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs index 6e0d02d6..78870858 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs @@ -139,6 +139,43 @@ namespace AsbCloudInfrastructure.Services.WellOperationService return result; } + public async Task> GetOperationsByIdWellAsync(int idWell, CancellationToken token) + { + var timezone = wellService.GetTimezone(idWell); + var query = BuildQuery(idWell); + var dateStart = query.Min(o => o.DateStart); + + query = query + .OrderBy(e => e.DateStart) + .ThenBy(e => e.DepthEnd) + .ThenBy(e => e.Id); + + var entities = await query.AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var nptHours = 0d; + var result = new List(); + + foreach (var entity in entities) + { + var dto = entity.Adapt(); + dto.Day = (entity.DateStart - dateStart).TotalDays; + dto.WellSectionTypeName = entity.WellSectionType.Caption; + dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours); + dto.CategoryName = entity.OperationCategory.Name; + if (entity.IdType == idOperationTypeFact) + { + if (WellOperationCategory.NonProductiveTimeSubIds.Contains(entity.IdCategory)) + nptHours += entity.DurationHours; + dto.NptHours = nptHours; + } + result.Add(dto); + } + + return result; + } + public async Task> GetGroupOperationsStatAsync( int idWell, int? operationType = default, diff --git a/AsbCloudInfrastructure/Validators/ProcessMapValidator.cs b/AsbCloudInfrastructure/Validators/ProcessMapValidator.cs index 22de04ad..661d01be 100644 --- a/AsbCloudInfrastructure/Validators/ProcessMapValidator.cs +++ b/AsbCloudInfrastructure/Validators/ProcessMapValidator.cs @@ -1,4 +1,4 @@ -using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMap; using FluentValidation; namespace AsbCloudInfrastructure.Validators diff --git a/AsbCloudWebApi/Controllers/ProcessMapController.cs b/AsbCloudWebApi/Controllers/ProcessMapController.cs index a80e1758..f5c955aa 100644 --- a/AsbCloudWebApi/Controllers/ProcessMapController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMapController.cs @@ -1,4 +1,4 @@ -using AsbCloudApp.Data; +using AsbCloudApp.Data.ProcessMap; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; From 7585aefc4e2e68443b491248fffb6cb60ee04ebe Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 28 Dec 2022 17:38:53 +0500 Subject: [PATCH 03/13] WellOperationService to WellOperationRepository --- .../IWellOperationRepository.cs} | 117 ++++----- AsbCloudDb/Model/WellOperation.cs | 6 + AsbCloudInfrastructure/DependencyInjection.cs | 2 +- .../WellOperationRepository.cs} | 205 +++++++-------- .../.~lock.ProcessMapReportTemplate.xlsx# | 1 - .../Services/ProcessMap/ProcessMapService.cs | 37 +-- .../OperationsStatService.cs | 17 +- .../WellOperationRepository.cs | 242 ------------------ .../Services/WellService.cs | 7 +- .../Controllers/WellOperationController.cs | 23 +- ConsoleApp1/Program.cs | 21 +- ConsoleApp1/ServiceFactory.cs | 3 +- 12 files changed, 219 insertions(+), 462 deletions(-) rename AsbCloudApp/{Services/IWellOperationService.cs => Repositories/IWellOperationRepository.cs} (75%) rename AsbCloudInfrastructure/{Services/WellOperationService/WellOperationService.cs => Repository/WellOperationRepository.cs} (71%) delete mode 100644 AsbCloudInfrastructure/Services/ProcessMap/.~lock.ProcessMapReportTemplate.xlsx# delete mode 100644 AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs diff --git a/AsbCloudApp/Services/IWellOperationService.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs similarity index 75% rename from AsbCloudApp/Services/IWellOperationService.cs rename to AsbCloudApp/Repositories/IWellOperationRepository.cs index 3fdbc1a4..4075445f 100644 --- a/AsbCloudApp/Services/IWellOperationService.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -5,13 +5,13 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Repositories { #nullable enable /// /// сервис операций по скважине /// - public interface IWellOperationService + public interface IWellOperationRepository { /// /// список названий операций @@ -19,61 +19,6 @@ namespace AsbCloudApp.Services /// IEnumerable GetCategories(); - // TODO: объединить параметры в объект запроса - /// - /// Получить список операций - /// - /// - /// - /// - Task> GetOperationsAsync( - WellOperationRequest request, - CancellationToken token); - - /// - /// Получить статистику операции по скважине с группировкой по категориям - /// - /// - /// - /// - Task> GetGroupOperationsStatAsync( - WellOperationRequest request, - CancellationToken token); - - /// - /// Получить операцию по id - /// - /// - /// - /// - Task GetOrDefaultAsync(int id, CancellationToken token); - - /// - /// Добавить несколько операций за один раз - /// - /// - /// - /// - Task InsertRangeAsync( - IEnumerable wellOperationDtos, CancellationToken token); - - /// - /// Обновить существующую операцию - /// - /// - /// - /// - Task UpdateAsync(WellOperationDto item, - CancellationToken token); - - /// - /// Удалить операции по id - /// - /// - /// - /// - Task DeleteAsync(IEnumerable ids, CancellationToken token); - /// /// Список секций /// @@ -88,12 +33,62 @@ namespace AsbCloudApp.Services DateTimeOffset? FirstOperationDate(int idWell); /// - /// Получение операций по идентификатору скважины + /// Получить страницу списка операций /// - /// + /// /// /// - Task> GetOperationsByIdWellAsync(int idWell, CancellationToken token); + Task> GetAsync(WellOperationRequest request, CancellationToken token); + + /// + /// Получить страницу списка операций + /// + /// + /// + /// + Task> GetPageAsync(WellOperationRequest request, CancellationToken token); + + /// + /// Получить операцию по id + /// + /// + /// + /// + Task GetOrDefaultAsync(int id, CancellationToken token); + + /// + /// Получить статистику операции по скважине с группировкой по категориям + /// + /// + /// + /// + Task> GetGroupOperationsStatAsync( + WellOperationRequest request, + CancellationToken token); + + /// + /// Добавить несколько операций за один раз + /// + /// + /// + /// + Task InsertRangeAsync(IEnumerable wellOperationDtos, CancellationToken token); + + /// + /// Обновить существующую операцию + /// + /// + /// + /// + Task UpdateAsync(WellOperationDto dto, CancellationToken token); + + /// + /// Удалить операции по id + /// + /// + /// + /// + Task DeleteAsync(IEnumerable ids, CancellationToken token); } #nullable disable -} +} \ No newline at end of file diff --git a/AsbCloudDb/Model/WellOperation.cs b/AsbCloudDb/Model/WellOperation.cs index 8ef65c91..4abe21fb 100644 --- a/AsbCloudDb/Model/WellOperation.cs +++ b/AsbCloudDb/Model/WellOperation.cs @@ -10,6 +10,9 @@ namespace AsbCloudDb.Model [Table("t_well_operation"), Comment("Данные по операциям на скважине")] public class WellOperation : IId { + public const int IdOperationTypePlan = 0; + public const int IdOperationTypeFact = 1; + [Key] [Column("id")] public int Id { get; set; } @@ -23,6 +26,9 @@ namespace AsbCloudDb.Model [Column("id_category"), Comment("Id категории операции")] public int IdCategory { get; set; } + /// + /// Тип 0 = План или 1 = Факт + /// [Column("id_type"), Comment("0 = План или 1 = Факт")] public int IdType { get; set; } diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index fae6f304..fe64742a 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -124,7 +124,7 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs similarity index 71% rename from AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs rename to AsbCloudInfrastructure/Repository/WellOperationRepository.cs index 5f0e90f1..bb958034 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -9,35 +9,31 @@ using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; +using System.Threading; +using AsbCloudApp.Repositories; -namespace AsbCloudInfrastructure.Services.WellOperationService +namespace AsbCloudInfrastructure.Repository { #nullable enable - public class WellOperationService : IWellOperationService + /// + /// репозиторий операций по скважине + /// + public class WellOperationRepository : IWellOperationRepository { private readonly IAsbCloudDbContext db; private readonly IMemoryCache memoryCache; private readonly IWellService wellService; + private static Dictionary? firstOperationsCache = null; - private Dictionary? firstOperationsCache = null; - - public const int idOperationTypePlan = 0; - public const int idOperationTypeFact = 1; - - public WellOperationService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService) + public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService) { this.db = db; this.memoryCache = memoryCache; this.wellService = wellService; } - public IDictionary GetSectionTypes() - => memoryCache - .GetOrCreateBasic(db) - .ToDictionary(s => s.Id, s => s.Caption); - + /// public IEnumerable GetCategories() { var allCategories = memoryCache @@ -56,6 +52,13 @@ namespace AsbCloudInfrastructure.Services.WellOperationService return result; } + /// + public IDictionary GetSectionTypes() + => memoryCache + .GetOrCreateBasic(db) + .ToDictionary(s => s.Id, s => s.Caption); + + /// public DateTimeOffset? FirstOperationDate(int idWell) { if (firstOperationsCache is null) @@ -65,8 +68,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService .Select(g => new Tuple ( g.Key, - g.Where(o => o.IdType == idOperationTypePlan).Min(o => o.DateStart), - g.Where(o => o.IdType == idOperationTypeFact).Min(o => o.DateStart) + g.Where(o => o.IdType == WellOperation.IdOperationTypePlan).Min(o => o.DateStart), + g.Where(o => o.IdType == WellOperation.IdOperationTypeFact).Min(o => o.DateStart) )); firstOperationsCache = query @@ -76,13 +79,24 @@ namespace AsbCloudInfrastructure.Services.WellOperationService return firstOperationsCache?.GetValueOrDefault(idWell); } - public async Task> GetOperationsAsync( + /// + public async Task> GetAsync( WellOperationRequest request, CancellationToken token) { - var timezone = wellService.GetTimezone(request.IdWell); + var query = BuildQuery(request) + .AsNoTracking(); + var result = await query.ToArrayAsync(token); + return result; + } - var query = BuildQuery(request); + /// + public async Task> GetPageAsync( + WellOperationRequest request, + CancellationToken token) + { + var query = BuildQuery(request) + .AsNoTracking(); var result = new PaginationContainer { @@ -91,81 +105,45 @@ namespace AsbCloudInfrastructure.Services.WellOperationService Count = await query.CountAsync(token).ConfigureAwait(false), }; - if (result.Skip > 0) - query = query.Skip(result.Skip!); - - var entities = await query.Take(result.Take).AsNoTracking() - .ToListAsync(token).ConfigureAwait(false); - - if (!entities.Any()) - return result; - - var nptHours = 0d; - - var dateStart = query.Min(o => o.DateStart); - foreach (var entity in entities) - { - var dto = entity.Adapt(); - dto.Day = (entity.DateStart - dateStart).TotalDays; - dto.WellSectionTypeName = entity.WellSectionType.Caption; - dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours); - dto.CategoryName = entity.OperationCategory.Name; - if (entity.IdType == idOperationTypeFact) - { - if (WellOperationCategory.NonProductiveTimeSubIds.Contains(entity.IdCategory)) - nptHours += entity.DurationHours; - dto.NptHours = nptHours; - } - result.Items.Add(dto); - } + query = query + .Skip(result.Skip) + .Take(result.Take); + result.Items = await query.ToListAsync(token); return result; } - public async Task> GetOperationsByIdWellAsync(int idWell, CancellationToken token) + /// + public async Task GetOrDefaultAsync(int id, + CancellationToken token) { - var timezone = wellService.GetTimezone(idWell); - var query = BuildQuery(idWell); - var dateStart = query.Min(o => o.DateStart); - - query = query - .OrderBy(e => e.DateStart) - .ThenBy(e => e.DepthEnd) - .ThenBy(e => e.Id); - - var entities = await query.AsNoTracking() - .ToListAsync(token) + var entity = await db.WellOperations + .Include(s => s.WellSectionType) + .Include(s => s.OperationCategory) + .FirstOrDefaultAsync(e => e.Id == id, token) .ConfigureAwait(false); - var nptHours = 0d; - var result = new List(); + if (entity is null) + return null; - foreach (var entity in entities) - { - var dto = entity.Adapt(); - dto.Day = (entity.DateStart - dateStart).TotalDays; - dto.WellSectionTypeName = entity.WellSectionType.Caption; - dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours); - dto.CategoryName = entity.OperationCategory.Name; - if (entity.IdType == idOperationTypeFact) - { - if (WellOperationCategory.NonProductiveTimeSubIds.Contains(entity.IdCategory)) - nptHours += entity.DurationHours; - dto.NptHours = nptHours; - } - result.Add(dto); - } + var timezone = wellService.GetTimezone(entity.IdWell); - return result; + var dto = entity.Adapt(); + dto.WellSectionTypeName = entity.WellSectionType.Caption; + dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours); + dto.CategoryName = entity.OperationCategory.Name; + return dto; } + /// public async Task> GetGroupOperationsStatAsync( WellOperationRequest request, CancellationToken token) { - var query = BuildQuery(request); + var query = BuildQuery(request); var entities = await query - .Select(o => new { + .Select(o => new + { o.IdCategory, DurationMinutes = o.DurationHours * 60, DurationDepth = o.DepthEnd - o.DepthStart @@ -200,7 +178,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService .GroupBy(o => o.IdParent) .Select(g => new WellGroupOpertionDto { - IdCategory = g.Key.HasValue ? g.Key.Value : defaultId, + IdCategory = g.Key ?? defaultId, Category = g.Key.HasValue ? parentRelationDictionary[g.Key.Value].Name : "unknown", Count = g.Sum(o => o.Count), DeltaDepth = g.Sum(o => o.DeltaDepth), @@ -212,27 +190,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService return dtos; } - public async Task GetOrDefaultAsync(int id, - CancellationToken token) - { - var entity = await db.WellOperations - .Include(s => s.WellSectionType) - .Include(s => s.OperationCategory) - .FirstOrDefaultAsync(e => e.Id == id, token) - .ConfigureAwait(false); - - if (entity is null) - return null; - - var timezone = wellService.GetTimezone(entity.IdWell); - - var dto = entity.Adapt(); - dto.WellSectionTypeName = entity.WellSectionType.Caption; - dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours); - dto.CategoryName = entity.OperationCategory.Name; - return dto; - } - + /// public async Task InsertRangeAsync( IEnumerable wellOperationDtos, CancellationToken token) @@ -258,6 +216,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService .ConfigureAwait(false); } + /// public async Task UpdateAsync( WellOperationDto dto, CancellationToken token) { @@ -269,6 +228,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService .ConfigureAwait(false); } + /// public async Task DeleteAsync(IEnumerable ids, CancellationToken token) { @@ -278,14 +238,55 @@ namespace AsbCloudInfrastructure.Services.WellOperationService .ConfigureAwait(false); } - private IQueryable BuildQuery(WellOperationRequest request) + /// + /// В результате попрежнему требуется конвертировать дату + /// + /// + /// + private IQueryable BuildQuery(WellOperationRequest request) { var timezone = wellService.GetTimezone(request.IdWell); + var timeZoneOffset = TimeSpan.FromHours(timezone.Hours); var query = db.WellOperations .Include(s => s.WellSectionType) .Include(s => s.OperationCategory) - .Where(s => s.IdWell == request.IdWell); + .Where(o => o.IdWell == request.IdWell) + .Select(o => new WellOperationDto + { + Id = o.Id, + IdType = o.IdType, + IdWell = o.IdWell, + IdWellSectionType = o.IdWellSectionType, + IdCategory = o.IdCategory, + + //o.Well, + //o.OperationCategory, + CategoryName = o.WellSectionType.Caption, + WellSectionTypeName = o.WellSectionType.Caption, + + DateStart = DateTime.SpecifyKind( o.DateStart.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified), + DepthStart = o.DepthStart, + DepthEnd = o.DepthEnd, + DurationHours = o.DurationHours, + CategoryInfo = o.CategoryInfo, + Comment = o.Comment, + + NptHours = db.WellOperations + .Where(subOp => subOp.IdWell == request.IdWell) + .Where(subOp => subOp.IdType == 1) + .Where(subOp => WellOperationCategory.NonProductiveTimeSubIds.Contains(subOp.IdCategory)) + .Where(subOp => subOp.DateStart <= o.DateStart) + .Select(subOp => subOp.DurationHours) + .Sum(), + + Day = (o.DateStart - db.WellOperations + .Where(subOp => subOp.IdWell == request.IdWell) + .Where(subOp => subOp.IdType == o.IdType) + .Where(subOp => subOp.DateStart <= o.DateStart) + .Min(subOp => subOp.DateStart)) + .TotalHours, + }); if (request.OperationType.HasValue) query = query.Where(e => e.IdType == request.OperationType.Value); diff --git a/AsbCloudInfrastructure/Services/ProcessMap/.~lock.ProcessMapReportTemplate.xlsx# b/AsbCloudInfrastructure/Services/ProcessMap/.~lock.ProcessMapReportTemplate.xlsx# deleted file mode 100644 index 8c2b057a..00000000 --- a/AsbCloudInfrastructure/Services/ProcessMap/.~lock.ProcessMapReportTemplate.xlsx# +++ /dev/null @@ -1 +0,0 @@ -,ASB/andas,asb,19.12.2022 11:39,file:///C:/Users/andas/AppData/Roaming/LibreOffice/4; \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs index 180b6ba1..0dfab7df 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs @@ -1,8 +1,9 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMap; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; -using DocumentFormat.OpenXml.Bibliography; using System; using System.Collections.Generic; using System.Linq; @@ -14,33 +15,37 @@ namespace AsbCloudInfrastructure.Services.ProcessMap #nullable enable public class ProcessMapService : IProcessMapService { - private readonly IWellOperationService wellOperationService; + private readonly IWellOperationRepository wellOperationRepository; private readonly IProcessMapRepository processMapRepository; - public ProcessMapService(IWellOperationService wellOperationService, + public ProcessMapService(IWellOperationRepository wellOperationService, IProcessMapRepository processMapRepository) { - this.wellOperationService = wellOperationService; + this.wellOperationRepository = wellOperationService; this.processMapRepository = processMapRepository; } public async Task> GetProcessMapAsync(int idWell, CancellationToken token) { var categoryIds = new int[] { WellOperationCategory.IdSlide, WellOperationCategory.IdRotor }; - var allOperations = (await wellOperationService.GetOperationsByIdWellAsync(idWell, token).ConfigureAwait(false)) - .Where(x => categoryIds.Contains(x.IdCategory)) - .Where(x => x.IdType == 1) - .OrderBy(x => x.IdWellSectionType) - .ThenBy(x => x.DateStart) - .ToList(); - var processMapDtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false); - var result = allOperations - .GroupBy(x => x.IdWellSectionType) - .SelectMany(x => handleSections(allOperations, processMapDtos!, x)) - .ToList(); + var operationsRequest = new WellOperationRequest + { + IdWell = idWell, + OperationCategoryIds = categoryIds, + OperationType = 1, + SortFields = new[]{ nameof(WellOperation.DateStart) } + }; + var allOperations = await wellOperationRepository.GetPageAsync(operationsRequest, token); + throw new NotImplementedException(); + //var processMapDtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false); - return result; + //var result = allOperations + // .GroupBy(x => x.IdWellSectionType) + // .SelectMany(x => handleSections(allOperations, processMapDtos!, x)) + // .ToList(); + + //return result; } private static List handleSections(IEnumerable allWellOperation, IEnumerable processMap, IEnumerable wellOperation) diff --git a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs index 116b23de..b9daba10 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs @@ -134,7 +134,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService var wellType = (await memoryCache .GetOrCreateBasicAsync(db, token)) .FirstOrDefault(t => t.Id == well.IdWellType); - var statWellDto = new StatWellDto() + var statWellDto = new StatWellDto { Id = well.Id, Caption = well.Caption, @@ -142,10 +142,9 @@ namespace AsbCloudInfrastructure.Services.WellOperationService IdState = well.IdState, State = wellService.GetStateText(well.IdState), LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id).DateTime, + Companies = await wellService.GetCompaniesAsync(well.Id, token) }; - statWellDto.Companies = await wellService.GetCompaniesAsync(well.Id, token); - if (well.WellOperations is null) return statWellDto; @@ -175,8 +174,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService .ToDictionary(s => s.Id); var sections = new List(sectionTypes.Count); - var operationsPlan = operations.Where(o => o.IdType == WellOperationService.idOperationTypePlan); - var operationsFact = operations.Where(o => o.IdType == WellOperationService.idOperationTypeFact); + var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan); + var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact); foreach ((var id, var sectionType) in sectionTypes) { @@ -195,8 +194,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService private static PlanFactBase GetStatTotal(IEnumerable operations, int idWellState, double timezoneOffsetH) { - var operationsPlan = operations.Where(o => o.IdType == WellOperationService.idOperationTypePlan); - var operationsFact = operations.Where(o => o.IdType == WellOperationService.idOperationTypeFact); + var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan); + var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact); var factEnd = CalcStat(operationsFact, timezoneOffsetH); if (factEnd is not null && idWellState != 2) factEnd.End = null; @@ -369,12 +368,12 @@ namespace AsbCloudInfrastructure.Services.WellOperationService .ConfigureAwait(false); var wellOperationsPlan = wellOperations - .Where(o => o.IdType == WellOperationService.idOperationTypePlan) + .Where(o => o.IdType == WellOperation.IdOperationTypePlan) .OrderBy(o => o.DateStart) .ThenBy(o => o.DepthEnd); var wellOperationsFact = wellOperations - .Where(o => o.IdType == WellOperationService.idOperationTypeFact) + .Where(o => o.IdType == WellOperation.IdOperationTypeFact) .OrderBy(o => o.DateStart) .ThenBy(o => o.DepthEnd); diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs deleted file mode 100644 index 6251bae9..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs +++ /dev/null @@ -1,242 +0,0 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Requests; -using AsbCloudApp.Services; -using AsbCloudDb; -using AsbCloudDb.Model; -using Mapster; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Caching.Memory; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.Threading; -using System.Collections; - -namespace AsbCloudInfrastructure.Services.WellOperationService -{ -#nullable enable - - - /* - var opsQuery = db.WellOperations - .Where( o => o.IdWell == idWell ) - .Where( o => o.IdType == idType ) - .Select( o => new { - o.Id, - o.IdType, - o.IdWell, - o.IdWellSectionType, - o.IdCategory, - - o.Well, - o.WellSectionType, - o.OperationCategory, - - o.DateStart, - o.DepthStart, - o.DepthEnd, - o.DurationHours, - o.CategoryInfo, - o.Comment, - - nptHours = db.WellOperations - .Where(subOp => subOp.IdWell == idWell) - .Where(subOp => subOp.IdType == idType) - .Where(subOp => nptCats.Contains( subOp.IdCategory )) - .Where(subOp => subOp.DateStart <= o.DateStart) - .Select(subOp => subOp.DurationHours) - .Sum(), - Day = o.DateStart - db.WellOperations - .Where(subOp => subOp.IdWell == idWell) - .Where(subOp => subOp.IdType == idType) - .Where(subOp => subOp.DateStart <= o.DateStart) - .Min(subOp => subOp.DateStart), - }) - .OrderBy(o => o.DateStart); - */ - public class WellOperationRepository - { - private readonly IAsbCloudDbContext db; - private readonly IMemoryCache memoryCache; - private readonly IWellService wellService; - private static Dictionary? firstOperationsCache = null; - - public const int idOperationTypePlan = 0; - public const int idOperationTypeFact = 1; - - public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService) - { - this.db = db; - this.memoryCache = memoryCache; - this.wellService = wellService; - } - - public IDictionary GetSectionTypes() - => memoryCache - .GetOrCreateBasic(db) - .ToDictionary(s => s.Id, s => s.Caption); - - public IEnumerable GetCategories() - { - var allCategories = memoryCache - .GetOrCreateBasic(db); - - var parentIds = allCategories - .Select(o => o.IdParent) - .Distinct(); - - var operationCategories = allCategories - .Where(o => !parentIds.Contains(o.Id)) - .OrderBy(o => o.IdParent) - .ThenBy(o => o.Name); - - var result = operationCategories.Adapt>(); - return result; - } - - public DateTimeOffset? FirstOperationDate(int idWell) - { - if (firstOperationsCache is null) - { - var query = db.WellOperations - .GroupBy(o => o.IdWell) - .Select(g => new Tuple - ( - g.Key, - g.Where(o => o.IdType == idOperationTypePlan).Min(o => o.DateStart), - g.Where(o => o.IdType == idOperationTypeFact).Min(o => o.DateStart) - )); - - firstOperationsCache = query - .ToDictionary(f => f.Item1, f => f.Item3 ?? f.Item2); - } - - return firstOperationsCache?.GetValueOrDefault(idWell); - } - - public async Task GetOrDefaultAsync(int id, - CancellationToken token) - { - var entity = await db.WellOperations - .Include(s => s.WellSectionType) - .Include(s => s.OperationCategory) - .FirstOrDefaultAsync(e => e.Id == id, token) - .ConfigureAwait(false); - - if (entity is null) - return null; - - var timezone = wellService.GetTimezone(entity.IdWell); - - var dto = entity.Adapt(); - dto.WellSectionTypeName = entity.WellSectionType.Caption; - dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours); - dto.CategoryName = entity.OperationCategory.Name; - return dto; - } - - public Task> GetAsync(WellOperationRequest request, - CancellationToken token) - { - return Task.FromResult(Enumerable.Empty()); - } - - public async Task InsertRangeAsync( - IEnumerable wellOperationDtos, - CancellationToken token) - { - var firstOperation = wellOperationDtos - .FirstOrDefault(); - if (firstOperation is null) - return 0; - - var idWell = firstOperation.IdWell; - - var timezone = wellService.GetTimezone(idWell); - foreach (var dto in wellOperationDtos) - { - var entity = dto.Adapt(); - entity.Id = default; - entity.DateStart = dto.DateStart.ToUtcDateTimeOffset(timezone.Hours); - entity.IdWell = idWell; - db.WellOperations.Add(entity); - } - - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } - - public async Task UpdateAsync( - WellOperationDto dto, CancellationToken token) - { - var timezone = wellService.GetTimezone(dto.IdWell); - var entity = dto.Adapt(); - entity.DateStart = dto.DateStart.ToUtcDateTimeOffset(timezone.Hours); - db.WellOperations.Update(entity); - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } - - public async Task DeleteAsync(IEnumerable ids, - CancellationToken token) - { - var query = db.WellOperations.Where(e => ids.Contains(e.Id)); - db.WellOperations.RemoveRange(query); - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } - - private IQueryable BuildQuery(WellOperationRequest request) - { - var timezone = wellService.GetTimezone(request.IdWell); - - var query = db.WellOperations - .Include(s => s.WellSectionType) - .Include(s => s.OperationCategory) - .Where(s => s.IdWell == request.IdWell); - - if (request.OperationType.HasValue) - query = query.Where(e => e.IdType == request.OperationType.Value); - - if (request.SectionTypeIds?.Any() == true) - query = query.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType)); - - if (request.OperationCategoryIds?.Any() == true) - query = query.Where(e => request.OperationCategoryIds.Contains(e.IdCategory)); - - if (request.GeDepth.HasValue) - query = query.Where(e => e.DepthEnd >= request.GeDepth.Value); - - if (request.LeDepth.HasValue) - query = query.Where(e => e.DepthEnd <= request.LeDepth.Value); - - if (request.GeDate.HasValue) - { - var geDateOffset = request.GeDate.Value.ToUtcDateTimeOffset(timezone.Hours); - query = query.Where(e => e.DateStart >= geDateOffset); - } - - if (request.LeDate.HasValue) - { - var leDateOffset = request.LeDate.Value.ToUtcDateTimeOffset(timezone.Hours); - query = query.Where(e => e.DateStart <= leDateOffset); - } - - if (request.SortFields?.Any() == true) - { - query = query.SortBy(request.SortFields); - } - else - { - query = query - .OrderBy(e => e.DateStart) - .ThenBy(e => e.DepthEnd) - .ThenBy(e => e.Id); - } - - return query; - } - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs index 3d73dbe4..967c44ca 100644 --- a/AsbCloudInfrastructure/Services/WellService.cs +++ b/AsbCloudInfrastructure/Services/WellService.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Exceptions; +using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.EfCache; @@ -23,7 +24,7 @@ namespace AsbCloudInfrastructure.Services private readonly ITelemetryService telemetryService; private readonly ICrudRepository companyTypesService; private readonly ITimezoneService timezoneService; - private readonly IWellOperationService wellOperationService; + private readonly IWellOperationRepository wellOperationRepository; public ITelemetryService TelemetryService => telemetryService; @@ -42,7 +43,7 @@ namespace AsbCloudInfrastructure.Services this.telemetryService = telemetryService; this.timezoneService = timezoneService; - this.wellOperationService = new WellOperationService.WellOperationService(db, memoryCache, this); + this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this); companyTypesService = new CrudCacheRepositoryBase(dbContext, memoryCache); } @@ -216,7 +217,7 @@ namespace AsbCloudInfrastructure.Services if (entity.Timezone is null) dto.Timezone = GetTimezone(entity.Id); - dto.StartDate = wellOperationService.FirstOperationDate(entity.Id)?.ToRemoteDateTime(dto.Timezone.Hours); + dto.StartDate = wellOperationRepository.FirstOperationDate(entity.Id)?.ToRemoteDateTime(dto.Timezone.Hours); dto.WellType = entity.WellType?.Caption; dto.Cluster = entity.Cluster?.Caption; dto.Deposit = entity.Cluster?.Deposit?.Caption; diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs index 2fc8a757..46ce1683 100644 --- a/AsbCloudWebApi/Controllers/WellOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellOperationController.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data; +using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; @@ -20,13 +21,13 @@ namespace AsbCloudWebApi.Controllers [Authorize] public class WellOperationController : ControllerBase { - private readonly IWellOperationService operationService; + private readonly IWellOperationRepository operationRepository; private readonly IWellService wellService; private readonly IWellOperationImportService wellOperationImportService; - public WellOperationController(IWellOperationService operationService, IWellService wellService, IWellOperationImportService wellOperationImportService) + public WellOperationController(IWellOperationRepository operationService, IWellService wellService, IWellOperationImportService wellOperationImportService) { - this.operationService = operationService; + this.operationRepository = operationService; this.wellService = wellService; this.wellOperationImportService = wellOperationImportService; } @@ -41,7 +42,7 @@ namespace AsbCloudWebApi.Controllers [ProducesResponseType(typeof(IDictionary), (int)System.Net.HttpStatusCode.OK)] public IActionResult GetSectionTypes() { - var result = operationService.GetSectionTypes(); + var result = operationRepository.GetSectionTypes(); return Ok(result); } @@ -55,7 +56,7 @@ namespace AsbCloudWebApi.Controllers [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public IActionResult GetCategories() { - var result = operationService.GetCategories(); + var result = operationRepository.GetCategories(); return Ok(result); } @@ -78,7 +79,7 @@ namespace AsbCloudWebApi.Controllers return Forbid(); var requestToService = new WellOperationRequest(request, idWell); - var result = await operationService.GetOperationsAsync( + var result = await operationRepository.GetPageAsync( requestToService, token) .ConfigureAwait(false); @@ -105,7 +106,7 @@ namespace AsbCloudWebApi.Controllers return Forbid(); var requestToService = new WellOperationRequest(request, idWell); - var result = await operationService.GetGroupOperationsStatAsync( + var result = await operationRepository.GetGroupOperationsStatAsync( requestToService, token) .ConfigureAwait(false); @@ -129,7 +130,7 @@ namespace AsbCloudWebApi.Controllers if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); - var result = await operationService.GetOrDefaultAsync(idOperation, token).ConfigureAwait(false); + var result = await operationRepository.GetOrDefaultAsync(idOperation, token).ConfigureAwait(false); return Ok(result); } @@ -152,7 +153,7 @@ namespace AsbCloudWebApi.Controllers foreach(var value in values) value.IdWell= idWell; - var result = await operationService.InsertRangeAsync(values, token) + var result = await operationRepository.InsertRangeAsync(values, token) .ConfigureAwait(false); return Ok(result); @@ -178,7 +179,7 @@ namespace AsbCloudWebApi.Controllers value.IdWell= idWell; value.Id = idOperation; - var result = await operationService.UpdateAsync(value, token) + var result = await operationRepository.UpdateAsync(value, token) .ConfigureAwait(false); return Ok(result); } @@ -199,7 +200,7 @@ namespace AsbCloudWebApi.Controllers token).ConfigureAwait(false)) return Forbid(); - var result = await operationService.DeleteAsync(new int[] { idOperation }, token) + var result = await operationRepository.DeleteAsync(new int[] { idOperation }, token) .ConfigureAwait(false); return Ok(result); diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 754e0194..19720e16 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -1,21 +1,10 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Data.DailyReport; -using AsbCloudDb; +using AsbCloudApp.Requests; using AsbCloudDb.Model; using AsbCloudInfrastructure; -using AsbCloudInfrastructure.Services.DailyReport; -using AsbCloudInfrastructure.Services.SAUB; -using ClosedXML.Excel; -using DocumentFormat.OpenXml.Wordprocessing; -using Microsoft.EntityFrameworkCore; -using Org.BouncyCastle.Utilities.Collections; +using AsbCloudInfrastructure.Repository; +using Microsoft.Extensions.Caching.Memory; using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Threading; -using System.Threading.Tasks; namespace ConsoleApp1 { @@ -29,7 +18,9 @@ namespace ConsoleApp1 DependencyInjection.MapsterSetup(); var sw = System.Diagnostics.Stopwatch.StartNew(); - + var repo = new WellOperationRepository(db, new MemoryCache(new MemoryCacheOptions()), ServiceFactory.MakeWellService()); + var req = new WellOperationRequest { IdWell = 88, OperationType = 1, Skip = 70}; + var res = repo.GetPageAsync(req, CancellationToken.None).Result; sw.Stop(); Console.WriteLine($"total time: {sw.ElapsedMilliseconds} ms"); diff --git a/ConsoleApp1/ServiceFactory.cs b/ConsoleApp1/ServiceFactory.cs index bf7c9a42..eceb5f9b 100644 --- a/ConsoleApp1/ServiceFactory.cs +++ b/ConsoleApp1/ServiceFactory.cs @@ -1,4 +1,5 @@ using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using AsbCloudInfrastructure.Services; using AsbCloudInfrastructure.Services.SAUB; using AsbCloudInfrastructure.Services.WellOperationService; @@ -71,7 +72,7 @@ namespace ConsoleApp1 public static WellService MakeWellService() => new (Context, memoryCache, MakeTelemetryService(), TimezoneService); - public static WellOperationService MakeWellOperationsService() + public static WellOperationRepository MakeWellOperationRepository() => new (Context, memoryCache, MakeWellService()); public static OperationsStatService MakeOperationsStatService() From f5becebbeb91f23dd4893c32f3f14a7e2cf8393e Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Fri, 30 Dec 2022 15:24:48 +0500 Subject: [PATCH 04/13] #7987467 Add telemetry statistic calc (not completed) --- .../Data/ProcessMap/ProcessMapReportDto.cs | 28 +- .../Data/ProcessMap/ProcessMapReportRowDto.cs | 18 +- .../Services/ProcessMap/ProcessMapService.cs | 307 +++++++++++------- .../ProcessMap/ProcessTelemetrySaubStat.cs | 35 ++ .../WellOperationImportService.cs | 1 + ConsoleApp1/Program.cs | 46 ++- 6 files changed, 297 insertions(+), 138 deletions(-) create mode 100644 AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs index 51e77911..6bc8ace1 100644 --- a/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs @@ -15,18 +15,24 @@ namespace AsbCloudApp.Data.ProcessMap /// /// Глубина по стволу, м + /// + /// на начало интервала + /// /// - public double Depth { get; set; } + public double DepthStart { get; set; } /// /// Дата/ время + /// + /// на начало интервала + /// /// - public DateTimeOffset Date { get; set; } + public DateTimeOffset DateStart { get; set; } /// - /// Т мех бурения, ч + /// Время мех бурения, ч /// - public double MechDrillingTime { get; set; } + public double MechDrillingHours { get; set; } /// /// Слайд @@ -41,22 +47,12 @@ namespace AsbCloudApp.Data.ProcessMap /// /// название секции скважины /// - public string? WellSectionTypeName { get; set; } + public int IdWellSectionType { get; set; } /// /// название секции скважины /// - public int? IdWellSectionType { get; set; } - - /// - /// Категория - /// - public string? Category { get; set; } - - /// - /// Идентификатор категории - /// - public int? IdCategory { get; set; } + public string WellSectionTypeName { get; set; } = null!; } #nullable disable } diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs index 6b4e942d..0c1ae626 100644 --- a/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs @@ -12,15 +12,20 @@ namespace AsbCloudApp.Data.ProcessMap /// public class ProcessMapReportRowDto { + /// + /// Проходка, м + /// + public double? DeltaDepth { get; set; } + /// /// Перепад давления, атм /// - public ProcessMapReportParamsDto PressureDrop { get; set; } = null!; + public ProcessMapReportParamsDto PressureDiff { get; set; } = null!; /// /// Нагрузка, т /// - public ProcessMapReportParamsDto Load { get; set; } = null!; + public ProcessMapReportParamsDto AxialLoad { get; set; } = null!; /// /// Момент на ВСП, кНхМ @@ -35,17 +40,12 @@ namespace AsbCloudApp.Data.ProcessMap /// /// Процент использования системы АПД, % /// - public double PercentageADFSystemUsage { get; set; } + public double Usage { get; set; } /// /// Фактическая механическая скорость, м/ч /// - public double ActualMechanicalSpeed { get; set; } - - /// - /// Проходка, м - /// - public double? SectionPenetration { get; set; } + public double Rop { get; set; } } #nullable disable } diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs index 0dfab7df..8f81b317 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs @@ -1,9 +1,11 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMap; +using AsbCloudApp.Data.SAUB; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; +using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; @@ -13,151 +15,236 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.ProcessMap { #nullable enable - public class ProcessMapService : IProcessMapService + public partial class ProcessMapService : IProcessMapService { + private readonly IAsbCloudDbContext db; private readonly IWellOperationRepository wellOperationRepository; private readonly IProcessMapRepository processMapRepository; + private readonly ITelemetryService telemetryService; - public ProcessMapService(IWellOperationRepository wellOperationService, - IProcessMapRepository processMapRepository) - { + public ProcessMapService( + IAsbCloudDbContext db, + IWellOperationRepository wellOperationService, + IProcessMapRepository processMapRepository, + ITelemetryService telemetryService) + { + this.db = db; this.wellOperationRepository = wellOperationService; this.processMapRepository = processMapRepository; + this.telemetryService = telemetryService; } public async Task> GetProcessMapAsync(int idWell, CancellationToken token) { - var categoryIds = new int[] { WellOperationCategory.IdSlide, WellOperationCategory.IdRotor }; - var operationsRequest = new WellOperationRequest { IdWell = idWell, - OperationCategoryIds = categoryIds, - OperationType = 1, + OperationCategoryIds = WellOperationCategory.MechanicalDrillingSubIds, + OperationType = WellOperation.IdOperationTypeFact, SortFields = new[]{ nameof(WellOperation.DateStart) } }; - var allOperations = await wellOperationRepository.GetPageAsync(operationsRequest, token); - throw new NotImplementedException(); - //var processMapDtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false); + var allFactDrillingOperations = (await wellOperationRepository.GetAsync(operationsRequest, token)) + .Where(o => o.DepthEnd > o.DepthStart); + + var processMapDtos = (await processMapRepository.GetByIdWellAsync(idWell, token))!; - //var result = allOperations - // .GroupBy(x => x.IdWellSectionType) - // .SelectMany(x => handleSections(allOperations, processMapDtos!, x)) - // .ToList(); - - //return result; - } - - private static List handleSections(IEnumerable allWellOperation, IEnumerable processMap, IEnumerable wellOperation) - { - var result = new List(); - var minDepth = wellOperation.Min(o => o.DepthStart); - var maxDepth = wellOperation.Max(o => o.DepthEnd); - - for (var depth = minDepth; depth <= maxDepth; depth += 100) - { - var currentDepth = result.Count() > 0 ? depth + (100 - depth % 100) : depth; - var operation = allWellOperation.First(x => x.DepthEnd >= currentDepth); - var minDate = operation.DateStart; - var maxDate = operation.DateStart.AddHours(operation.DurationHours); - var currentDate = GetDate(currentDepth, minDepth, maxDepth, minDate, maxDate); - var currentHours = GetHourse(currentDepth, minDepth, maxDepth, operation.DurationHours); - var processMapData = processMap.FirstOrDefault(x => x.IdWellSectionType == operation.IdWellSectionType); - - var dto = GetRecord(currentDepth, currentDate, currentHours, operation, processMap); - - if (operation.DepthStart < currentDepth) + var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell)!.Value; + IEnumerable telemetryStat = await GetTelemetryDataAsync(idTelemetry, token); + + var result = allFactDrillingOperations + .GroupBy(o => o.IdWellSectionType) + .SelectMany(sectionOperations => { - var prevOperation = allWellOperation.FirstOrDefault(x => x.DepthEnd == operation.DepthStart); - if (prevOperation is not null) - { - var prevDepth = currentDepth - prevOperation.DepthEnd; - var prevMinDate = prevOperation.DateStart; - var prevMaxDate = operation.DateStart.AddHours(operation.DurationHours); - var prevDate = GetDate(prevDepth, prevOperation.DepthStart, prevOperation.DepthEnd, minDate, maxDate); - var prevHours = GetHourse(currentDepth, prevOperation.DepthStart, prevOperation.DepthEnd, prevOperation.DurationHours); - - if (dto.IdCategory != prevOperation.IdCategory) - FillRecordRow(prevDepth, prevHours, dto, prevOperation.IdCategory, processMap); - - dto.MechDrillingTime = currentHours + prevHours; - } - } - - result.Add(dto); - } + var sectionProcessMap = processMapDtos.Where(p => p.IdWellSectionType == sectionOperations.Key); + return HandleSections(sectionOperations, sectionProcessMap); + }) + .ToList(); return result; } - private static ProcessMapReportDto GetRecord(double depth, DateTimeOffset sate, double hours, WellOperationDto operation, IEnumerable processMap) - { - var dto = new ProcessMapReportDto - { - IdWell = operation.IdWell, - Depth = depth, - Date = sate, - MechDrillingTime = hours, - Category = operation.IdCategory == WellOperationCategory.IdSlide ? "Слайд" : "Ротор", - IdCategory = operation.IdCategory, - IdWellSectionType = operation.IdWellSectionType, - WellSectionTypeName = operation.WellSectionTypeName + private async Task> GetTelemetryDataAsync(int idTelemetry, CancellationToken token) + { + var timezone = telemetryService.GetTimezone(idTelemetry); + var timezoneOffset = TimeSpan.FromHours(timezone.Hours); + + var query = db.Set() + .Where(t => t.IdTelemetry == idTelemetry) + .Where(t => t.BlockPosition > 0.0001) + .Where(t => t.WellDepth > 0.0001) + .Where(t => t.WellDepth - t.BitDepth < 0.01) + .GroupBy(t => new { H = t.DateTime.Hour, W = Math.Truncate(t.WellDepth!.Value) }) + .Select(g => new ProcessTelemetrySaubStat + { + Count = g.Count(), + + DateMin = g.Min(t => t.DateTime.UtcDateTime), + DateMax = g.Max(t => t.DateTime.UtcDateTime), + + WellDepthMin = g.Min(t => t.WellDepth!.Value), + WellDepthMax = g.Max(t => t.WellDepth!.Value), + + Pressure = g.Average(t => t.Pressure!.Value), + PressureSp = g.Average(t => t.PressureSp!.Value), + PressureSpRotor = g.Average(t => t.PressureSpRotor!.Value), + PressureSpSlide = g.Average(t => t.PressureSpSlide!.Value), + PressureIdle = g.Average(t => t.PressureIdle!.Value), + PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax!.Value), + + AxialLoad = g.Average(t => t.AxialLoad!.Value), + AxialLoadSp = g.Average(t => t.AxialLoadSp!.Value), + AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax!.Value), + + RotorTorque = g.Average(t => t.RotorTorque!.Value), + RotorTorqueSp = g.Average(t => t.RotorTorqueSp!.Value), + RotorTorqueLimitMax = g.Average(t => t.RotorTorqueLimitMax!.Value), + + BlockSpeed = g.Average(t => t.BlockSpeed!.Value), + BlockSpeedSp = g.Average(t => t.BlockSpeedSp!.Value), + BlockSpeedSpRotor = g.Average(t => t.BlockSpeedSpRotor!.Value), + BlockSpeedSpSlide = g.Average(t => t.BlockSpeedSpSlide!.Value), + }) + .Where(s => s.WellDepthMin != s.WellDepthMax) + .Where(s => s.Count > 3) + .OrderBy(t => t.DateMin); + + var data = await query.ToArrayAsync(token); + return data; + } + + private static IEnumerable HandleSections( + IEnumerable sectionOperations, + IEnumerable sectionProcessMap ) + { + var minDepth = sectionOperations.Min(o => o.DepthStart); + var maxDepth = sectionOperations.Max(o => o.DepthEnd); + + var depthIntervals = SplitByIntervals(minDepth, maxDepth).ToArray(); + var result = new ProcessMapReportDto[depthIntervals.Length]; + + for (var i = 0; i < depthIntervals.Length; i++ ) + result[i] = MakeProcessMapReportDto(depthIntervals[i], sectionOperations, sectionProcessMap); + + return result; + } + + private static ProcessMapReportDto MakeProcessMapReportDto( + (double min, double max) depthInterval, + IEnumerable sectionOperations, + IEnumerable sectionProcessMap) + { + var dto = new ProcessMapReportDto{ + DepthStart = depthInterval.min + }; + + var intervalOperations = sectionOperations.Where(o => o.DepthEnd >= depthInterval.min && o.DepthStart <= depthInterval.max); + var intervalProcessMap = sectionProcessMap.Where(map => map.DepthEnd >= depthInterval.min && map.DepthStart <= depthInterval.max); + if (intervalOperations.Any()) + { + var firstIntervalOperation = intervalOperations.First(); + var slideOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdSlide); + var rotorOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdRotor); + + dto.DepthStart = depthInterval.min; + dto.DateStart = GetInterpolatedDate(firstIntervalOperation, depthInterval.min); + dto.IdWell = firstIntervalOperation.IdWell; + dto.IdWellSectionType = firstIntervalOperation.IdWellSectionType; + dto.WellSectionTypeName = firstIntervalOperation.WellSectionTypeName; + dto.MechDrillingHours = CalcHours(depthInterval, sectionOperations); + dto.Slide = CalcDrillStat(depthInterval, slideOperations, intervalProcessMap); + dto.Rotor = CalcDrillStat(depthInterval, rotorOperations, intervalProcessMap); + } + return dto; + } + + private static ProcessMapReportRowDto CalcDrillStat( + (double min, double max) depthInterval, + IEnumerable intervalModeOperations, + IEnumerable intervalProcessMap) + { + var dto = new ProcessMapReportRowDto(); + if(intervalModeOperations.Any()) + { + var deltaDepth = CalcDeltaDepth(depthInterval, intervalModeOperations); + dto.DeltaDepth = deltaDepth; + dto.Rop = deltaDepth / CalcHours(depthInterval, intervalModeOperations); + + dto.PressureDiff = CalcPressureDiff(depthInterval, intervalProcessMap); }; - FillRecordRow(depth, hours, dto, operation.IdCategory, processMap); return dto; } - private static void FillRecordRow(double depth, double hours, ProcessMapReportDto dto, int idCategory, IEnumerable processMap) + private static ProcessMapReportParamsDto CalcPressureDiff( + (double min, double max) depthInterval, + IEnumerable intervalProcessMap) { - var row = new ProcessMapReportRowDto { - SectionPenetration = depth, - ActualMechanicalSpeed = depth / hours, - PercentageADFSystemUsage = dto.Depth / depth * 100 - }; - - var processMapData = processMap.FirstOrDefault(x => x.IdWell == dto.IdWell && x.IdWellSectionType == dto.IdWellSectionType); - if (processMapData is not null) + var dto = new ProcessMapReportParamsDto(); + if (intervalProcessMap.Any()) { - row.PressureDrop = new ProcessMapReportParamsDto - { - SetPointPlan = processMapData.Pressure.Plan - }; - row.Load = new ProcessMapReportParamsDto - { - SetPointPlan = processMapData.AxialLoad.Plan - }; - row.TopDriveTorque = new ProcessMapReportParamsDto - { - SetPointPlan = processMapData.TopDriveTorque.Plan - }; - row.SpeedL​imit = new ProcessMapReportParamsDto - { - - }; + dto.SetPointPlan = intervalProcessMap.First().Pressure.Plan; } - - if (idCategory == WellOperationCategory.IdSlide) - dto.Slide = row; - else - dto.Rotor = row; + throw new NotImplementedException(); } - private static DateTimeOffset GetDate(double depth, double deptStart, double deptEnd, DateTimeOffset dateStart, DateTimeOffset dateEnd) + private static double CalcDeltaDepth((double min, double max) depthInterval, IEnumerable intervalOperations) { - var a = depth - deptStart; - var b = deptEnd - deptStart; - var c = dateEnd - dateStart; - var result = dateStart + (a / b) * c; - return result; + var ddepth = 0d; + foreach (var operation in intervalOperations) + { + var depthStart = operation.DepthStart > depthInterval.min + ? operation.DepthStart + : depthInterval.min; + + var depthEnd = operation.DepthEnd < depthInterval.max + ? operation.DepthEnd + : depthInterval.max; + + ddepth += (depthEnd - depthEnd); + } + return ddepth; } - private static double GetHourse(double depth, double deptStart, double deptEnd, double hourse) + private static double CalcHours((double min, double max) depthInterval, IEnumerable intervalOperations) { - var a = depth - deptStart; - var b = deptEnd - deptStart; - var result = 0 + (a / b) * hourse; - return result; + var hours = 0d; + foreach (var operation in intervalOperations) + { + var dateStart = operation.DepthStart > depthInterval.min + ? operation.DateStart + : GetInterpolatedDate(operation, depthInterval.min); + + var dateEnd = operation.DepthEnd < depthInterval.max + ? operation.DateStart + TimeSpan.FromHours(operation.DurationHours) + : GetInterpolatedDate(operation, depthInterval.max); + + hours += (dateEnd - dateStart).TotalHours; + } + return hours; + } + + private static DateTime GetInterpolatedDate(WellOperationDto operation, double depth) + { + if (operation.DepthStart > depth) + throw new ArgumentOutOfRangeException(nameof(depth)); + + var ratio = (depth - operation.DepthStart) / (operation.DepthEnd - operation.DepthStart); + var deltaHours = operation.DurationHours * ratio; + var interpolatedDate = operation.DateStart + TimeSpan.FromHours(deltaHours); + return interpolatedDate; + } + + private static IEnumerable<(double min, double max)> SplitByIntervals(double min, double max) + { + const double step = 100; + var iMin = min; + var iMax = (1 + (int)(min / step)) * step; + for (; iMax < max; iMax += step) + { + yield return (iMin, iMax); + iMin = iMax; + } + yield return (iMin, max); } } #nullable disable diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs new file mode 100644 index 00000000..9c09d2ea --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs @@ -0,0 +1,35 @@ +using System; + +namespace AsbCloudInfrastructure.Services.ProcessMap +{ +#nullable enable + class ProcessTelemetrySaubStat { + public int Count { get; set; } + public DateTime DateMin { get; set; } + public DateTime DateMax { get; set; } + + public float WellDepthMin { get; set; } + public float WellDepthMax { get; set; } + + public float Pressure { get; set; } + public float PressureSp { get; set; } + public float PressureIdle { get; set; } + public float PressureSpRotor { get; set; } + public float PressureSpSlide { get; set; } + public float PressureDeltaLimitMax { get; set; } + + public float AxialLoad { get; set; } + public float AxialLoadSp { get; set; } + public float AxialLoadLimitMax { get; set; } + + public float RotorTorque { get; set; } + public float RotorTorqueSp { get; set; } + public float RotorTorqueLimitMax { get; set; } + + public float BlockSpeed { get; set; } + public float BlockSpeedSp { get; set; } + public float BlockSpeedSpRotor { get; set; } + public float BlockSpeedSpSlide { get; set; } + } +#nullable disable +} diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationImportService.cs index 81771165..e9ed3d11 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationImportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationImportService.cs @@ -65,6 +65,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService } } + // TODO: use WellOperationRepository instead of DB public WellOperationImportService(IAsbCloudDbContext db, IWellService wellService) { this.db = db; diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 19720e16..af1ac385 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -4,6 +4,7 @@ using AsbCloudInfrastructure; using AsbCloudInfrastructure.Repository; using Microsoft.Extensions.Caching.Memory; using System; +using System.Linq; using System.Threading; namespace ConsoleApp1 @@ -18,12 +19,51 @@ namespace ConsoleApp1 DependencyInjection.MapsterSetup(); var sw = System.Diagnostics.Stopwatch.StartNew(); - var repo = new WellOperationRepository(db, new MemoryCache(new MemoryCacheOptions()), ServiceFactory.MakeWellService()); - var req = new WellOperationRequest { IdWell = 88, OperationType = 1, Skip = 70}; - var res = repo.GetPageAsync(req, CancellationToken.None).Result; + var idTelemetry = 5; + var query = db.Set() + .Where(t => t.IdTelemetry == idTelemetry) + .Where(t => t.BlockPosition > 0.0001) + .Where(t => t.WellDepth > 0.0001) + .Where(t => t.WellDepth - t.BitDepth < 0.01) + .GroupBy(t => new { H = t.DateTime.Hour, W = Math.Truncate(t.WellDepth!.Value) }) + .Select(g => new + { + Count = g.Count(), + + DateMin = g.Min(t => t.DateTime), + DateMax = g.Max(t => t.DateTime), + + WellDepthMin = g.Min(t => t.WellDepth), + WellDepthMax = g.Max(t => t.WellDepth), + + Pressure = g.Average(t => t.Pressure), + PressureSp = g.Average(t => t.PressureSp), + PressureSpRotor = g.Average(t => t.PressureSpRotor), + PressureSpSlide = g.Average(t => t.PressureSpSlide), + PressureIdle = g.Average(t => t.PressureIdle), + PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax), + + AxialLoad = g.Average(t => t.AxialLoad), + AxialLoadSp = g.Average(t => t.AxialLoadSp), + AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax), + + RotorTorque = g.Average(t => t.RotorTorque), + RotorTorqueSp = g.Average(t => t.RotorTorqueSp), + RotorTorqueIdle = g.Average(t => t.RotorTorqueIdle), + + BlockSpeed = g.Average(t => t.BlockSpeed), + BlockSpeedSp = g.Average(t => t.BlockSpeedSp), + BlockSpeedSpRotor = g.Average(t => t.BlockSpeedSpRotor), + BlockSpeedSpSlide = g.Average(t => t.BlockSpeedSpSlide), + }) + .Where(s => s.WellDepthMin != s.WellDepthMax) + .Where(s => s.Count > 3) + .OrderBy(t => t.DateMin); + var data = query.ToArray(); sw.Stop(); Console.WriteLine($"total time: {sw.ElapsedMilliseconds} ms"); + var count = data.Length; Console.ReadLine(); } } From ac1c9aedb2e82fd901a8c68797887745df2c0e9e Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 10 Jan 2023 12:31:01 +0500 Subject: [PATCH 05/13] ProcessMapService calculations draft --- .../ProcessMap/ProcessMapReportParamsDto.cs | 6 +- .../Data/ProcessMap/ProcessMapReportRowDto.cs | 16 +-- .../Services/ProcessMap/ProcessMapService.cs | 106 ++++++++++++++---- 3 files changed, 92 insertions(+), 36 deletions(-) diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs index 6136d144..cf180f07 100644 --- a/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs @@ -15,12 +15,12 @@ namespace AsbCloudApp.Data.ProcessMap /// /// Уставка план /// - public double SetPointPlan { get; set; } + public double? SetpointPlan { get; set; } /// /// Уставка факт /// - public double? SetPointFact { get; set; } + public double? SetpointFact { get; set; } /// /// Факт @@ -35,7 +35,7 @@ namespace AsbCloudApp.Data.ProcessMap /// /// Процент бурения по уставке ,% /// - public double? PercDrillingSetPoint { get; set; } + public double? PercDrillingSetpoint { get; set; } } #nullable disable } diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs index 0c1ae626..737f73ea 100644 --- a/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AsbCloudApp.Data.ProcessMap +namespace AsbCloudApp.Data.ProcessMap { #nullable enable /// @@ -20,22 +14,22 @@ namespace AsbCloudApp.Data.ProcessMap /// /// Перепад давления, атм /// - public ProcessMapReportParamsDto PressureDiff { get; set; } = null!; + public ProcessMapReportParamsDto PressureDiff { get; set; } = new(); /// /// Нагрузка, т /// - public ProcessMapReportParamsDto AxialLoad { get; set; } = null!; + public ProcessMapReportParamsDto AxialLoad { get; set; } = new(); /// /// Момент на ВСП, кНхМ /// - public ProcessMapReportParamsDto TopDriveTorque { get; set; } = null!; + public ProcessMapReportParamsDto TopDriveTorque { get; set; } = new(); /// /// Ограничение скорости, м/ч /// - public ProcessMapReportParamsDto SpeedL​imit { get; set; } = null!; + public ProcessMapReportParamsDto SpeedL​imit { get; set; } = new(); /// /// Процент использования системы АПД, % diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs index 8f81b317..13c0db9f 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs @@ -49,14 +49,14 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var processMapDtos = (await processMapRepository.GetByIdWellAsync(idWell, token))!; var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell)!.Value; - IEnumerable telemetryStat = await GetTelemetryDataAsync(idTelemetry, token); + IEnumerable telemetryDataStat = await GetTelemetryDataAsync(idTelemetry, token); var result = allFactDrillingOperations .GroupBy(o => o.IdWellSectionType) .SelectMany(sectionOperations => { var sectionProcessMap = processMapDtos.Where(p => p.IdWellSectionType == sectionOperations.Key); - return HandleSections(sectionOperations, sectionProcessMap); + return HandleSections(sectionOperations, sectionProcessMap, telemetryDataStat); }) .ToList(); @@ -114,7 +114,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMap private static IEnumerable HandleSections( IEnumerable sectionOperations, - IEnumerable sectionProcessMap ) + IEnumerable sectionProcessMap, + IEnumerable telemetryDataStat) { var minDepth = sectionOperations.Min(o => o.DepthStart); var maxDepth = sectionOperations.Max(o => o.DepthEnd); @@ -123,7 +124,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var result = new ProcessMapReportDto[depthIntervals.Length]; for (var i = 0; i < depthIntervals.Length; i++ ) - result[i] = MakeProcessMapReportDto(depthIntervals[i], sectionOperations, sectionProcessMap); + result[i] = MakeProcessMapReportDto(depthIntervals[i], sectionOperations, sectionProcessMap, telemetryDataStat); return result; } @@ -131,7 +132,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMap private static ProcessMapReportDto MakeProcessMapReportDto( (double min, double max) depthInterval, IEnumerable sectionOperations, - IEnumerable sectionProcessMap) + IEnumerable sectionProcessMap, + IEnumerable telemetryDataStat) { var dto = new ProcessMapReportDto{ DepthStart = depthInterval.min @@ -139,6 +141,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var intervalOperations = sectionOperations.Where(o => o.DepthEnd >= depthInterval.min && o.DepthStart <= depthInterval.max); var intervalProcessMap = sectionProcessMap.Where(map => map.DepthEnd >= depthInterval.min && map.DepthStart <= depthInterval.max); + var intervalTelemetryDataStat = CalcIntervalTelemetryDataStat(depthInterval, telemetryDataStat); + if (intervalOperations.Any()) { var firstIntervalOperation = intervalOperations.First(); @@ -151,40 +155,98 @@ namespace AsbCloudInfrastructure.Services.ProcessMap dto.IdWellSectionType = firstIntervalOperation.IdWellSectionType; dto.WellSectionTypeName = firstIntervalOperation.WellSectionTypeName; dto.MechDrillingHours = CalcHours(depthInterval, sectionOperations); - dto.Slide = CalcDrillStat(depthInterval, slideOperations, intervalProcessMap); - dto.Rotor = CalcDrillStat(depthInterval, rotorOperations, intervalProcessMap); + dto.Slide = CalcDrillModeStat(depthInterval, slideOperations, intervalProcessMap, intervalTelemetryDataStat); + dto.Rotor = CalcDrillModeStat(depthInterval, rotorOperations, intervalProcessMap, intervalTelemetryDataStat); } return dto; } - private static ProcessMapReportRowDto CalcDrillStat( + private static ProcessTelemetrySaubStat? CalcIntervalTelemetryDataStat((double min, double max) depthInterval, IEnumerable telemetryDataStat) + { + ProcessTelemetrySaubStat[] data = telemetryDataStat + .Where(d => d.WellDepthMin <= depthInterval.max && d.WellDepthMax >= depthInterval.min) + .ToArray(); + + if (!data.Any()) + return null; + + if (data.Length == 1) + return data.First(); + + + var result = new ProcessTelemetrySaubStat + { + WellDepthMin = data.Min(d => d.WellDepthMin), + WellDepthMax = data.Max(d => d.WellDepthMax), + DateMin = data.Min(d => d.DateMin), + DateMax = data.Max(d => d.DateMax), + }; + + var intervalDeltaDepth = result.WellDepthMax - result.WellDepthMin; + + foreach (var item in data) + { + var itemWeight = (item.WellDepthMax - item.WellDepthMin) / intervalDeltaDepth; + + result.Pressure += item.Pressure * itemWeight; + result.PressureSp += item.PressureSp * itemWeight; + result.PressureSpRotor += item.PressureSpSlide * itemWeight; + result.PressureIdle += item.PressureIdle * itemWeight; + + result.AxialLoad += item.AxialLoad * itemWeight; + result.AxialLoadSp += item.AxialLoadSp * itemWeight; + result.AxialLoadLimitMax += item.AxialLoadLimitMax * itemWeight; + + result.RotorTorque += item.RotorTorque * itemWeight; + result.RotorTorqueSp += item.RotorTorqueSp * itemWeight; + result.RotorTorqueLimitMax += item.RotorTorqueLimitMax * itemWeight; + + result.BlockSpeed += item.BlockSpeed * itemWeight; + result.BlockSpeedSp += item.BlockSpeedSp * itemWeight; + result.BlockSpeedSpRotor += item.BlockSpeedSpRotor * itemWeight; + result.BlockSpeedSpSlide += item.BlockSpeedSpSlide * itemWeight; + } + + return result; + } + + private static ProcessMapReportRowDto CalcDrillModeStat( (double min, double max) depthInterval, IEnumerable intervalModeOperations, - IEnumerable intervalProcessMap) + IEnumerable intervalProcessMap, + ProcessTelemetrySaubStat? telemetryDataStat) { var dto = new ProcessMapReportRowDto(); - if(intervalModeOperations.Any()) + if (intervalModeOperations.Any()) { var deltaDepth = CalcDeltaDepth(depthInterval, intervalModeOperations); dto.DeltaDepth = deltaDepth; dto.Rop = deltaDepth / CalcHours(depthInterval, intervalModeOperations); - dto.PressureDiff = CalcPressureDiff(depthInterval, intervalProcessMap); + var processMapFirst = intervalProcessMap.First(); + + dto.PressureDiff.SetpointPlan = processMapFirst.Pressure.Plan; + dto.AxialLoad.SetpointPlan = processMapFirst.AxialLoad.Plan; + dto.TopDriveTorque.SetpointPlan = processMapFirst.TopDriveTorque.Plan; + dto.SpeedLimit.SetpointPlan = double.NaN; }; - return dto; - } - - private static ProcessMapReportParamsDto CalcPressureDiff( - (double min, double max) depthInterval, - IEnumerable intervalProcessMap) - { - var dto = new ProcessMapReportParamsDto(); - if (intervalProcessMap.Any()) + if (telemetryDataStat is not null) { - dto.SetPointPlan = intervalProcessMap.First().Pressure.Plan; + dto.PressureDiff.SetpointFact = telemetryDataStat.PressureSp; + dto.PressureDiff.Fact = telemetryDataStat.Pressure; + dto.PressureDiff.Limit = telemetryDataStat.PressureDeltaLimitMax; + + dto.AxialLoad.SetpointFact = telemetryDataStat.AxialLoadSp; + dto.AxialLoad.Fact = telemetryDataStat.AxialLoad; + dto.AxialLoad.Limit = telemetryDataStat.AxialLoadLimitMax; + + dto.TopDriveTorque.SetpointFact = telemetryDataStat.RotorTorqueSp; + dto.TopDriveTorque.Fact = telemetryDataStat.RotorTorque; + dto.TopDriveTorque.Limit = telemetryDataStat.RotorTorqueLimitMax; } - throw new NotImplementedException(); + + return dto; } private static double CalcDeltaDepth((double min, double max) depthInterval, IEnumerable intervalOperations) From 9f51007622b12c1b6a948deb3c2c24c5b531f3dc Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Fri, 13 Jan 2023 14:34:26 +0500 Subject: [PATCH 06/13] ProcessMapReport. Add GetTelemetryDataStatAsync(..) to TelemetryDataSaubService. --- .../Data/SAUB/TelemetryDataSaubStatDto.cs | 117 ++++++++++++++++++ .../Services/ITelemetryDataSaubService.cs | 26 ++++ AsbCloudApp/Services/ITelemetryDataService.cs | 3 +- AsbCloudInfrastructure/DependencyInjection.cs | 2 +- .../ProcessMap/ProcessMapReportService.cs | 11 +- .../Services/ProcessMap/ProcessMapService.cs | 62 ++-------- .../ProcessMap/ProcessTelemetrySaubStat.cs | 35 ------ .../Services/SAUB/TelemetryDataBaseService.cs | 4 +- .../Services/SAUB/TelemetryDataSaubService.cs | 55 +++++++- 9 files changed, 213 insertions(+), 102 deletions(-) create mode 100644 AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs create mode 100644 AsbCloudApp/Services/ITelemetryDataSaubService.cs delete mode 100644 AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs new file mode 100644 index 00000000..90bbd5f0 --- /dev/null +++ b/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs @@ -0,0 +1,117 @@ +using System; + +namespace AsbCloudApp.Data.SAUB +{ +#nullable enable + /// + /// Статистика телеметрии САУБ (усредненные значения) по интервалам глубины + /// + public class TelemetryDataSaubStatDto + { + /// + /// Кол-во записей в интервале + /// + public int Count { get; set; } + + /// + /// Дата начала интервала + /// + public DateTime DateMin { get; set; } + + /// + /// Дата окончания интервала + /// + public DateTime DateMax { get; set; } + + /// + /// Глубина начала интервала + /// + public float WellDepthMin { get; set; } + + /// + /// Глубина окончания интервала + /// + public float WellDepthMax { get; set; } + + /// + /// Давление + /// + public float Pressure { get; set; } + + /// + /// действующее задание давления + /// + public float PressureSp { get; set; } + + /// + /// Давление при холостом ходе. + /// + public float PressureIdle { get; set; } + + /// + /// задание давления для роторного режима + /// + public float PressureSpRotor { get; set; } + + /// + /// задание давления для режима слайда + /// + public float PressureSpSlide { get; set; } + + /// + /// ограничение макс перепада давления + /// + public float PressureDeltaLimitMax { get; set; } + + /// + /// осевая нагрузка + /// + public float AxialLoad { get; set; } + + /// + /// задание осевой нагрузки + /// + public float AxialLoadSp { get; set; } + + /// + /// ограничение макс. осевой нагрузки + /// + public float AxialLoadLimitMax { get; set; } + + /// + /// момент ротора + /// + public float RotorTorque { get; set; } + + /// + /// задание момента ротора + /// + public float RotorTorqueSp { get; set; } + + /// + /// момент ротора на х.х. + /// + public float RotorTorqueLimitMax { get; set; } + + /// + /// Талевый блок. Скорость + /// + public float BlockSpeed { get; set; } + + /// + /// Талевый блок. Задание скорости + /// + public float BlockSpeedSp { get; set; } + + /// + /// Талевый блок. Задание скорости для роторного бурения + /// + public float BlockSpeedSpRotor { get; set; } + + /// + /// Талевый блок. Задание скорости для режима слайда + /// + public float BlockSpeedSpSlide { get; set; } + } +#nullable disable +} diff --git a/AsbCloudApp/Services/ITelemetryDataSaubService.cs b/AsbCloudApp/Services/ITelemetryDataSaubService.cs new file mode 100644 index 00000000..d6bdcb6f --- /dev/null +++ b/AsbCloudApp/Services/ITelemetryDataSaubService.cs @@ -0,0 +1,26 @@ +using AsbCloudApp.Data.SAUB; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace AsbCloudApp.Services +{ + /// + /// Телеметрия САУБ + /// + public interface ITelemetryDataSaubService : ITelemetryDataService + { + /// + /// усредненная статистика по 1м за весь период + /// + /// МЕДЛЕННЫЙ ЗАПРОС + /// + /// + /// + /// + /// + Task> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token); + } +} +#nullable disable \ No newline at end of file diff --git a/AsbCloudApp/Services/ITelemetryDataService.cs b/AsbCloudApp/Services/ITelemetryDataService.cs index 8efc74ae..585843ff 100644 --- a/AsbCloudApp/Services/ITelemetryDataService.cs +++ b/AsbCloudApp/Services/ITelemetryDataService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; + #nullable enable namespace AsbCloudApp.Services { @@ -33,7 +34,7 @@ namespace AsbCloudApp.Services /// /// /// - Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token = default); + Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token); } } #nullable disable \ No newline at end of file diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 6a2f9fca..1b7b05d1 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -184,7 +184,7 @@ namespace AsbCloudInfrastructure services.AddTransient, CrudCacheRepositoryBase>(); // TelemetryData services - services.AddTransient, TelemetryDataSaubService>(); + services.AddTransient(); services.AddTransient, TelemetryDataSpinService>(); // Wits diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs index fa80efe4..c8357a2a 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs @@ -30,16 +30,9 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var stream = GetExcelTemplateStream(); using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled); - var data = processMapService.GetProcessMapAsync(idWell, token); + var data = await processMapService.GetProcessMapAsync(idWell, token); - //var dtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false); - //if (dtos is not null) - //{ - // var processMapReportDto = await processMapService.GetProcessMapAsync(dtos, token).ConfigureAwait(false); - // FillProcessMapToWorkbook(workbook, processMapReportDto); - //} - - FillProcessMapToWorkbook(workbook, new List()); + FillProcessMapToWorkbook(workbook, data); MemoryStream memoryStream = new MemoryStream(); workbook.SaveAs(memoryStream, new SaveOptions { }); diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs index 13c0db9f..0d6daae0 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs @@ -49,7 +49,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var processMapDtos = (await processMapRepository.GetByIdWellAsync(idWell, token))!; var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell)!.Value; - IEnumerable telemetryDataStat = await GetTelemetryDataAsync(idTelemetry, token); + IEnumerable telemetryDataStat = await GetTelemetryDataAsync(idTelemetry, token); var result = allFactDrillingOperations .GroupBy(o => o.IdWellSectionType) @@ -63,59 +63,15 @@ namespace AsbCloudInfrastructure.Services.ProcessMap return result; } - private async Task> GetTelemetryDataAsync(int idTelemetry, CancellationToken token) + private async Task> GetTelemetryDataAsync(int idTelemetry, CancellationToken token) { - var timezone = telemetryService.GetTimezone(idTelemetry); - var timezoneOffset = TimeSpan.FromHours(timezone.Hours); - - var query = db.Set() - .Where(t => t.IdTelemetry == idTelemetry) - .Where(t => t.BlockPosition > 0.0001) - .Where(t => t.WellDepth > 0.0001) - .Where(t => t.WellDepth - t.BitDepth < 0.01) - .GroupBy(t => new { H = t.DateTime.Hour, W = Math.Truncate(t.WellDepth!.Value) }) - .Select(g => new ProcessTelemetrySaubStat - { - Count = g.Count(), - - DateMin = g.Min(t => t.DateTime.UtcDateTime), - DateMax = g.Max(t => t.DateTime.UtcDateTime), - - WellDepthMin = g.Min(t => t.WellDepth!.Value), - WellDepthMax = g.Max(t => t.WellDepth!.Value), - - Pressure = g.Average(t => t.Pressure!.Value), - PressureSp = g.Average(t => t.PressureSp!.Value), - PressureSpRotor = g.Average(t => t.PressureSpRotor!.Value), - PressureSpSlide = g.Average(t => t.PressureSpSlide!.Value), - PressureIdle = g.Average(t => t.PressureIdle!.Value), - PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax!.Value), - - AxialLoad = g.Average(t => t.AxialLoad!.Value), - AxialLoadSp = g.Average(t => t.AxialLoadSp!.Value), - AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax!.Value), - - RotorTorque = g.Average(t => t.RotorTorque!.Value), - RotorTorqueSp = g.Average(t => t.RotorTorqueSp!.Value), - RotorTorqueLimitMax = g.Average(t => t.RotorTorqueLimitMax!.Value), - - BlockSpeed = g.Average(t => t.BlockSpeed!.Value), - BlockSpeedSp = g.Average(t => t.BlockSpeedSp!.Value), - BlockSpeedSpRotor = g.Average(t => t.BlockSpeedSpRotor!.Value), - BlockSpeedSpSlide = g.Average(t => t.BlockSpeedSpSlide!.Value), - }) - .Where(s => s.WellDepthMin != s.WellDepthMax) - .Where(s => s.Count > 3) - .OrderBy(t => t.DateMin); - - var data = await query.ToArrayAsync(token); - return data; + } private static IEnumerable HandleSections( IEnumerable sectionOperations, IEnumerable sectionProcessMap, - IEnumerable telemetryDataStat) + IEnumerable telemetryDataStat) { var minDepth = sectionOperations.Min(o => o.DepthStart); var maxDepth = sectionOperations.Max(o => o.DepthEnd); @@ -133,7 +89,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap (double min, double max) depthInterval, IEnumerable sectionOperations, IEnumerable sectionProcessMap, - IEnumerable telemetryDataStat) + IEnumerable telemetryDataStat) { var dto = new ProcessMapReportDto{ DepthStart = depthInterval.min @@ -161,9 +117,9 @@ namespace AsbCloudInfrastructure.Services.ProcessMap return dto; } - private static ProcessTelemetrySaubStat? CalcIntervalTelemetryDataStat((double min, double max) depthInterval, IEnumerable telemetryDataStat) + private static TelemetryDataSaubStat? CalcIntervalTelemetryDataStat((double min, double max) depthInterval, IEnumerable telemetryDataStat) { - ProcessTelemetrySaubStat[] data = telemetryDataStat + TelemetryDataSaubStat[] data = telemetryDataStat .Where(d => d.WellDepthMin <= depthInterval.max && d.WellDepthMax >= depthInterval.min) .ToArray(); @@ -174,7 +130,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap return data.First(); - var result = new ProcessTelemetrySaubStat + var result = new TelemetryDataSaubStat { WellDepthMin = data.Min(d => d.WellDepthMin), WellDepthMax = data.Max(d => d.WellDepthMax), @@ -214,7 +170,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap (double min, double max) depthInterval, IEnumerable intervalModeOperations, IEnumerable intervalProcessMap, - ProcessTelemetrySaubStat? telemetryDataStat) + TelemetryDataSaubStat? telemetryDataStat) { var dto = new ProcessMapReportRowDto(); if (intervalModeOperations.Any()) diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs deleted file mode 100644 index 9c09d2ea..00000000 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace AsbCloudInfrastructure.Services.ProcessMap -{ -#nullable enable - class ProcessTelemetrySaubStat { - public int Count { get; set; } - public DateTime DateMin { get; set; } - public DateTime DateMax { get; set; } - - public float WellDepthMin { get; set; } - public float WellDepthMax { get; set; } - - public float Pressure { get; set; } - public float PressureSp { get; set; } - public float PressureIdle { get; set; } - public float PressureSpRotor { get; set; } - public float PressureSpSlide { get; set; } - public float PressureDeltaLimitMax { get; set; } - - public float AxialLoad { get; set; } - public float AxialLoadSp { get; set; } - public float AxialLoadLimitMax { get; set; } - - public float RotorTorque { get; set; } - public float RotorTorqueSp { get; set; } - public float RotorTorqueLimitMax { get; set; } - - public float BlockSpeed { get; set; } - public float BlockSpeedSp { get; set; } - public float BlockSpeedSpRotor { get; set; } - public float BlockSpeedSpSlide { get; set; } - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index 941bc012..d8f7736c 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -17,8 +17,8 @@ namespace AsbCloudInfrastructure.Services.SAUB where TEntity : class, ITelemetryData { protected readonly IAsbCloudDbContext db; - private readonly ITelemetryService telemetryService; - private readonly TelemetryDataCache telemetryDataCache; + protected readonly ITelemetryService telemetryService; + protected readonly TelemetryDataCache telemetryDataCache; public TelemetryDataBaseService( IAsbCloudDbContext db, diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs index 9d666c1c..7839b83b 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs @@ -2,12 +2,17 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.SAUB { #nullable enable - public class TelemetryDataSaubService : TelemetryDataBaseService + public class TelemetryDataSaubService : TelemetryDataBaseService, ITelemetryDataSaubService { private readonly ITelemetryUserService telemetryUserService; @@ -21,6 +26,54 @@ namespace AsbCloudInfrastructure.Services.SAUB this.telemetryUserService = telemetryUserService; } + public async Task> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token) + { + var timezone = telemetryService.GetTimezone(idTelemetry); + var timezoneOffset = TimeSpan.FromHours(timezone.Hours); + + var query = db.Set() + .Where(t => t.IdTelemetry == idTelemetry) + .Where(t => t.BlockPosition > 0.0001) + .Where(t => t.WellDepth > 0.0001) + .Where(t => t.WellDepth - t.BitDepth < 0.01) + .GroupBy(t => new { H = t.DateTime.Hour, W = Math.Truncate(t.WellDepth!.Value) }) + .Select(g => new TelemetryDataSaubStatDto + { + Count = g.Count(), + + DateMin = g.Min(t => t.DateTime.UtcDateTime), + DateMax = g.Max(t => t.DateTime.UtcDateTime), + + WellDepthMin = g.Min(t => t.WellDepth!.Value), + WellDepthMax = g.Max(t => t.WellDepth!.Value), + + Pressure = g.Average(t => t.Pressure!.Value), + PressureSp = g.Average(t => t.PressureSp!.Value), + PressureSpRotor = g.Average(t => t.PressureSpRotor!.Value), + PressureSpSlide = g.Average(t => t.PressureSpSlide!.Value), + PressureIdle = g.Average(t => t.PressureIdle!.Value), + PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax!.Value), + + AxialLoad = g.Average(t => t.AxialLoad!.Value), + AxialLoadSp = g.Average(t => t.AxialLoadSp!.Value), + AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax!.Value), + + RotorTorque = g.Average(t => t.RotorTorque!.Value), + RotorTorqueSp = g.Average(t => t.RotorTorqueSp!.Value), + RotorTorqueLimitMax = g.Average(t => t.RotorTorqueLimitMax!.Value), + + BlockSpeed = g.Average(t => t.BlockSpeed!.Value), + BlockSpeedSp = g.Average(t => t.BlockSpeedSp!.Value), + BlockSpeedSpRotor = g.Average(t => t.BlockSpeedSpRotor!.Value), + BlockSpeedSpSlide = g.Average(t => t.BlockSpeedSpSlide!.Value), + }) + .Where(s => s.WellDepthMin != s.WellDepthMax) + .Where(s => s.Count > 3) + .OrderBy(t => t.DateMin); + + return await query.ToArrayAsync(token); + } + public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset) { var entity = src.Adapt(); From 9f996003eb1181de4897a5655c64d4faeb51de2f Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Fri, 13 Jan 2023 14:34:26 +0500 Subject: [PATCH 07/13] ProcessMapReport. Add GetTelemetryDataStatAsync(..) to TelemetryDataSaubService. --- .../Data/SAUB/TelemetryDataSaubStatDto.cs | 117 ++++++++++++++++++ .../Services/ITelemetryDataSaubService.cs | 26 ++++ AsbCloudApp/Services/ITelemetryDataService.cs | 3 +- AsbCloudInfrastructure/DependencyInjection.cs | 2 +- .../ProcessMap/ProcessMapReportService.cs | 11 +- .../Services/ProcessMap/ProcessMapService.cs | 75 +++-------- .../ProcessMap/ProcessTelemetrySaubStat.cs | 35 ------ .../Services/SAUB/TelemetryDataBaseService.cs | 4 +- .../Services/SAUB/TelemetryDataSaubService.cs | 55 +++++++- 9 files changed, 219 insertions(+), 109 deletions(-) create mode 100644 AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs create mode 100644 AsbCloudApp/Services/ITelemetryDataSaubService.cs delete mode 100644 AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs new file mode 100644 index 00000000..90bbd5f0 --- /dev/null +++ b/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs @@ -0,0 +1,117 @@ +using System; + +namespace AsbCloudApp.Data.SAUB +{ +#nullable enable + /// + /// Статистика телеметрии САУБ (усредненные значения) по интервалам глубины + /// + public class TelemetryDataSaubStatDto + { + /// + /// Кол-во записей в интервале + /// + public int Count { get; set; } + + /// + /// Дата начала интервала + /// + public DateTime DateMin { get; set; } + + /// + /// Дата окончания интервала + /// + public DateTime DateMax { get; set; } + + /// + /// Глубина начала интервала + /// + public float WellDepthMin { get; set; } + + /// + /// Глубина окончания интервала + /// + public float WellDepthMax { get; set; } + + /// + /// Давление + /// + public float Pressure { get; set; } + + /// + /// действующее задание давления + /// + public float PressureSp { get; set; } + + /// + /// Давление при холостом ходе. + /// + public float PressureIdle { get; set; } + + /// + /// задание давления для роторного режима + /// + public float PressureSpRotor { get; set; } + + /// + /// задание давления для режима слайда + /// + public float PressureSpSlide { get; set; } + + /// + /// ограничение макс перепада давления + /// + public float PressureDeltaLimitMax { get; set; } + + /// + /// осевая нагрузка + /// + public float AxialLoad { get; set; } + + /// + /// задание осевой нагрузки + /// + public float AxialLoadSp { get; set; } + + /// + /// ограничение макс. осевой нагрузки + /// + public float AxialLoadLimitMax { get; set; } + + /// + /// момент ротора + /// + public float RotorTorque { get; set; } + + /// + /// задание момента ротора + /// + public float RotorTorqueSp { get; set; } + + /// + /// момент ротора на х.х. + /// + public float RotorTorqueLimitMax { get; set; } + + /// + /// Талевый блок. Скорость + /// + public float BlockSpeed { get; set; } + + /// + /// Талевый блок. Задание скорости + /// + public float BlockSpeedSp { get; set; } + + /// + /// Талевый блок. Задание скорости для роторного бурения + /// + public float BlockSpeedSpRotor { get; set; } + + /// + /// Талевый блок. Задание скорости для режима слайда + /// + public float BlockSpeedSpSlide { get; set; } + } +#nullable disable +} diff --git a/AsbCloudApp/Services/ITelemetryDataSaubService.cs b/AsbCloudApp/Services/ITelemetryDataSaubService.cs new file mode 100644 index 00000000..d6bdcb6f --- /dev/null +++ b/AsbCloudApp/Services/ITelemetryDataSaubService.cs @@ -0,0 +1,26 @@ +using AsbCloudApp.Data.SAUB; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace AsbCloudApp.Services +{ + /// + /// Телеметрия САУБ + /// + public interface ITelemetryDataSaubService : ITelemetryDataService + { + /// + /// усредненная статистика по 1м за весь период + /// + /// МЕДЛЕННЫЙ ЗАПРОС + /// + /// + /// + /// + /// + Task> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token); + } +} +#nullable disable \ No newline at end of file diff --git a/AsbCloudApp/Services/ITelemetryDataService.cs b/AsbCloudApp/Services/ITelemetryDataService.cs index 8efc74ae..585843ff 100644 --- a/AsbCloudApp/Services/ITelemetryDataService.cs +++ b/AsbCloudApp/Services/ITelemetryDataService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; + #nullable enable namespace AsbCloudApp.Services { @@ -33,7 +34,7 @@ namespace AsbCloudApp.Services /// /// /// - Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token = default); + Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token); } } #nullable disable \ No newline at end of file diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 6a2f9fca..1b7b05d1 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -184,7 +184,7 @@ namespace AsbCloudInfrastructure services.AddTransient, CrudCacheRepositoryBase>(); // TelemetryData services - services.AddTransient, TelemetryDataSaubService>(); + services.AddTransient(); services.AddTransient, TelemetryDataSpinService>(); // Wits diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs index fa80efe4..c8357a2a 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs @@ -30,16 +30,9 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var stream = GetExcelTemplateStream(); using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled); - var data = processMapService.GetProcessMapAsync(idWell, token); + var data = await processMapService.GetProcessMapAsync(idWell, token); - //var dtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false); - //if (dtos is not null) - //{ - // var processMapReportDto = await processMapService.GetProcessMapAsync(dtos, token).ConfigureAwait(false); - // FillProcessMapToWorkbook(workbook, processMapReportDto); - //} - - FillProcessMapToWorkbook(workbook, new List()); + FillProcessMapToWorkbook(workbook, data); MemoryStream memoryStream = new MemoryStream(); workbook.SaveAs(memoryStream, new SaveOptions { }); diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs index 13c0db9f..c29ffd8e 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs @@ -5,7 +5,6 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; -using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; @@ -21,17 +20,23 @@ namespace AsbCloudInfrastructure.Services.ProcessMap private readonly IWellOperationRepository wellOperationRepository; private readonly IProcessMapRepository processMapRepository; private readonly ITelemetryService telemetryService; + private readonly ITelemetryDataSaubService telemetryDataSaubService; + private readonly ILimitingParameterRepository limitingParameterRepository; public ProcessMapService( IAsbCloudDbContext db, IWellOperationRepository wellOperationService, IProcessMapRepository processMapRepository, - ITelemetryService telemetryService) + ITelemetryService telemetryService, + ITelemetryDataSaubService telemetryDataSaubService, + ILimitingParameterRepository limitingParameterRepository) { this.db = db; this.wellOperationRepository = wellOperationService; this.processMapRepository = processMapRepository; this.telemetryService = telemetryService; + this.telemetryDataSaubService = telemetryDataSaubService; + this.limitingParameterRepository = limitingParameterRepository; } public async Task> GetProcessMapAsync(int idWell, CancellationToken token) @@ -49,7 +54,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var processMapDtos = (await processMapRepository.GetByIdWellAsync(idWell, token))!; var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell)!.Value; - IEnumerable telemetryDataStat = await GetTelemetryDataAsync(idTelemetry, token); + IEnumerable telemetryDataStat = await telemetryDataSaubService.GetTelemetryDataStatAsync(idTelemetry, token); var result = allFactDrillingOperations .GroupBy(o => o.IdWellSectionType) @@ -63,59 +68,10 @@ namespace AsbCloudInfrastructure.Services.ProcessMap return result; } - private async Task> GetTelemetryDataAsync(int idTelemetry, CancellationToken token) - { - var timezone = telemetryService.GetTimezone(idTelemetry); - var timezoneOffset = TimeSpan.FromHours(timezone.Hours); - - var query = db.Set() - .Where(t => t.IdTelemetry == idTelemetry) - .Where(t => t.BlockPosition > 0.0001) - .Where(t => t.WellDepth > 0.0001) - .Where(t => t.WellDepth - t.BitDepth < 0.01) - .GroupBy(t => new { H = t.DateTime.Hour, W = Math.Truncate(t.WellDepth!.Value) }) - .Select(g => new ProcessTelemetrySaubStat - { - Count = g.Count(), - - DateMin = g.Min(t => t.DateTime.UtcDateTime), - DateMax = g.Max(t => t.DateTime.UtcDateTime), - - WellDepthMin = g.Min(t => t.WellDepth!.Value), - WellDepthMax = g.Max(t => t.WellDepth!.Value), - - Pressure = g.Average(t => t.Pressure!.Value), - PressureSp = g.Average(t => t.PressureSp!.Value), - PressureSpRotor = g.Average(t => t.PressureSpRotor!.Value), - PressureSpSlide = g.Average(t => t.PressureSpSlide!.Value), - PressureIdle = g.Average(t => t.PressureIdle!.Value), - PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax!.Value), - - AxialLoad = g.Average(t => t.AxialLoad!.Value), - AxialLoadSp = g.Average(t => t.AxialLoadSp!.Value), - AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax!.Value), - - RotorTorque = g.Average(t => t.RotorTorque!.Value), - RotorTorqueSp = g.Average(t => t.RotorTorqueSp!.Value), - RotorTorqueLimitMax = g.Average(t => t.RotorTorqueLimitMax!.Value), - - BlockSpeed = g.Average(t => t.BlockSpeed!.Value), - BlockSpeedSp = g.Average(t => t.BlockSpeedSp!.Value), - BlockSpeedSpRotor = g.Average(t => t.BlockSpeedSpRotor!.Value), - BlockSpeedSpSlide = g.Average(t => t.BlockSpeedSpSlide!.Value), - }) - .Where(s => s.WellDepthMin != s.WellDepthMax) - .Where(s => s.Count > 3) - .OrderBy(t => t.DateMin); - - var data = await query.ToArrayAsync(token); - return data; - } - private static IEnumerable HandleSections( IEnumerable sectionOperations, IEnumerable sectionProcessMap, - IEnumerable telemetryDataStat) + IEnumerable telemetryDataStat) { var minDepth = sectionOperations.Min(o => o.DepthStart); var maxDepth = sectionOperations.Max(o => o.DepthEnd); @@ -133,7 +89,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap (double min, double max) depthInterval, IEnumerable sectionOperations, IEnumerable sectionProcessMap, - IEnumerable telemetryDataStat) + IEnumerable telemetryDataStat) { var dto = new ProcessMapReportDto{ DepthStart = depthInterval.min @@ -161,9 +117,9 @@ namespace AsbCloudInfrastructure.Services.ProcessMap return dto; } - private static ProcessTelemetrySaubStat? CalcIntervalTelemetryDataStat((double min, double max) depthInterval, IEnumerable telemetryDataStat) + private static TelemetryDataSaubStatDto? CalcIntervalTelemetryDataStat((double min, double max) depthInterval, IEnumerable telemetryDataStat) { - ProcessTelemetrySaubStat[] data = telemetryDataStat + TelemetryDataSaubStatDto[] data = telemetryDataStat .Where(d => d.WellDepthMin <= depthInterval.max && d.WellDepthMax >= depthInterval.min) .ToArray(); @@ -173,8 +129,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap if (data.Length == 1) return data.First(); - - var result = new ProcessTelemetrySaubStat + var result = new TelemetryDataSaubStatDto { WellDepthMin = data.Min(d => d.WellDepthMin), WellDepthMax = data.Max(d => d.WellDepthMax), @@ -200,7 +155,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap result.RotorTorque += item.RotorTorque * itemWeight; result.RotorTorqueSp += item.RotorTorqueSp * itemWeight; result.RotorTorqueLimitMax += item.RotorTorqueLimitMax * itemWeight; - + result.BlockSpeed += item.BlockSpeed * itemWeight; result.BlockSpeedSp += item.BlockSpeedSp * itemWeight; result.BlockSpeedSpRotor += item.BlockSpeedSpRotor * itemWeight; @@ -214,7 +169,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap (double min, double max) depthInterval, IEnumerable intervalModeOperations, IEnumerable intervalProcessMap, - ProcessTelemetrySaubStat? telemetryDataStat) + TelemetryDataSaubStatDto? telemetryDataStat) { var dto = new ProcessMapReportRowDto(); if (intervalModeOperations.Any()) diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs deleted file mode 100644 index 9c09d2ea..00000000 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessTelemetrySaubStat.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace AsbCloudInfrastructure.Services.ProcessMap -{ -#nullable enable - class ProcessTelemetrySaubStat { - public int Count { get; set; } - public DateTime DateMin { get; set; } - public DateTime DateMax { get; set; } - - public float WellDepthMin { get; set; } - public float WellDepthMax { get; set; } - - public float Pressure { get; set; } - public float PressureSp { get; set; } - public float PressureIdle { get; set; } - public float PressureSpRotor { get; set; } - public float PressureSpSlide { get; set; } - public float PressureDeltaLimitMax { get; set; } - - public float AxialLoad { get; set; } - public float AxialLoadSp { get; set; } - public float AxialLoadLimitMax { get; set; } - - public float RotorTorque { get; set; } - public float RotorTorqueSp { get; set; } - public float RotorTorqueLimitMax { get; set; } - - public float BlockSpeed { get; set; } - public float BlockSpeedSp { get; set; } - public float BlockSpeedSpRotor { get; set; } - public float BlockSpeedSpSlide { get; set; } - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index 941bc012..d8f7736c 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -17,8 +17,8 @@ namespace AsbCloudInfrastructure.Services.SAUB where TEntity : class, ITelemetryData { protected readonly IAsbCloudDbContext db; - private readonly ITelemetryService telemetryService; - private readonly TelemetryDataCache telemetryDataCache; + protected readonly ITelemetryService telemetryService; + protected readonly TelemetryDataCache telemetryDataCache; public TelemetryDataBaseService( IAsbCloudDbContext db, diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs index 9d666c1c..7839b83b 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs @@ -2,12 +2,17 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.SAUB { #nullable enable - public class TelemetryDataSaubService : TelemetryDataBaseService + public class TelemetryDataSaubService : TelemetryDataBaseService, ITelemetryDataSaubService { private readonly ITelemetryUserService telemetryUserService; @@ -21,6 +26,54 @@ namespace AsbCloudInfrastructure.Services.SAUB this.telemetryUserService = telemetryUserService; } + public async Task> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token) + { + var timezone = telemetryService.GetTimezone(idTelemetry); + var timezoneOffset = TimeSpan.FromHours(timezone.Hours); + + var query = db.Set() + .Where(t => t.IdTelemetry == idTelemetry) + .Where(t => t.BlockPosition > 0.0001) + .Where(t => t.WellDepth > 0.0001) + .Where(t => t.WellDepth - t.BitDepth < 0.01) + .GroupBy(t => new { H = t.DateTime.Hour, W = Math.Truncate(t.WellDepth!.Value) }) + .Select(g => new TelemetryDataSaubStatDto + { + Count = g.Count(), + + DateMin = g.Min(t => t.DateTime.UtcDateTime), + DateMax = g.Max(t => t.DateTime.UtcDateTime), + + WellDepthMin = g.Min(t => t.WellDepth!.Value), + WellDepthMax = g.Max(t => t.WellDepth!.Value), + + Pressure = g.Average(t => t.Pressure!.Value), + PressureSp = g.Average(t => t.PressureSp!.Value), + PressureSpRotor = g.Average(t => t.PressureSpRotor!.Value), + PressureSpSlide = g.Average(t => t.PressureSpSlide!.Value), + PressureIdle = g.Average(t => t.PressureIdle!.Value), + PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax!.Value), + + AxialLoad = g.Average(t => t.AxialLoad!.Value), + AxialLoadSp = g.Average(t => t.AxialLoadSp!.Value), + AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax!.Value), + + RotorTorque = g.Average(t => t.RotorTorque!.Value), + RotorTorqueSp = g.Average(t => t.RotorTorqueSp!.Value), + RotorTorqueLimitMax = g.Average(t => t.RotorTorqueLimitMax!.Value), + + BlockSpeed = g.Average(t => t.BlockSpeed!.Value), + BlockSpeedSp = g.Average(t => t.BlockSpeedSp!.Value), + BlockSpeedSpRotor = g.Average(t => t.BlockSpeedSpRotor!.Value), + BlockSpeedSpSlide = g.Average(t => t.BlockSpeedSpSlide!.Value), + }) + .Where(s => s.WellDepthMin != s.WellDepthMax) + .Where(s => s.Count > 3) + .OrderBy(t => t.DateMin); + + return await query.ToArrayAsync(token); + } + public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset) { var entity = src.Adapt(); From 8fd3f3c29034fddef66fb00706ac1e85d61b98f3 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 16 Jan 2023 10:29:52 +0500 Subject: [PATCH 08/13] LimitingParameterDataDto fix. DateTimeOffset -> DateTime --- AsbCloudApp/Data/LimitingParameterDataDto.cs | 4 +-- .../ILimitingParameterRepository.cs | 1 + .../Repository/LimitingParameterRepository.cs | 27 ++++++++++++------- .../Services/LimitingParameterService.cs | 3 +-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/AsbCloudApp/Data/LimitingParameterDataDto.cs b/AsbCloudApp/Data/LimitingParameterDataDto.cs index ee957947..83db213b 100644 --- a/AsbCloudApp/Data/LimitingParameterDataDto.cs +++ b/AsbCloudApp/Data/LimitingParameterDataDto.cs @@ -21,12 +21,12 @@ namespace AsbCloudApp.Data /// /// Дата начала ограничения /// - public DateTimeOffset DateStart { get; set; } + public DateTime DateStart { get; set; } /// /// Дата окончания ограничения /// - public DateTimeOffset DateEnd { get; set; } + public DateTime DateEnd { get; set; } /// /// Глубина начала ограничения diff --git a/AsbCloudApp/Repositories/ILimitingParameterRepository.cs b/AsbCloudApp/Repositories/ILimitingParameterRepository.cs index 507270ef..fcce0759 100644 --- a/AsbCloudApp/Repositories/ILimitingParameterRepository.cs +++ b/AsbCloudApp/Repositories/ILimitingParameterRepository.cs @@ -20,6 +20,7 @@ namespace AsbCloudApp.Repositories /// /// Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token); + Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token); } #nullable disable } diff --git a/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs b/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs index 88c5f869..9c05d743 100644 --- a/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs +++ b/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs @@ -3,6 +3,7 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudDb.Model; using Microsoft.EntityFrameworkCore; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -19,41 +20,49 @@ namespace AsbCloudInfrastructure.Repository { this.context = context; } + public async Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token) { - var query = BuildQuery(request, wellDto); + var timezoneOffset = wellDto.Timezone.Hours; + var IdTelemetry = wellDto.IdTelemetry!.Value; + return await GetLimitingParametersAsync(request, IdTelemetry, timezoneOffset, token); + } + + public async Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token) + { + var timezoneSpan = TimeSpan.FromHours(timezoneHours); + var query = BuildQuery(request, idTelemetry, timezoneHours); var data = (await query.ToListAsync(token)) .Select(x => new LimitingParameterDataDto { - IdWell = wellDto.Id, + IdWell = request.IdWell, IdTelemetry = x.IdTelemetry, IdFeedRegulator = x.IdFeedRegulator, - DateStart = x.DateStart, - DateEnd = x.DateEnd, + DateStart = DateTime.SpecifyKind(x.DateStart.UtcDateTime + timezoneSpan, DateTimeKind.Unspecified), + DateEnd = DateTime.SpecifyKind(x.DateEnd.UtcDateTime + timezoneSpan, DateTimeKind.Unspecified), DepthStart = x.DepthStart, DepthEnd = x.DepthEnd }); - return data; } - private IQueryable BuildQuery(LimitingParameterRequest request, WellDto wellDto) + private IQueryable BuildQuery(LimitingParameterRequest request, int idTelemetry, double timezoneHours) { var query = context.LimitingParameter .OrderBy(x => x.Id) - .Where(x => x.IdTelemetry == wellDto.IdTelemetry) + .Where(x => x.IdTelemetry == idTelemetry) .AsNoTracking(); if (request.GtDate.HasValue) { - var gtDate = request.GtDate.Value.ToUtcDateTimeOffset(wellDto.Timezone.Hours); + var gtDate = request.GtDate.Value.ToUtcDateTimeOffset(timezoneHours); query = query.Where(x => x.DateEnd >= gtDate); } if (request.LtDate.HasValue) { - var ltDate = request.LtDate.Value.ToUtcDateTimeOffset(wellDto.Timezone.Hours); + var ltDate = request.LtDate.Value.ToUtcDateTimeOffset(timezoneHours); query = query.Where(x => x.DateStart <= ltDate); } diff --git a/AsbCloudInfrastructure/Services/LimitingParameterService.cs b/AsbCloudInfrastructure/Services/LimitingParameterService.cs index 0a609507..848fbdf2 100644 --- a/AsbCloudInfrastructure/Services/LimitingParameterService.cs +++ b/AsbCloudInfrastructure/Services/LimitingParameterService.cs @@ -40,7 +40,6 @@ namespace AsbCloudInfrastructure.Services var data = (await limitingParameterRepository.GetLimitingParametersAsync(request, well, token)) .GroupBy(x => x.IdFeedRegulator); - List result = new List(data.Count()); foreach (var item in data) { @@ -107,7 +106,7 @@ namespace AsbCloudInfrastructure.Services return (float)result; } - private DateTimeOffset GetDate(double depth, LimitingParameterDataDto dto) + private DateTime GetDate(double depth, LimitingParameterDataDto dto) { var a = depth - dto.DepthStart; var b = dto.DepthEnd - dto.DepthStart; From f7f0f02c34f171e72ec38b7c227b49fafbd96ef9 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 17 Jan 2023 08:56:07 +0500 Subject: [PATCH 09/13] =?UTF-8?q?ProcessMapReport.=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=87=D0=B5=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D0=BA=20=D0=B2=D1=81=D0=B5=D1=85=20=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D1=81=D1=87=D0=B5=D1=82=D0=BE=D0=B2.=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D1=84=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20excel=20?= =?UTF-8?q?=D0=BF=D0=BE=20dto.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/ProcessMap/ProcessMapReportDto.cs | 2 +- .../ILimitingParameterRepository.cs | 9 + .../ProcessMap/ProcessMapReportService.cs | 179 +++++++++++++++--- .../ProcessMap/ProcessMapReportTemplate.xlsx | Bin 9885 -> 6007 bytes .../Services/ProcessMap/ProcessMapService.cs | 167 +++++++++++----- .../Services/ProcessMap/XLExtentions.cs | 63 ++++++ .../Services/SAUB/TelemetryDataSaubService.cs | 4 +- 7 files changed, 345 insertions(+), 79 deletions(-) create mode 100644 AsbCloudInfrastructure/Services/ProcessMap/XLExtentions.cs diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs index 6bc8ace1..514de0f9 100644 --- a/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs +++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs @@ -27,7 +27,7 @@ namespace AsbCloudApp.Data.ProcessMap /// на начало интервала /// /// - public DateTimeOffset DateStart { get; set; } + public DateTime DateStart { get; set; } /// /// Время мех бурения, ч diff --git a/AsbCloudApp/Repositories/ILimitingParameterRepository.cs b/AsbCloudApp/Repositories/ILimitingParameterRepository.cs index fcce0759..a9b61823 100644 --- a/AsbCloudApp/Repositories/ILimitingParameterRepository.cs +++ b/AsbCloudApp/Repositories/ILimitingParameterRepository.cs @@ -20,6 +20,15 @@ namespace AsbCloudApp.Repositories /// /// Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token); + + /// + /// Получение списка ограничивающих параметров по идентификатору скважины + /// + /// + /// + /// + /// + /// Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token); } #nullable disable diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs index c8357a2a..db5c306e 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs @@ -1,7 +1,5 @@ using AsbCloudApp.Data.ProcessMap; using AsbCloudApp.Services; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.DailyReport; using ClosedXML.Excel; using System.Collections.Generic; using System.IO; @@ -14,14 +12,13 @@ namespace AsbCloudInfrastructure.Services.ProcessMap #nullable enable public class ProcessMapReportService : IProcessMapReportService { - private readonly IAsbCloudDbContext context; - private readonly IProcessMapRepository processMapRepository; + const int firstColumn = 2; + const int headerRowsCount = 3; + private readonly IProcessMapService processMapService; - public ProcessMapReportService(IAsbCloudDbContext context, IProcessMapRepository processMapRepository, IProcessMapService processMapService) + public ProcessMapReportService(IProcessMapService processMapService) { - this.context = context; - this.processMapRepository = processMapRepository; this.processMapService = processMapService; } @@ -40,42 +37,164 @@ namespace AsbCloudInfrastructure.Services.ProcessMap return memoryStream; } - private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable dto) + private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable data) { - var rowsCount = 4; - var columnCount = 2; - var countMerge = 27; - var sheet = workbook.Worksheets.FirstOrDefault(); if (sheet is null) return; - - - sheet.Row(rowsCount).Cell(columnCount).Value = "saddadasdasdasds"; - sheet.Range(rowsCount, columnCount, rowsCount, countMerge).Row(1).Merge(); - SetBorder(sheet.Row(rowsCount).Cell(columnCount).Style); - - rowsCount++; - sheet.Row(rowsCount).Cell(columnCount).Value = 2; - sheet.Row(rowsCount).Cell(columnCount).Value = 3; - columnCount++; - sheet.Row(rowsCount).Cell(columnCount).Value = 4; + var dataBySections = data.GroupBy(p => p.IdWellSectionType); + FillSheet(sheet, dataBySections); } - private Stream GetExcelTemplateStream() + private static void FillSheet(IXLWorksheet sheet, IEnumerable> dataBySections) + { + var startRow = headerRowsCount + 1; + foreach (var sectionData in dataBySections) + { + if(sectionData.Any()) + startRow = FillSection(sheet, sectionData, startRow); + } + } + + private static int FillSection(IXLWorksheet sheet, IGrouping sectionData, int row) + { + var rowStart = row; + const int lastHeaderColumn = 27; + + var sectionName = sectionData.FirstOrDefault()?.WellSectionTypeName + ?? sectionData.Key.ToString(); + + sheet.Range(row, firstColumn, row, lastHeaderColumn) + .Merge() + .FirstCell() + .SetVal(sectionName); + + row++; + + foreach (var interval in sectionData) + row = FillIntervalData(sheet, interval, row); + + var sectionStyle = sheet.Range(rowStart, firstColumn, row - 1, lastHeaderColumn).Style; + SetBorders(sectionStyle); + return row; + } + + private static int FillIntervalData(IXLWorksheet sheet, ProcessMapReportDto interval, int row) + { + const int columnDepth = firstColumn; + const int columnDate = firstColumn + 1; + const int columnRopTime = firstColumn + 2; + const int columnMode = firstColumn + 3; + + int rowRotor = row; + int rowSlide = row + 1; + + sheet.Range(rowRotor, columnDepth, rowSlide, columnDepth) + .Merge().FirstCell() + .SetVal(interval.DepthStart, "0.0"); + + sheet.Range(rowRotor, columnDate, rowSlide, columnDate) + .Merge().FirstCell() + .SetVal(interval.DateStart); + + sheet.Range(rowRotor, columnRopTime, rowSlide, columnRopTime) + .Merge().FirstCell() + .SetVal(interval.MechDrillingHours); + + row = FillIntervalModeData(sheet, "Ротор", interval.Rotor, columnMode, row); + row = FillIntervalModeData(sheet, "Слайд", interval.Rotor, columnMode, row); + + return row; + } + + private static int FillIntervalModeData(IXLWorksheet sheet, string modeName, ProcessMapReportRowDto modeData, int column, int row) + { + int columnDeltaDepth = column + 1; + int columnPressure = columnDeltaDepth + 1; + int columnLoad = columnPressure + 5; + int columnTorque = columnLoad + 5; + int columnSpeed = columnTorque + 5; + int columnUsage = columnSpeed + 4; + int columnRop = columnUsage + 1; + + sheet.Cell(row, column) + .SetVal(modeName); + + sheet.Cell(row, columnDeltaDepth) + .SetVal(modeData.DeltaDepth); + + FillIntervalModeDataParam(sheet, modeData.PressureDiff, columnPressure, row); + FillIntervalModeDataParam(sheet, modeData.AxialLoad, columnLoad, row); + FillIntervalModeDataParam(sheet, modeData.TopDriveTorque, columnTorque, row); + FillIntervalModeDataSpeed(sheet, modeData.SpeedLimit, columnSpeed, row); + + sheet.Cell(row, columnUsage) + .SetVal(modeData.Usage); + + sheet.Cell(row, columnRop) + .SetVal(modeData.Rop); + + return row + 1; + } + + private static void FillIntervalModeDataParam(IXLWorksheet sheet, ProcessMapReportParamsDto dataParam, int column, int row) + { + const int columnOffsetSpPlan = 0; + const int columnOffsetSpFact = 1; + const int columnOffsetFact = 2; + const int columnOffsetLimit = 3; + const int columnOffsetPercent = 4; + + sheet.Cell(row, column + columnOffsetSpPlan) + .SetVal(dataParam.SetpointPlan); + + sheet.Cell(row, column + columnOffsetSpFact) + .SetVal(dataParam.SetpointFact); + + sheet.Cell(row, column + columnOffsetFact) + .SetVal(dataParam.Fact); + + sheet.Cell(row, column + columnOffsetLimit) + .SetVal(dataParam.Limit); + + sheet.Cell(row, column + columnOffsetPercent) + .SetVal(dataParam.PercDrillingSetpoint); + } + + private static void FillIntervalModeDataSpeed(IXLWorksheet sheet, ProcessMapReportParamsDto dataParam, int column, int row) + { + const int columnOffsetSpPlan = 0; + const int columnOffsetSpFact = 1; + const int columnOffsetFact = 2; + const int columnOffsetPercent = 3; + + sheet.Cell(row, column + columnOffsetSpPlan) + .SetVal(dataParam.SetpointPlan); + + sheet.Cell(row, column + columnOffsetSpFact) + .SetVal(dataParam.SetpointFact); + + sheet.Cell(row, column + columnOffsetFact) + .SetVal(dataParam.Fact); + + sheet.Cell(row, column + columnOffsetPercent) + .SetVal(dataParam.PercDrillingSetpoint); + } + + private static Stream GetExcelTemplateStream() { var stream = System.Reflection.Assembly.GetExecutingAssembly() .GetManifestResourceStream("AsbCloudInfrastructure.Services.ProcessMap.ProcessMapReportTemplate.xlsx"); return stream!; } - private static IXLStyle SetBorder(IXLStyle style) + private static IXLStyle SetBorders(IXLStyle style) { - style.Border.RightBorder = XLBorderStyleValues.Medium; - style.Border.LeftBorder = XLBorderStyleValues.Medium; - style.Border.TopBorder = XLBorderStyleValues.Medium; - style.Border.BottomBorder = XLBorderStyleValues.Medium; - style.Border.InsideBorder = XLBorderStyleValues.Medium; + style.Border.RightBorder = XLBorderStyleValues.Thin ; + style.Border.LeftBorder = XLBorderStyleValues.Thin; + style.Border.TopBorder = XLBorderStyleValues.Thin ; + style.Border.BottomBorder = XLBorderStyleValues.Thin ; + style.Border.InsideBorder = XLBorderStyleValues.Thin ; return style; } } diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportTemplate.xlsx b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportTemplate.xlsx index 52e91ccc430913b57a85bdb42eaadb9bfa7227d4..64b328cd82d6f571285c9a726b2ff39661bfb0a3 100644 GIT binary patch literal 6007 zcmaJ_1yq#%@@A=}yFpSyI;BJDM!LIeVOgYGI;2}Vqy$$&@}ndL>28sZMOr}q;CIiJ z>;2zv_H3Q=&b;q$;+dI8O%VZ+01gEO1x{X{QycDqpx^yA0b4n`aj@TiRwZ_*ba7&Y z9r{EupYttBpyZb{E6Fv}@KUxvb|$ZjEbI>XekO&FhY<_yigWc3_-S6eq~y%H#L1v& z9I2%j3E#?K;aA!{_|w&kSfm)7a>}@AG#dwfMB@!{G&jkE+v(}}O^q917xNS3p%%PX zoHh_2Wja4OrGs3;M?5A9(fT>pgB$p2ia?amOy10cJ0}do!@;TjPd8!TUE%4-;Q<0W zn1etL?4C}Ju^Nib^PD(~=LF2FRaL5Z(_E~;IB~f^|KP{UsQ~&o)~5td;*-VMnry2_ zqfbcsV}%M>d!IFLbrRWxc^_{Kjc++>pn#C(T<9(E&fwRAlnB3qNt3=bL>~lt_Ne#2 zRl_rfB1sPSfMgtssql*_MSV>&)7Pg`C71c_u#osfwSv19N+8eJ!o0V$)Df&0fHk48 zLh7w6q;HA5D3UkgB+P@JXgn#}NOJRmwm1{CK1s)8@kdNw;SVx{MD$as?1E}bHH*5b z4(&|rIP$kGwAf)UmAIKPR`MG40~FdM>|JS@5sygfaB`4)_fvFm2G*1vL;8hWd(E7T zcigvdIFdI^Qff69iu6%&@hd8f_#fMQ{iq&LW}9GBR?1pfaOTHb#xALX3P4|_3^y<|vI;U&2Q z-t<<}u7@qE^P)H8xkAgzAMX%O!Q1zVF@>$*XZz?Zk1u@U!AYeZGR8qPtAcaf^RZZT z+w{qYU8kKRsq*qVd-O0G7keqSweHH^Z0AwA7s`81V0K-~pI>iX6g8)F5PjU(cJyw# zh@%RUe6$9dgYgp;>lsVF{2)!|Y|g!0M9mPF^m;loKz0a(De@EHJ}q@(94__mQt}bv zKcyw+-)ZRv@p80syHCn}T_e?bP6EH>>Y8h@#8fq8gDj{v=>-Ex0Ie*F{JQsz4#qPb2IHpSpro0FzM2$5`_fd9Yopc^1rA8C^~+omYNXeqw)`n4`G1^zO~rEr+^xtb4B7+~pJ-PB{G-nW7jU zg4(%F#h7pO!slmcB~d=~LTR>qWK?x1S{6IQp-My9Af1;ua;O7HvL{V3reSY8Yl7M$ zfo;fN*fPs4yxE{)$tD@QmiM7jM~q_rR`EyR&)bV>uFMdMJAYqAnSMVFimu!DWqv``lliXRjE=Pz; z_OmC>aZLJ~=_zV!9G(c$ZVdC6xcC$Y;~Z9;b1Zxv#$}|3NtsCjtUV4?%Zp}h?s3>J zMSD0tln%^$FFm;_e6zi5Id9wSba+F40=0<*)c7t!lj3aNO_QfuKVb z4UJRZq(6L9HbqA|>tqfV-;bqs6680*DM$67JAAVGoHK0dsIU-g6{ZLO@d!jdRwS9} zNY7T(EuzPl{S}MRGjhD_w75%nsi(PnZ1^e+JeL1)5E`3dUDLQ7dwU1jKoqa>ES;mf zT45*pr&=NT4dHIKR#p%_>$SnPJ|Dq!{K=`*r)mwdi&AU!{AoAWkA=0hG)31r%Jt)K80;SU8{&l<*p80jmVO z@$B3hZdad17W^_aYlx0T;xVrUHr7=fc9T9XvFh7qOcy3|MvN=DK;JeRT-DZApXKkH zT(#kaCEj2>#v_G|>d7aU=n;cVr7WW^cJXp7x!=2mo@Dd5{6)tqvFAj71K*2F;Vkb< zE0!$dHls5P%6L!P*1nhN9iK+{T`;T;rRoSix>v3$8t9EK(d3AEr499(IY)V=RSl-yVHTm$FhDX!|x6IeDbNai`lThn>OmeMP(Qx0l8HT}y_ z9Sj;pfXozmyg(OALL-4~W4qW(q_gi=8wRTg{cCi(>f&xItAukuo-4o!4XFD9qkz^- zU$;XP$>gKB&TfJP?K8qyoH#meU-a^dJ;5Ym|4yU8csWg8XMkYEYqJ&NtfiJ`mN~)+ zB~DFllb7>$8lWiS>D!W#J5w&`;Kj)krf|q;*b~7ymwRhHDLxxlnw5nih?nK~1{1=UJ{B zkox`&XFUtazINf_m6yVmz^cf*6%l8MP&vvPtcOZTF3&7?w6#Oi)_hF>pEOOWY|(LM zF)?c9I=YtS=h&qLf|_;98F9-S<3bHd^4?A1%6FE+NJ8(h(0v5+n$13d_AL$ZqFrYT zv})6n+4c%P>CF}x)uyMi2}wsE&vXv!L86I>%R*D&(u82Lz;_T+ZEHbhsNt@GGsN^A zLW7WtjBCEE)-4to{K5 z{p0ds_j+>Qe zxpTv{XyOfTSeoH;XNR2#{cVI_Yh5Jmw`i_b*B|SDLZ>Q^Q_97drFqVo%!wD}RTRc+ zfglOM&<>|D_amW(ATng^aZ8h47UfI)Bw-N$4A$WwF+p-2MAsIDxBS- zn7_=m#3(ZiGVq~qD}q<30NWK>Q#MXG)p@gB_}fy=zWjhN-Aq_q;N3rf+~9^a#|?OXkdl_|Ley1PA<&#k3-+&2#LU4ktin-6R8ZVfggEk1)SCeSTzU% zU33+MkC_QHIxm8lLpF0f>V+ZSYg9!!a_IAGz+Ye_J~69%f~v^Xv$xD)e*@>9zPIY} z-GFh3^H0D@@UJ1m)(mWAsR04oIotf2HHtNroyR2zmfWI7<@TO4B9%Q)*=LUz08q3m zg!QP4sEDc{HS^{}o)uGXLFsRV1Lqmav#2)F4i_W%DStFP8;91)E+6{vEcI-D9ICe} zFO<6UbuS*y(2Ol2EmO`7xQ6|lG#G{um0QoKB%fRomtD%hI>&`95Vhtut5|m{(eugK zNW;D9x8n#vf@1FAEh9|65CP1_{j`@q`v_`dc+CGSD zPkXLxGr^b>+!s;Fi&4~amal54@Oi%L?yll~0xpdADJG3Y%xSPD#k zpgzW>MC0*Ah_CmuerfkYqif^YK3KQ6z5$P>RvMdyZ?N_);xE1_2v~m zNx~0;IHt*b@*z;63T4cxC^>+k7NJ{R`zGCqNr}JHowj}&)Ubp`YoNVbt4gX^K2VMs ztMK9|%l&eA1<2>4X2G#&IUH$Y|Cw|-Wi?x1|LG#IN!XJD^*ongyAo>GBT_fr%{sRx zsC#YiB>v=UK+JbNIv)t(Z5vt$kc*-6%v3ITsb&THzN?ZYH(}2M;NSpA|CAhLe<#P^ zE9ArV=IT)>%6V8n8w61DfG$Z?88JI z0#hdNjHZFM^<)Jq^2z9G4 z%=<{Ga83wyL`8{u262r@-2=T=KH1acHiy?>FfcM}|NQ$Nu@CR;q*g6pw@BNf(;GEX z0@X;ajw0!kFB!J{dVEE&j($h_UPpqwKNlVY{#<9_Br>alO9HVvJHEA&b_7G=L?q$F z!l{U)SItEI#+F8NQCPHU8)7Cyf8bPL%SxXe9Z8l-0tG$#sC;H!Rj>pNlcrk8b6LID zqagO+s>N9#K+tRo?;Lqp-Jr(eFncdze!sq9A6TB7J32jk<5okaIO&@Lm-sp^#Ih4! zmWh@l{?S}rpW^MAvlzWsW|7_JF#)sVb!LmM7|bP^lj$oN7>+~Mm!g`vZM?#8Xfk|3 zD8jtRHVI}k9AhQ#7I793Cfl(|s54l%{M>o^Xq;B9N&UlelyLT?A`?9UzfZMm$yA&k zmBa1To=*}N`R7^cix#n?S+rNfL{FiDeb?N)`(xJj4gR-qK|n>LHH&23j{JqNfH>aU zUvabQk`4E|%V^j?#_bLZf5*+t#pOP1ZxZ^QJ2`Q}4*jC~c2WdT4J6`T6qlDO?9+rU z(b|Y0>qI(zVh?So1`rB(sC?MIvN5ZWT&DM-XsIuu^~y{@#MCVts;8wo9en#Z61!7w zR4;^3uz-=}XZsRx*9C>l4-d6R$C5bMKz+w7ycK50nx*^V<(72BYE7~B6U+<8)n-|I z+XO3~sPI6U0*XeKc*BT6zY7jceSx9P>C;hZN*lhjclZFoLjH#OXOOysgiWu{CUj@( zhNaJ5dE)&np9d@tlRfslipT zPPVY-Cv&n>hr8CNs}QqU$1Fv^NuEwKf%#@yj}Bu72+DwLHvhUW16KnFa@;$2Hs8Jf zH*A+t8WoHnFGis%PKvr;<< zmJ-+(&kV0%rU_cG(@BHWb6nMVjzGhaKEH|T zGazWT3c^vCM|w@KSx}kqo-xwyI(|R(>@ef8nihSnW~{E>(dSkhYjfeOckU^b?Le!c z^q8&q$EL4R1_&&^a|g&(_d~e*HpqcA9ftTlMKPm`oJ3NnnLztTBr)q#4wOgZ#GhT? zuOQV7uEL^F9ca_jd*(uvpu&BZ(5U_!vIYb80eSHJ#^hVB)nP3KScI9jtX}D`Bq0`x zj?95pn!lFJi`n&8>WwZ(!W|jr*m;mez1HO_Pmd8cJNUO=ovuFgG#Rc`RE<4|XZjwU zwqI@_2~&huHU3A|`@xiyKER=kMm*{&UHjyb6%iLwg}}EgbCsHIR&g-N1x=hECHy4; zTP?VVQ>=wK(KA1&vLyON`!=_ZGEc=Kj1KACYkQr~MXq~syE|=`ngTgO!pEC$Hzs!` z@^LTTV%`2=!>#&4$v@#?6fBa$mP(`V_q46<5|zrb(yN#;_dZTvmT22-?s9M9SAzn; z6TtnZI3Kcl_Y~)U$^*hvP4Pb!AM!5uq~C90yt~yO6yTrA4;RsUYUa1JA^cMQP1O9U z`fwDx-&B9g4)VY6`(JzOpH?3B?EA6px6ony{Q!RsaerEP*xT-V`)`rJ`eosNboxK- zJjB}jPWW5&@7(%deeqBAhuCrt$iD^e&f34#{{_!~YCo*td;Iw=W_S;@f1}Z#1|Fu? fe;N?H`}_Zty_zD@U6|nD(C%J=ckN~Mm-qhW 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 q0N@`k@>lrZ4b5NStJHsi|890v6_8-N3jm> GetProcessMapAsync(int idWell, CancellationToken token) { - var operationsRequest = new WellOperationRequest - { - IdWell = idWell, - OperationCategoryIds = WellOperationCategory.MechanicalDrillingSubIds, - OperationType = WellOperation.IdOperationTypeFact, - SortFields = new[]{ nameof(WellOperation.DateStart) } - }; - var allFactDrillingOperations = (await wellOperationRepository.GetAsync(operationsRequest, token)) - .Where(o => o.DepthEnd > o.DepthStart); - - var processMapDtos = (await processMapRepository.GetByIdWellAsync(idWell, token))!; + var well = wellService.GetOrDefault(idWell) + ?? throw new ArgumentInvalidException("idWell not found", nameof(idWell)); + var idTelemetry = well.IdTelemetry + ?? throw new ArgumentInvalidException("telemetry by well not found", nameof(idWell)); - var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell)!.Value; - IEnumerable telemetryDataStat = await telemetryDataSaubService.GetTelemetryDataStatAsync(idTelemetry, token); - - var result = allFactDrillingOperations + var processMap = (await processMapRepository.GetByIdWellAsync(idWell, token))!; + var factDrillingOperations = await GetFactDrillingOperationsAsync(idWell, token); + var telemetryDataStat = await telemetryDataSaubService.GetTelemetryDataStatAsync(idTelemetry, token); + var limitingParameters = await limitingParameterRepository.GetLimitingParametersAsync(new(), well, token); + var subsystemsOperationTime = await GetOperationTimeAsync(idWell, token); + + var result = factDrillingOperations .GroupBy(o => o.IdWellSectionType) .SelectMany(sectionOperations => { - var sectionProcessMap = processMapDtos.Where(p => p.IdWellSectionType == sectionOperations.Key); - return HandleSections(sectionOperations, sectionProcessMap, telemetryDataStat); + var sectionProcessMap = processMap.Where(p => p.IdWellSectionType == sectionOperations.Key); + return HandleSection(sectionOperations, sectionProcessMap, telemetryDataStat, limitingParameters, subsystemsOperationTime!); }) .ToList(); return result; } - private static IEnumerable HandleSections( + private Task?> GetOperationTimeAsync(int idWell, CancellationToken token) + { + var request = new SubsystemOperationTimeRequest + { + IdWell = idWell, + IdsSubsystems = new int[] { SubsystemOperationTimeService.IdSubsystemAKB, SubsystemOperationTimeService.IdSubsystemSpin }, + }; + return subsystemOperationTimeService.GetOperationTimeAsync(request, token); + } + + private async Task> GetFactDrillingOperationsAsync(int idWell, CancellationToken token) + { + var operationsRequest = new WellOperationRequest + { + IdWell = idWell, + OperationCategoryIds = WellOperationCategory.MechanicalDrillingSubIds, + OperationType = WellOperation.IdOperationTypeFact, + SortFields = new[] { nameof(WellOperation.DateStart) } + }; + + var allFactDrillingOperations = await wellOperationRepository.GetAsync(operationsRequest, token); + var factDrillingOperations = allFactDrillingOperations.Where(o => o.DepthEnd > o.DepthStart); + return factDrillingOperations; + } + + private static IEnumerable HandleSection( IEnumerable sectionOperations, IEnumerable sectionProcessMap, - IEnumerable telemetryDataStat) + IEnumerable telemetryDataStat, + IEnumerable limitingParameters, + IEnumerable subsystemsOperationTime) { var minDepth = sectionOperations.Min(o => o.DepthStart); var maxDepth = sectionOperations.Max(o => o.DepthEnd); @@ -80,7 +109,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var result = new ProcessMapReportDto[depthIntervals.Length]; for (var i = 0; i < depthIntervals.Length; i++ ) - result[i] = MakeProcessMapReportDto(depthIntervals[i], sectionOperations, sectionProcessMap, telemetryDataStat); + result[i] = MakeProcessMapReportDto(depthIntervals[i], sectionOperations, sectionProcessMap, telemetryDataStat, limitingParameters, subsystemsOperationTime); return result; } @@ -89,7 +118,9 @@ namespace AsbCloudInfrastructure.Services.ProcessMap (double min, double max) depthInterval, IEnumerable sectionOperations, IEnumerable sectionProcessMap, - IEnumerable telemetryDataStat) + IEnumerable telemetryDataStat, + IEnumerable limitingParameters, + IEnumerable subsystemsOperationTime) { var dto = new ProcessMapReportDto{ DepthStart = depthInterval.min @@ -98,22 +129,25 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var intervalOperations = sectionOperations.Where(o => o.DepthEnd >= depthInterval.min && o.DepthStart <= depthInterval.max); var intervalProcessMap = sectionProcessMap.Where(map => map.DepthEnd >= depthInterval.min && map.DepthStart <= depthInterval.max); var intervalTelemetryDataStat = CalcIntervalTelemetryDataStat(depthInterval, telemetryDataStat); + var intervalLimitingParametrs = limitingParameters.Where(l => l.DepthEnd >= depthInterval.min && l.DepthStart <= depthInterval.max); + var intervalSubsystemsOperationTime = subsystemsOperationTime.Where(o => o.DepthEnd >= depthInterval.min && o.DepthStart <= depthInterval.max); - if (intervalOperations.Any()) + var firstIntervalOperation = intervalOperations.FirstOrDefault(); + if (firstIntervalOperation is not null) { - var firstIntervalOperation = intervalOperations.First(); - var slideOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdSlide); - var rotorOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdRotor); - - dto.DepthStart = depthInterval.min; dto.DateStart = GetInterpolatedDate(firstIntervalOperation, depthInterval.min); dto.IdWell = firstIntervalOperation.IdWell; dto.IdWellSectionType = firstIntervalOperation.IdWellSectionType; dto.WellSectionTypeName = firstIntervalOperation.WellSectionTypeName; - dto.MechDrillingHours = CalcHours(depthInterval, sectionOperations); - dto.Slide = CalcDrillModeStat(depthInterval, slideOperations, intervalProcessMap, intervalTelemetryDataStat); - dto.Rotor = CalcDrillModeStat(depthInterval, rotorOperations, intervalProcessMap, intervalTelemetryDataStat); - } + dto.MechDrillingHours = CalcHours(depthInterval, intervalOperations); + } + + var slideOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdSlide); + var rotorOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdRotor); + + dto.Slide = CalcDrillModeStat(depthInterval, slideOperations, intervalProcessMap, intervalTelemetryDataStat, intervalLimitingParametrs, intervalSubsystemsOperationTime); + dto.Rotor = CalcDrillModeStat(depthInterval, rotorOperations, intervalProcessMap, intervalTelemetryDataStat, intervalLimitingParametrs, intervalSubsystemsOperationTime); + return dto; } @@ -169,22 +203,26 @@ namespace AsbCloudInfrastructure.Services.ProcessMap (double min, double max) depthInterval, IEnumerable intervalModeOperations, IEnumerable intervalProcessMap, - TelemetryDataSaubStatDto? telemetryDataStat) + TelemetryDataSaubStatDto? telemetryDataStat, + IEnumerable intervalLimitingParametrs, + IEnumerable intervalSubsystemsOperationTime) { var dto = new ProcessMapReportRowDto(); if (intervalModeOperations.Any()) { var deltaDepth = CalcDeltaDepth(depthInterval, intervalModeOperations); dto.DeltaDepth = deltaDepth; - dto.Rop = deltaDepth / CalcHours(depthInterval, intervalModeOperations); + dto.Rop = deltaDepth / CalcHours(depthInterval, intervalModeOperations); + }; + if (intervalProcessMap.Any()) + { var processMapFirst = intervalProcessMap.First(); - dto.PressureDiff.SetpointPlan = processMapFirst.Pressure.Plan; dto.AxialLoad.SetpointPlan = processMapFirst.AxialLoad.Plan; dto.TopDriveTorque.SetpointPlan = processMapFirst.TopDriveTorque.Plan; - dto.SpeedLimit.SetpointPlan = double.NaN; - }; + //dto.SpeedLimit.SetpointPlan = null; + } if (telemetryDataStat is not null) { @@ -199,6 +237,46 @@ namespace AsbCloudInfrastructure.Services.ProcessMap dto.TopDriveTorque.SetpointFact = telemetryDataStat.RotorTorqueSp; dto.TopDriveTorque.Fact = telemetryDataStat.RotorTorque; dto.TopDriveTorque.Limit = telemetryDataStat.RotorTorqueLimitMax; + + dto.SpeedLimit.SetpointFact = telemetryDataStat.BlockSpeedSp; + dto.SpeedLimit.Fact = telemetryDataStat.BlockSpeed; + //dto.SpeedLimit.Limit = mull; + } + + if(intervalLimitingParametrs.Any()) + { + const int idLimParamRop = 1; + const int idLimParamPressure = 2; + const int idLimParamAxialLoad = 3; + const int idLimParamTorque = 4; + + var intervalLimitingParametrsStat = intervalLimitingParametrs + .GroupBy(p => p.IdFeedRegulator) + .Select(g => new + { + IdLimParam = g.Key, + SumDepth = g.Sum(p => p.DepthEnd - p.DepthStart), + }); + + var totalDepth = intervalLimitingParametrsStat + .Sum(s => s.SumDepth); + + dto.AxialLoad.PercDrillingSetpoint = intervalLimitingParametrsStat + .FirstOrDefault(s => s.IdLimParam == idLimParamAxialLoad)?.SumDepth / totalDepth; + + dto.PressureDiff.PercDrillingSetpoint = intervalLimitingParametrsStat + .FirstOrDefault(s => s.IdLimParam == idLimParamPressure)?.SumDepth / totalDepth; + + dto.TopDriveTorque.PercDrillingSetpoint = intervalLimitingParametrsStat + .FirstOrDefault(s => s.IdLimParam == idLimParamTorque)?.SumDepth / totalDepth; + + dto.SpeedLimit.PercDrillingSetpoint = intervalLimitingParametrsStat + .FirstOrDefault(s => s.IdLimParam == idLimParamRop)?.SumDepth / totalDepth; + } + + if (intervalSubsystemsOperationTime.Any() && dto.DeltaDepth > 0) + { + dto.Usage = intervalSubsystemsOperationTime.Sum(t => t.DepthEnd - t.DepthStart) / dto.DeltaDepth.Value; } return dto; @@ -242,9 +320,6 @@ namespace AsbCloudInfrastructure.Services.ProcessMap private static DateTime GetInterpolatedDate(WellOperationDto operation, double depth) { - if (operation.DepthStart > depth) - throw new ArgumentOutOfRangeException(nameof(depth)); - var ratio = (depth - operation.DepthStart) / (operation.DepthEnd - operation.DepthStart); var deltaHours = operation.DurationHours * ratio; var interpolatedDate = operation.DateStart + TimeSpan.FromHours(deltaHours); diff --git a/AsbCloudInfrastructure/Services/ProcessMap/XLExtentions.cs b/AsbCloudInfrastructure/Services/ProcessMap/XLExtentions.cs new file mode 100644 index 00000000..7117e1cf --- /dev/null +++ b/AsbCloudInfrastructure/Services/ProcessMap/XLExtentions.cs @@ -0,0 +1,63 @@ +using ClosedXML.Excel; +using System; + +namespace AsbCloudInfrastructure.Services.ProcessMap; + +internal static class XLExtentions +{ + public static IXLCell SetVal(this IXLCell cell, object value) + { + switch (value) + { + case DateTime dateTime: + cell.SetVal(dateTime); + break; + case IFormattable formattable: + cell.SetVal(formattable); + break; + case string valueString: + cell.SetVal(valueString); + break; + default: + cell.Value = value; + break; + } + + return cell; + } + + public static IXLCell SetVal(this IXLCell cell, string value, bool adaptRowHeight = false) + { + cell.Value = value; + if (adaptRowHeight) + { + var colWidth = cell.WorksheetColumn().Width; + var maxCharsToWrap = colWidth / (0.1d * cell.Style.Font.FontSize); + if (value.Length > maxCharsToWrap) + { + var row = cell.WorksheetRow(); + var baseHeight = row.Height; + row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap); + } + } + + return cell; + } + + public static IXLCell SetVal(this IXLCell cell, DateTime value, string dateFormat = "DD.MM.YYYY HH:MM:SS") + { + cell.Value = value; + cell.DataType = XLDataType.DateTime; + cell.Style.DateFormat.Format = dateFormat; + + return cell; + } + + public static IXLCell SetVal(this IXLCell cell, IFormattable value, string format = "0.00") + { + cell.Value = value; + cell.DataType = XLDataType.Number; + cell.Style.NumberFormat.Format = format; + return cell; + } +} diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs index 7839b83b..8ec8cb10 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs @@ -41,8 +41,8 @@ namespace AsbCloudInfrastructure.Services.SAUB { Count = g.Count(), - DateMin = g.Min(t => t.DateTime.UtcDateTime), - DateMax = g.Max(t => t.DateTime.UtcDateTime), + DateMin = DateTime.SpecifyKind(g.Min(t => t.DateTime.UtcDateTime) + timezoneOffset, DateTimeKind.Unspecified), + DateMax = DateTime.SpecifyKind(g.Max(t => t.DateTime.UtcDateTime) + timezoneOffset, DateTimeKind.Unspecified), WellDepthMin = g.Min(t => t.WellDepth!.Value), WellDepthMax = g.Max(t => t.WellDepth!.Value), From e398beaaa1eb5851014f83b4709638e0ef39b09e Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 17 Jan 2023 10:00:08 +0500 Subject: [PATCH 10/13] ProcessMapReport. Add some todos. --- .../ProcessMap/ProcessMapReportService.cs | 7 +++--- .../Services/ProcessMap/ProcessMapService.cs | 23 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs index db5c306e..da7f3f79 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs @@ -13,6 +13,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMap public class ProcessMapReportService : IProcessMapReportService { const int firstColumn = 2; + const int lastColumn = 27; + const int headerRowsCount = 3; private readonly IProcessMapService processMapService; @@ -59,12 +61,11 @@ namespace AsbCloudInfrastructure.Services.ProcessMap private static int FillSection(IXLWorksheet sheet, IGrouping sectionData, int row) { var rowStart = row; - const int lastHeaderColumn = 27; var sectionName = sectionData.FirstOrDefault()?.WellSectionTypeName ?? sectionData.Key.ToString(); - sheet.Range(row, firstColumn, row, lastHeaderColumn) + sheet.Range(row, firstColumn, row, lastColumn) .Merge() .FirstCell() .SetVal(sectionName); @@ -74,7 +75,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap foreach (var interval in sectionData) row = FillIntervalData(sheet, interval, row); - var sectionStyle = sheet.Range(rowStart, firstColumn, row - 1, lastHeaderColumn).Style; + var sectionStyle = sheet.Range(rowStart, firstColumn, row - 1, lastColumn).Style; SetBorders(sectionStyle); return row; } diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs index 3342b24c..0884896d 100644 --- a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs @@ -13,8 +13,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using AsbCloudDb.Model.Subsystems; -using System.Reflection.Metadata.Ecma335; using AsbCloudInfrastructure.Services.Subsystems; namespace AsbCloudInfrastructure.Services.ProcessMap @@ -126,6 +124,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap DepthStart = depthInterval.min }; + // TODO: trim items by detpth intervals. Use linear interpolation. var intervalOperations = sectionOperations.Where(o => o.DepthEnd >= depthInterval.min && o.DepthStart <= depthInterval.max); var intervalProcessMap = sectionProcessMap.Where(map => map.DepthEnd >= depthInterval.min && map.DepthStart <= depthInterval.max); var intervalTelemetryDataStat = CalcIntervalTelemetryDataStat(depthInterval, telemetryDataStat); @@ -142,6 +141,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMap dto.MechDrillingHours = CalcHours(depthInterval, intervalOperations); } + // TODO: Разделить интервальные коллекции на ротор и слайд. Пока нет готовой методики. var slideOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdSlide); var rotorOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdRotor); @@ -261,17 +261,20 @@ namespace AsbCloudInfrastructure.Services.ProcessMap var totalDepth = intervalLimitingParametrsStat .Sum(s => s.SumDepth); - dto.AxialLoad.PercDrillingSetpoint = intervalLimitingParametrsStat - .FirstOrDefault(s => s.IdLimParam == idLimParamAxialLoad)?.SumDepth / totalDepth; + if (totalDepth > 0) + { + dto.AxialLoad.PercDrillingSetpoint = intervalLimitingParametrsStat + .FirstOrDefault(s => s.IdLimParam == idLimParamAxialLoad)?.SumDepth / totalDepth; - dto.PressureDiff.PercDrillingSetpoint = intervalLimitingParametrsStat - .FirstOrDefault(s => s.IdLimParam == idLimParamPressure)?.SumDepth / totalDepth; + dto.PressureDiff.PercDrillingSetpoint = intervalLimitingParametrsStat + .FirstOrDefault(s => s.IdLimParam == idLimParamPressure)?.SumDepth / totalDepth; - dto.TopDriveTorque.PercDrillingSetpoint = intervalLimitingParametrsStat - .FirstOrDefault(s => s.IdLimParam == idLimParamTorque)?.SumDepth / totalDepth; + dto.TopDriveTorque.PercDrillingSetpoint = intervalLimitingParametrsStat + .FirstOrDefault(s => s.IdLimParam == idLimParamTorque)?.SumDepth / totalDepth; - dto.SpeedLimit.PercDrillingSetpoint = intervalLimitingParametrsStat - .FirstOrDefault(s => s.IdLimParam == idLimParamRop)?.SumDepth / totalDepth; + dto.SpeedLimit.PercDrillingSetpoint = intervalLimitingParametrsStat + .FirstOrDefault(s => s.IdLimParam == idLimParamRop)?.SumDepth / totalDepth; + } } if (intervalSubsystemsOperationTime.Any() && dto.DeltaDepth > 0) From 595eca8e267bdf6a57fa89c6d12ea09771f6d431 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 17 Jan 2023 13:28:35 +0500 Subject: [PATCH 11/13] nit code format --- .../Repository/TelemetryWirelineRunOutRepository.cs | 2 -- AsbCloudInfrastructure/Repository/WellOperationRepository.cs | 2 -- .../Controllers/SAUB/TelemetryWirelineRunOutController.cs | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs b/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs index 134a1ac8..325bb2b4 100644 --- a/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs +++ b/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs @@ -2,9 +2,7 @@ using AsbCloudApp.Data.SAUB; using AsbCloudApp.Repositories; using AsbCloudApp.Services; -using AsbCloudDb; using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.SAUB; using Mapster; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index bb958034..e47a9460 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -260,8 +260,6 @@ namespace AsbCloudInfrastructure.Repository IdWellSectionType = o.IdWellSectionType, IdCategory = o.IdCategory, - //o.Well, - //o.OperationCategory, CategoryName = o.WellSectionType.Caption, WellSectionTypeName = o.WellSectionType.Caption, diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs index c32fd408..c7829193 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs @@ -24,7 +24,7 @@ namespace AsbCloudWebApi.Controllers.SAUB private readonly IWellService wellService; private readonly IHubContext telemetryHubContext; private readonly ITelemetryWirelineRunOutRepository repository; - private string SirnalRMethodGetDataName => "ReceiveWirelineRunOut"; + private static string SirnalRMethodGetDataName => "ReceiveWirelineRunOut"; public TelemetryWirelineRunOutController( ITelemetryService telemetryService, From 07f77f83d82074326122229957015bc1a02b4b74 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 17 Jan 2023 15:39:36 +0500 Subject: [PATCH 12/13] fix TelemetryDataSaubController --- AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs index b9ff1d88..4248778b 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs @@ -15,7 +15,7 @@ namespace AsbCloudWebApi.Controllers.SAUB { public TelemetryDataSaubController( ITelemetryService telemetryService, - ITelemetryDataService telemetryDataService, + ITelemetryDataSaubService telemetryDataService, IWellService wellService, IHubContext telemetryHubContext) : base( From fa6fdc067e2cb37f1a275a70a2ea721e7bcb2565 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 17 Jan 2023 15:40:49 +0500 Subject: [PATCH 13/13] WellFinalDocumentsService.ReNotifyPublishersAsync replace exception type by argumentInvalid --- AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index 818eef38..4ffaa620 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -204,7 +204,7 @@ namespace AsbCloudInfrastructure.Services })); if(!docs.Any()) - throw new Exception("Нет такой категории, или в нее уже загружен документ"); + throw new ArgumentInvalidException("Нет такой категории, или в нее уже загружен документ", nameof(idCategory)); var message = requester.MakeDisplayName() + " ожидает от Вас загрузку на портал документа «{{0}}»"; await GenerateMessageAsync(docs, message, token);