2023-10-09 17:04:05 +05:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
2023-11-09 15:01:29 +05:00
|
|
|
|
using AsbCloudApp.Data;
|
2023-10-09 17:04:05 +05:00
|
|
|
|
using AsbCloudApp.Data.ProcessMaps;
|
|
|
|
|
using AsbCloudApp.Data.ProcessMaps.Report;
|
|
|
|
|
using AsbCloudApp.Data.SAUB;
|
|
|
|
|
using AsbCloudApp.Exceptions;
|
|
|
|
|
using AsbCloudApp.Repositories;
|
|
|
|
|
using AsbCloudApp.Services;
|
2023-10-16 13:45:29 +05:00
|
|
|
|
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
2023-10-17 10:20:27 +05:00
|
|
|
|
using AsbCloudInfrastructure.Services.ProcessMaps.Report.Data;
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
2023-10-17 10:20:27 +05:00
|
|
|
|
namespace AsbCloudInfrastructure.Services.ProcessMaps.Report;
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
2023-10-16 13:45:29 +05:00
|
|
|
|
public class ProcessMapReportWellDrillingService : IProcessMapReportWellDrillingService
|
2023-10-09 17:04:05 +05:00
|
|
|
|
{
|
|
|
|
|
private readonly IWellService wellService;
|
2023-10-12 15:26:37 +05:00
|
|
|
|
private readonly IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto> processMapPlanWellDrillingRepository;
|
2023-10-09 17:04:05 +05:00
|
|
|
|
private readonly ITelemetryDataSaubService telemetryDataSaubService;
|
|
|
|
|
private readonly IWellOperationRepository wellOperationRepository;
|
|
|
|
|
|
2023-10-16 13:45:29 +05:00
|
|
|
|
public ProcessMapReportWellDrillingService(IWellService wellService,
|
2023-10-17 10:20:27 +05:00
|
|
|
|
IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto> processMapPlanWellDrillingRepository,
|
2023-10-09 17:04:05 +05:00
|
|
|
|
ITelemetryDataSaubService telemetryDataSaubService,
|
|
|
|
|
IWellOperationRepository wellOperationRepository)
|
|
|
|
|
{
|
|
|
|
|
this.wellService = wellService;
|
2023-10-12 15:26:37 +05:00
|
|
|
|
this.processMapPlanWellDrillingRepository = processMapPlanWellDrillingRepository;
|
2023-10-09 17:04:05 +05:00
|
|
|
|
this.telemetryDataSaubService = telemetryDataSaubService;
|
|
|
|
|
this.wellOperationRepository = wellOperationRepository;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
public async Task<IEnumerable<ProcessMapReportWellDrillingDto>> GetAsync(int idWell,
|
2023-10-09 17:04:05 +05:00
|
|
|
|
CancellationToken token)
|
|
|
|
|
{
|
|
|
|
|
var well = await wellService.GetOrDefaultAsync(idWell, token)
|
|
|
|
|
?? throw new ArgumentInvalidException(nameof(idWell), $"Скважина с Id: {idWell} не найдена");
|
|
|
|
|
|
|
|
|
|
if (!well.IdTelemetry.HasValue)
|
2023-12-25 16:16:06 +05:00
|
|
|
|
return Enumerable.Empty<ProcessMapReportWellDrillingDto>();
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var processMapPlanWellDrillings = await processMapPlanWellDrillingRepository.GetByIdWellAsync(idWell, token);
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
if (!processMapPlanWellDrillings.Any())
|
|
|
|
|
return Enumerable.Empty<ProcessMapReportWellDrillingDto>();
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
|
|
|
|
var telemetryDataStat =
|
|
|
|
|
(await telemetryDataSaubService.GetTelemetryDataStatAsync(well.IdTelemetry.Value, token)).ToArray();
|
|
|
|
|
|
|
|
|
|
if (!telemetryDataStat.Any())
|
2023-10-12 15:26:37 +05:00
|
|
|
|
return Enumerable.Empty<ProcessMapReportWellDrillingDto>();
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var result = CalcByIntervals(processMapPlanWellDrillings, telemetryDataStat);
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
private IEnumerable<ProcessMapReportWellDrillingDto> CalcByIntervals(
|
|
|
|
|
IEnumerable<ProcessMapPlanWellDrillingDto> processMapPlanWellDrillings,
|
2023-10-09 17:04:05 +05:00
|
|
|
|
TelemetryDataSaubStatDto[] telemetryDataStat)
|
|
|
|
|
{
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var processMapIntervals = CalcDepthIntervals(processMapPlanWellDrillings);
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var result = new List<ProcessMapReportWellDrillingDto>(processMapIntervals.Count() * 4);
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
|
|
|
|
var telemetryIndexStart =
|
|
|
|
|
Array.FindIndex(telemetryDataStat, t => t.WellDepthMin >= processMapIntervals.First().DepthStart);
|
|
|
|
|
if (telemetryIndexStart < 0)
|
2023-10-12 15:26:37 +05:00
|
|
|
|
return Enumerable.Empty<ProcessMapReportWellDrillingDto>();
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
|
|
|
|
IDictionary<int, string> sectionTypes = wellOperationRepository
|
|
|
|
|
.GetSectionTypes()
|
|
|
|
|
.ToDictionary(s => s.Id, s => s.Caption);
|
|
|
|
|
|
|
|
|
|
foreach (var interval in processMapIntervals)
|
|
|
|
|
{
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var processMapPlanWellDrillingInterval = processMapPlanWellDrillings
|
2023-10-09 17:04:05 +05:00
|
|
|
|
.Where(p => p.DepthStart <= interval.DepthEnd && p.DepthEnd >= interval.DepthStart);
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
if (!processMapPlanWellDrillingInterval.Any())
|
2023-10-09 17:04:05 +05:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var telemetryIndexEnd = Array.FindIndex(telemetryDataStat, telemetryIndexStart,
|
|
|
|
|
t => t.WellDepthMin >= interval.DepthEnd);
|
|
|
|
|
if (telemetryIndexEnd < 0)
|
|
|
|
|
telemetryIndexEnd = telemetryDataStat.Length - 1;
|
|
|
|
|
var telemetryDataInterval =
|
|
|
|
|
telemetryDataStat.AsSpan(telemetryIndexStart, telemetryIndexEnd - telemetryIndexStart);
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
IEnumerable<ProcessMapReportWellDrillingDto> subIntervalsResult =
|
|
|
|
|
CalcSubIntervals(interval, processMapPlanWellDrillingInterval, telemetryDataInterval, sectionTypes);
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
|
|
|
|
result.AddRange(subIntervalsResult);
|
|
|
|
|
telemetryIndexStart = telemetryIndexEnd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<(double DepthStart, double DepthEnd)> CalcDepthIntervals(
|
2023-10-12 15:26:37 +05:00
|
|
|
|
IEnumerable<ProcessMapPlanWellDrillingDto> processMapPlanWellDrillings)
|
2023-10-09 17:04:05 +05:00
|
|
|
|
{
|
2023-10-12 15:26:37 +05:00
|
|
|
|
if (!processMapPlanWellDrillings.Any())
|
2023-10-09 17:04:05 +05:00
|
|
|
|
yield break;
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var intervalStarts = processMapPlanWellDrillings
|
2023-10-09 17:04:05 +05:00
|
|
|
|
.OrderBy(i => i.DepthStart)
|
|
|
|
|
.Select(p => p.DepthStart)
|
|
|
|
|
.Distinct()
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
|
|
|
|
for (var i = 1; i < intervalStarts.Length; i++)
|
|
|
|
|
yield return (intervalStarts[i - 1], intervalStarts[i]);
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
yield return (intervalStarts[^1], processMapPlanWellDrillings.Max(p => p.DepthEnd));
|
2023-10-09 17:04:05 +05:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
private static IEnumerable<ProcessMapReportWellDrillingDto> CalcSubIntervals(
|
2023-10-09 17:04:05 +05:00
|
|
|
|
(double DepthStart, double DepthEnd) interval,
|
2023-10-12 15:26:37 +05:00
|
|
|
|
IEnumerable<ProcessMapPlanWellDrillingDto> processMapPlanWellDrillingInterval,
|
2023-10-09 17:04:05 +05:00
|
|
|
|
Span<TelemetryDataSaubStatDto> telemetryDataInterval,
|
|
|
|
|
IDictionary<int, string> sectionTypes)
|
|
|
|
|
{
|
|
|
|
|
var telemetryDataIntervalLength = telemetryDataInterval.Length;
|
|
|
|
|
if (telemetryDataInterval.Length == 0)
|
2023-10-12 15:26:37 +05:00
|
|
|
|
return Enumerable.Empty<ProcessMapReportWellDrillingDto>();
|
2023-10-09 17:04:05 +05:00
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var result = new List<ProcessMapReportWellDrillingDto>();
|
2023-10-09 17:04:05 +05:00
|
|
|
|
var telemetryIndexStart = 0;
|
|
|
|
|
var subInterval = interval;
|
|
|
|
|
|
|
|
|
|
for (var i = telemetryIndexStart + 1; i < telemetryDataIntervalLength; i++)
|
|
|
|
|
{
|
|
|
|
|
if (IsDifferent(telemetryDataInterval[telemetryIndexStart], telemetryDataInterval[i]))
|
|
|
|
|
{
|
|
|
|
|
subInterval.DepthEnd = telemetryDataInterval[i - 1].WellDepthMax;
|
|
|
|
|
var telemetryRowSpan = telemetryDataInterval[telemetryIndexStart..(i - 1)];
|
|
|
|
|
|
|
|
|
|
if (!telemetryRowSpan.IsEmpty)
|
|
|
|
|
{
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var intervalReportRow = CalcSubIntervalReportRow(subInterval, processMapPlanWellDrillingInterval,
|
2023-10-09 17:04:05 +05:00
|
|
|
|
telemetryRowSpan, sectionTypes);
|
|
|
|
|
result.Add(intervalReportRow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
telemetryIndexStart = i;
|
|
|
|
|
subInterval.DepthStart = subInterval.DepthEnd;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subInterval.DepthEnd = interval.DepthEnd;
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var intervalReportRowLast = CalcSubIntervalReportRow(subInterval, processMapPlanWellDrillingInterval,
|
2023-10-09 17:04:05 +05:00
|
|
|
|
telemetryDataInterval[telemetryIndexStart..telemetryDataIntervalLength], sectionTypes);
|
|
|
|
|
result.Add(intervalReportRowLast);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
private static ProcessMapReportWellDrillingDto CalcSubIntervalReportRow(
|
2023-10-09 17:04:05 +05:00
|
|
|
|
(double DepthStart, double DepthEnd) subInterval,
|
2023-10-12 15:26:37 +05:00
|
|
|
|
IEnumerable<ProcessMapPlanWellDrillingDto> processMapPlanWellDrillings,
|
2023-10-09 17:04:05 +05:00
|
|
|
|
Span<TelemetryDataSaubStatDto> telemetryRowSpan,
|
|
|
|
|
IDictionary<int, string> sectionTypes)
|
|
|
|
|
{
|
|
|
|
|
var telemetryStat = new TelemetryStat(telemetryRowSpan);
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var processMapByMode = processMapPlanWellDrillings.FirstOrDefault(p => p.IdMode == telemetryStat.IdMode);
|
|
|
|
|
var processMapFirst = processMapPlanWellDrillings.First();
|
2023-10-09 17:04:05 +05:00
|
|
|
|
var idWellSectionType = processMapByMode?.IdWellSectionType ?? processMapFirst.IdWellSectionType;
|
|
|
|
|
|
2023-10-12 15:26:37 +05:00
|
|
|
|
var result = new ProcessMapReportWellDrillingDto
|
2023-10-09 17:04:05 +05:00
|
|
|
|
{
|
|
|
|
|
IdWell = processMapByMode?.IdWell ?? processMapFirst.IdWell,
|
|
|
|
|
IdWellSectionType = idWellSectionType,
|
|
|
|
|
WellSectionTypeName = sectionTypes[idWellSectionType],
|
|
|
|
|
|
|
|
|
|
DepthStart = subInterval.DepthStart,
|
|
|
|
|
DepthEnd = subInterval.DepthEnd,
|
|
|
|
|
DateStart = telemetryStat.DateStart,
|
|
|
|
|
|
2023-10-17 10:20:27 +05:00
|
|
|
|
MechDrillingHours = telemetryStat.DrillingHours,
|
2023-10-09 17:04:05 +05:00
|
|
|
|
DrillingMode = telemetryStat.ModeName,
|
|
|
|
|
|
|
|
|
|
DeltaDepth = telemetryStat.DeltaDepth,
|
|
|
|
|
|
|
|
|
|
PressureDiff = telemetryStat.Pressure.MakeParams(processMapByMode?.Pressure.Plan),
|
|
|
|
|
AxialLoad = telemetryStat.AxialLoad.MakeParams(processMapByMode?.AxialLoad.Plan),
|
|
|
|
|
TopDriveTorque = telemetryStat.RotorTorque.MakeParams(processMapByMode?.TopDriveTorque.Plan),
|
|
|
|
|
SpeedLimit = telemetryStat.BlockSpeed.MakeParams(processMapByMode?.RopPlan),
|
|
|
|
|
|
2023-11-09 15:01:29 +05:00
|
|
|
|
Rop = new PlanFactDto<double?>
|
|
|
|
|
{
|
|
|
|
|
Plan = processMapByMode?.RopPlan,
|
|
|
|
|
Fact = telemetryStat.Rop
|
|
|
|
|
},
|
|
|
|
|
|
2023-10-09 17:04:05 +05:00
|
|
|
|
UsagePlan = processMapByMode?.UsageSaub ?? telemetryStat.UsagePredictPlan,
|
|
|
|
|
UsageFact = telemetryStat.UsageSaub,
|
|
|
|
|
};
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool IsDifferent(TelemetryDataSaubStatDto intervalStart, TelemetryDataSaubStatDto current)
|
|
|
|
|
{
|
|
|
|
|
if (intervalStart.WellDepthMin > current.WellDepthMin)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (intervalStart.IdMode != current.IdMode)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (Math.Abs(intervalStart.PressureSp - current.PressureSp) > 5d)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (Math.Abs(intervalStart.AxialLoadSp - current.AxialLoadSp) > 1d)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (Math.Abs(intervalStart.RotorTorqueSp - current.RotorTorqueSp) > 5d)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
var blockSpeedSpDiff = Math.Abs(intervalStart.BlockSpeedSp - current.BlockSpeedSp);
|
|
|
|
|
if (!(blockSpeedSpDiff > 5d))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
switch (intervalStart.BlockSpeedSp)
|
|
|
|
|
{
|
|
|
|
|
case <= 30:
|
|
|
|
|
case > 30 when blockSpeedSpDiff > 15d:
|
|
|
|
|
case > 80 when blockSpeedSpDiff > 20d:
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|