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 }