using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services { #nullable enable public class DrillParamsService : CrudServiceBase, IDrillParamsService { private readonly IAsbCloudDbContext db; private readonly ITelemetryService telemetryService; public DrillParamsService(IAsbCloudDbContext context, ITelemetryService telemetryService) : base(context) { this.db = context; this.telemetryService = telemetryService; } public async Task GetDefaultDrillParamsAsync(int idWell, double startDepth, double endDepth, CancellationToken token = default) { var idTelemetry = telemetryService.GetOrDefaultIdTelemetryByIdWell(idWell); if (idTelemetry is null) return null; var drillParamsDto = await (from telemetry in db.TelemetryDataSaub where telemetry.IdTelemetry == idTelemetry && telemetry.WellDepth >= startDepth && telemetry.WellDepth <= endDepth group telemetry by telemetry.IdTelemetry into g select new DrillParamsDto() { IdWell = idWell, Depth = new MinMaxDto { Min = endDepth, Max = startDepth }, IdWellSectionType = 0, AxialLoad = new MinMaxExtendedViewDto { Min = g.Min(t => t.AxialLoad) ?? double.NaN, Avg = g.Average(t => t.AxialLoad) ?? double.NaN, Max = g.Max(t => t.AxialLoad) ?? double.NaN }, Pressure = new MinMaxExtendedViewDto { Min = g.Min(t => t.Pressure) ?? double.NaN, Avg = g.Average(t => t.Pressure) ?? double.NaN, Max = g.Max(t => t.Pressure) ?? double.NaN }, RotorTorque = new MinMaxExtendedViewDto { Min = g.Min(t => t.RotorTorque) ?? double.NaN, Avg = g.Average(t => t.RotorTorque) ?? double.NaN, Max = g.Max(t => t.RotorTorque) ?? double.NaN }, RotorSpeed = new MinMaxExtendedViewDto { Min = g.Min(t => t.RotorSpeed) ?? double.NaN, Avg = g.Average(t => t.RotorSpeed) ?? double.NaN, Max = g.Max(t => t.RotorSpeed) ?? double.NaN }, Flow = new MinMaxExtendedViewDto { Min = g.Min(t => t.Flow) ?? double.NaN, Avg = g.Min(t => t.Flow) ?? double.NaN, Max = g.Min(t => t.Flow) ?? double.NaN } }) .AsNoTracking() .DefaultIfEmpty() .OrderBy(t => t.AxialLoad.Min) .FirstOrDefaultAsync(token) .ConfigureAwait(false); return drillParamsDto; } public async Task> GetAllAsync(int idWell, CancellationToken token = default) { var entities = await db.DrillParams .Where(p => p.IdWell == idWell) .OrderBy(p=> p.Id) .AsNoTracking() .ToArrayAsync(token) .ConfigureAwait(false); var dtos = entities.Select(p => { var dto = new DrillParamsDto { IdWell = p.IdWell, Id = p.Id, IdWellSectionType = p.IdWellSectionType, Depth = new MinMaxDto { Max = p.PressureMax, Min = p.PressureMin }, Pressure = MakeMinMaxExtended(p.PressureAvg, p.PressureMax, p.PressureMin), AxialLoad = MakeMinMaxExtended(p.AxialLoadAvg, p.AxialLoadMax, p.AxialLoadMin), Flow = MakeMinMaxExtended(p.FlowAvg, p.FlowMax, p.FlowMin), RotorSpeed = MakeMinMaxExtended(p.RotorSpeedAvg, p.RotorSpeedMax, p.RotorSpeedMin), RotorTorque = MakeMinMaxExtended(p.RotorTorqueAvg, p.RotorTorqueMax, p.RotorTorqueMin) }; return dto; }); return dtos; } public async Task> GetCompositeAllAsync(int idWell, CancellationToken token = default) { var allDrillParamsQuery = db.WellComposites .Where(c => c.IdWell == idWell) .Join(db.DrillParams, c => c.IdWellSrc, p => p.IdWell, (c, p) => p); var allDrillParams = await allDrillParamsQuery .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); var compositeWellDrillParamsQuery = db.WellComposites .Where(c => c.IdWell == idWell) .Join(db.DrillParams, c => new { IdWell = c.IdWellSrc, IdSection = c.IdWellSectionType }, p => new { IdWell = p.IdWell, IdSection = p.IdWellSectionType }, (c, p) => p); var compositeWellDrillParams = await compositeWellDrillParamsQuery .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); var result = compositeWellDrillParams.Select(x => Convert(x, allDrillParams)); return result; } public async Task InsertAsync(int idWell, DrillParamsDto dto, CancellationToken token = default) { dto.IdWell = idWell; var result = await base.InsertAsync(dto, token).ConfigureAwait(false); return result; } public async Task InsertRangeAsync(int idWell, IEnumerable dtos, CancellationToken token = default) { foreach (var dto in dtos) dto.IdWell = idWell; var result = await base.InsertRangeAsync(dtos, token).ConfigureAwait(false); return result; } public async Task SaveAsync(int idWell, IEnumerable dtos, CancellationToken token = default) { db.DrillParams.RemoveRange(db.DrillParams.Where(d => d.IdWell == idWell)); foreach (var dto in dtos) dto.IdWell = idWell; var result = await base.InsertRangeAsync(dtos, token).ConfigureAwait(false); return result; } public async Task UpdateAsync(int idWell, int dtoId, DrillParamsDto dto, CancellationToken token = default) { dto.IdWell = idWell; var result = await base.UpdateAsync(dto, token).ConfigureAwait(false); return result; } private static DrillParamsDto Convert(DrillParams entity, IEnumerable drillParams) { return new DrillParamsDto { Id = entity.Id, IdWellSectionType = entity.IdWellSectionType, AxialLoad = MakeMinMaxExtended(entity.AxialLoadAvg, entity.AxialLoadMax, entity.AxialLoadMin, drillParams.Select(x => (x.AxialLoadMin, x.AxialLoadMax))), Depth = new MinMaxDto { Min = entity.DepthEnd, Max = entity.DepthStart }, Flow = MakeMinMaxExtended(entity.FlowAvg, entity.FlowMax, entity.FlowMin, drillParams.Select(x => (x.FlowMin, x.FlowMax))), IdWell = entity.IdWell, Pressure = MakeMinMaxExtended(entity.PressureAvg, entity.PressureMax, entity.PressureMin, drillParams.Select(x => (x.PressureMin, x.PressureMax))), RotorSpeed = MakeMinMaxExtended(entity.RotorSpeedAvg, entity.RotorSpeedMax, entity.RotorSpeedMin, drillParams.Select(x => (x.RotorSpeedMin, x.RotorSpeedMax))), RotorTorque = MakeMinMaxExtended(entity.RotorTorqueAvg, entity.RotorTorqueMax, entity.RotorTorqueMin, drillParams.Select(x => (x.RotorTorqueMin, x.RotorTorqueMax))) }; } private static MinMaxExtendedViewDto MakeMinMaxExtended(double avg, double max, double min, IEnumerable<(double min, double max)>? allDrillParams = null) => new MinMaxExtendedViewDto { Avg = avg, Max = max, Min = min, IsMax = (! allDrillParams?.Any (mx => mx.max > max)) ?? false, IsMin = (! allDrillParams?.Any (mn => mn.min < min)) ?? false }; } #nullable disable }