forked from ddrilling/AsbCloudServer
239 lines
9.1 KiB
C#
239 lines
9.1 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using AsbCloudApp.Data;
|
|
using AsbCloudApp.Data.ProcessMaps.Operations;
|
|
using AsbCloudApp.Data.Trajectory;
|
|
using AsbCloudApp.Data.WellOperation;
|
|
using AsbCloudApp.Data.WellReport;
|
|
using AsbCloudApp.Repositories;
|
|
using AsbCloudApp.Requests;
|
|
using AsbCloudApp.Services;
|
|
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
|
using AsbCloudApp.Services.WellReport;
|
|
using AsbCloudDb.Model;
|
|
|
|
namespace AsbCloudInfrastructure.Services.WellReport;
|
|
|
|
public class WellReportService : IWellReportService
|
|
{
|
|
private readonly IWellService wellService;
|
|
private readonly IWellOperationService wellOperationService;
|
|
private readonly IWellContactService wellContactService;
|
|
private readonly IProcessMapReportDrillingService processMapReportDrillingService;
|
|
private readonly ISubsystemService subsystemService;
|
|
|
|
private readonly ITrajectoryRepository<TrajectoryGeoPlanDto> trajectoryPlanRepository;
|
|
private readonly ITrajectoryRepository<TrajectoryGeoFactDto> trajectoryFactRepository;
|
|
|
|
private readonly IChangeLogRepository<ProcessMapPlanRotorDto, ProcessMapPlanBaseRequestWithWell>
|
|
processMapPlanRotorRepository;
|
|
|
|
private readonly IScheduleRepository scheduleRepository;
|
|
|
|
private IEnumerable<WellOperationDto> factWellOperations;
|
|
private IEnumerable<WellOperationDto> planWellOperations;
|
|
|
|
public WellReportService(IWellService wellService,
|
|
IWellOperationService wellOperationService,
|
|
IWellContactService wellContactService,
|
|
IProcessMapReportDrillingService processMapReportDrillingService,
|
|
ISubsystemService subsystemService,
|
|
ITrajectoryRepository<TrajectoryGeoPlanDto> trajectoryPlanRepository,
|
|
ITrajectoryRepository<TrajectoryGeoFactDto> trajectoryFactRepository,
|
|
IChangeLogRepository<ProcessMapPlanRotorDto, ProcessMapPlanBaseRequestWithWell> processMapPlanRotorRepository,
|
|
IScheduleRepository scheduleRepository)
|
|
{
|
|
this.wellService = wellService;
|
|
this.wellOperationService = wellOperationService;
|
|
this.wellContactService = wellContactService;
|
|
this.processMapReportDrillingService = processMapReportDrillingService;
|
|
this.subsystemService = subsystemService;
|
|
this.trajectoryPlanRepository = trajectoryPlanRepository;
|
|
this.trajectoryFactRepository = trajectoryFactRepository;
|
|
this.processMapPlanRotorRepository = processMapPlanRotorRepository;
|
|
this.scheduleRepository = scheduleRepository;
|
|
}
|
|
|
|
public async Task<WellReportDto?> GetAsync(int idWell, CancellationToken token)
|
|
{
|
|
var well = await wellService.GetOrDefaultAsync(idWell, token);
|
|
|
|
if (well == null)
|
|
return null;
|
|
|
|
await InitWellOperations(idWell, token);
|
|
|
|
var wellContactRequest = new WellContactRequest
|
|
{
|
|
IdsWells = new[] { idWell },
|
|
};
|
|
|
|
var contacts = await wellContactService.GetAllAsync(wellContactRequest, token);
|
|
|
|
var sectionReports = await GetSectionReportsAsync(idWell, token);
|
|
var drillerReports = await GetDrillerReportsAsync(idWell, token);
|
|
|
|
var firstFactOperation = factWellOperations.MinByOrDefault(x => x.DateStart);
|
|
var lastPlanOperation = planWellOperations.MaxByOrDefault(x => x.DateStart);
|
|
|
|
var planTrajectories = await trajectoryPlanRepository.GetAsync(idWell, token);
|
|
var factTrajectories = await trajectoryFactRepository.GetAsync(idWell, token);
|
|
|
|
var factOperationsWithoutNpt = factWellOperations.Where(o => !WellOperationCategory.NonProductiveTimeSubIds.Contains(o.IdCategory));
|
|
|
|
return new WellReportDto
|
|
{
|
|
Well = well,
|
|
DateFrom = firstFactOperation?.DateStart,
|
|
DateTo = lastPlanOperation?.DateStart.AddHours(lastPlanOperation.DurationHours),
|
|
Days = new PlanFactDto<double?>
|
|
{
|
|
Plan = planWellOperations.Sum(x => x.DurationHours) / 24,
|
|
Fact = factWellOperations.Sum(x => x.DurationHours) / 24
|
|
},
|
|
WellBoreDepth = new PlanFactDto<double?>
|
|
{
|
|
Plan = planWellOperations.MaxOrDefault(x => x.DepthEnd),
|
|
Fact = factWellOperations.MaxOrDefault(x => x.DepthEnd)
|
|
},
|
|
VerticalDepth = new PlanFactDto<double?>
|
|
{
|
|
Plan = planTrajectories.Max(x => x.VerticalDepth),
|
|
Fact = factTrajectories.Max(x => x.VerticalDepth)
|
|
},
|
|
WithoutNtpDays = factOperationsWithoutNpt.Sum(x => x.DurationHours) / 24,
|
|
Contacts = contacts,
|
|
SectionReports = sectionReports,
|
|
DrillerReports = drillerReports,
|
|
};
|
|
}
|
|
|
|
private async Task InitWellOperations(int idWell, CancellationToken token)
|
|
{
|
|
var request = new WellOperationRequest(new[] { idWell })
|
|
{
|
|
OperationType = WellOperation.IdOperationTypeFact
|
|
};
|
|
|
|
factWellOperations = await wellOperationService.GetAsync(request, token);
|
|
|
|
request.OperationType = WellOperation.IdOperationTypePlan;
|
|
|
|
planWellOperations = await wellOperationService.GetAsync(request, token);
|
|
}
|
|
|
|
private async Task<IEnumerable<SectionReportDto>> GetSectionReportsAsync(int idWell, CancellationToken token)
|
|
{
|
|
var factWellOperationsBySection = factWellOperations.GroupBy(x => x.IdWellSectionType)
|
|
.ToDictionary(x => x.Key, x => x.AsEnumerable());
|
|
|
|
var processMapPlanRequest = new ProcessMapPlanBaseRequestWithWell(idWell);
|
|
|
|
var processMapPlanRotorBySection =
|
|
(await processMapPlanRotorRepository.GetCurrent(processMapPlanRequest, token))
|
|
.GroupBy(x => x.IdWellSectionType)
|
|
.ToDictionary(x => x.Key, x => x.AsEnumerable());
|
|
|
|
var dataSaubStatRequest = new DataSaubStatRequest();
|
|
|
|
var processMapReportBySection =
|
|
(await processMapReportDrillingService.GetAsync(idWell, dataSaubStatRequest, token))
|
|
.GroupBy(x => x.IdWellSectionType)
|
|
.ToDictionary(x => x.Key, x => x.AsEnumerable());
|
|
|
|
var idsSection = factWellOperationsBySection.Keys
|
|
.Concat(processMapPlanRotorBySection.Keys)
|
|
.Concat(processMapReportBySection.Keys)
|
|
.Distinct();
|
|
|
|
var sectionReports = new List<SectionReportDto>();
|
|
|
|
foreach (var idSection in idsSection)
|
|
{
|
|
var sectionReport = new SectionReportDto
|
|
{
|
|
IdSection = idSection,
|
|
OperatingMode = new PlanFactDto<OperatingModeDto>()
|
|
};
|
|
|
|
if (factWellOperationsBySection.TryGetValue(idSection, out var factOperations))
|
|
{
|
|
var subsystemRequest = new SubsystemRequest
|
|
{
|
|
IdWell = idWell,
|
|
GeDepth = factOperations.Min(y => y.DepthStart),
|
|
LeDepth = factOperations.Max(y => y.DepthEnd)
|
|
};
|
|
|
|
sectionReport.SubsystemsStat = await subsystemService.GetStatAsync(subsystemRequest, token);
|
|
sectionReport.OperatingMode.Fact = new OperatingModeDto
|
|
{
|
|
DepthStart = factOperations.Min(w => w.DepthStart),
|
|
DepthEnd = factOperations.Max(w => w.DepthEnd)
|
|
};
|
|
}
|
|
|
|
if (processMapPlanRotorBySection.TryGetValue(idSection, out var processMapPlanRotor))
|
|
sectionReport.OperatingMode.Plan = new OperatingModeDto
|
|
{
|
|
DepthStart = processMapPlanRotor.Min(p => p.DepthStart),
|
|
DepthEnd = processMapPlanRotor.Max(p => p.DepthEnd),
|
|
RopMin = processMapPlanRotor.Min(p => p.RopMax),
|
|
RopMax = processMapPlanRotor.Max(p => p.RopMax),
|
|
RopAvg = processMapPlanRotor.Average(p => p.RopMax),
|
|
WeightOnBitMin = processMapPlanRotor.Min(p => p.WeightOnBit),
|
|
WeightOnBitMax = processMapPlanRotor.Max(p => p.WeightOnBitMax),
|
|
WeightOnBitAvg = processMapPlanRotor.Average(p => p.WeightOnBit),
|
|
DriveTorqueMin = processMapPlanRotor.Min(p => p.TopDriveTorque),
|
|
DriveTorqueMax = processMapPlanRotor.Max(p => p.TopDriveTorqueMax),
|
|
DriveTorqueAvg = processMapPlanRotor.Average(p => p.TopDriveTorque),
|
|
DifferentialPressureMin = processMapPlanRotor.Min(p => p.DifferentialPressure),
|
|
DifferentialPressureMax = processMapPlanRotor.Max(p => p.DifferentialPressureMax),
|
|
DifferentialPressureAvg = processMapPlanRotor.Average(p => p.DifferentialPressure),
|
|
FrowRateMin = processMapPlanRotor.Min(p => p.FlowRate),
|
|
FrowRateMax = processMapPlanRotor.Max(p => p.FlowRateMax)
|
|
};
|
|
|
|
if (processMapReportBySection.TryGetValue(idSection, out var processMapReport))
|
|
sectionReport.DrillingBySetpoints = new DrillingBySetpointsDto
|
|
{
|
|
MetersByPressure = processMapReport.Sum(x => x.DeltaDepth * x.PressureDiff.SetpointUsage / 100),
|
|
MetersByLoad = processMapReport.Sum(x => x.DeltaDepth * x.AxialLoad.SetpointUsage / 100),
|
|
MetersByTorque = processMapReport.Sum(x => x.DeltaDepth * x.TopDriveTorque.SetpointUsage / 100),
|
|
MetersBySpeed = processMapReport.Sum(x => x.DeltaDepth * x.SpeedLimit.SetpointUsage / 100)
|
|
};
|
|
|
|
sectionReports.Add(sectionReport);
|
|
}
|
|
|
|
return sectionReports;
|
|
}
|
|
|
|
private async Task<IEnumerable<DrillerReportDto>> GetDrillerReportsAsync(int idWell, CancellationToken token)
|
|
{
|
|
var schedules = await scheduleRepository.GetByIdWellAsync(idWell, token);
|
|
|
|
var result = new List<DrillerReportDto>();
|
|
|
|
foreach (var schedule in schedules)
|
|
{
|
|
var subsystemRequest = new SubsystemRequest
|
|
{
|
|
IdWell = idWell,
|
|
IdDriller = schedule.IdDriller
|
|
};
|
|
|
|
var drillerReport = new DrillerReportDto
|
|
{
|
|
Shedule = schedule,
|
|
SubsystemsStat = await subsystemService.GetStatAsync(subsystemRequest, token)
|
|
};
|
|
|
|
result.Add(drillerReport);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
} |