using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services { public class WellSectionService : IWellSectionService { private readonly IAsbCloudDbContext db; public WellSectionService(IAsbCloudDbContext db) { this.db = db; } public async Task> GetSectionsByWellIdAsync(int idWell, CancellationToken token = default) { var wellOperations = await (from w in db.WellOperations where w.IdWell == idWell select w) .Include(w => w.WellSectionType) .ToListAsync(token) .ConfigureAwait(false); if (!wellOperations.Any()) return null; var wellOperationsGroupedBySections = wellOperations .GroupBy(op => op.IdWellSectionType).ToList(); var wellOperationsClone = wellOperations.Select(o => o.ShallowCopy()).ToList(); wellOperationsClone.ForEach(op => { op.IdWellSectionType = 1; op.WellSectionType = new WellSectionType { Caption = "Обобщенное по скважине" }; }); var groupedWellOperationsClone = wellOperationsClone.GroupBy(o => o.IdWell); wellOperationsGroupedBySections.Add(groupedWellOperationsClone.First()); var depthsPlanList = GetWellDepthStats(wellOperationsGroupedBySections, 0).ToList(); var depthsFactList = GetWellDepthStats(wellOperationsGroupedBySections, 1).ToList(); var durationsPlanList = GetWellDurationStats(wellOperationsGroupedBySections, 0).ToList(); var durationsFactList = GetWellDurationStats(wellOperationsGroupedBySections, 1).ToList(); var mechSpeedsPlanList = GetWellStats(wellOperationsGroupedBySections, 1001, 0).ToList(); var mechSpeedsFactList = GetWellStats(wellOperationsGroupedBySections, 1001, 1).ToList(); var bhaUpSpeedPlanList = GetWellStats(wellOperationsGroupedBySections, 1046, 0).ToList(); var bhaUpSpeedFactList = GetWellStats(wellOperationsGroupedBySections, 1046, 1).ToList(); var bhaDownSpeedPlanList = GetWellStats(wellOperationsGroupedBySections, 1047, 0).ToList(); var bhaDownSpeedFactList = GetWellStats(wellOperationsGroupedBySections, 1047, 1).ToList(); var casingDownPlanList = GetWellStats(wellOperationsGroupedBySections, 1048, 0).ToList(); var casingDownFactList = GetWellStats(wellOperationsGroupedBySections, 1048, 1).ToList(); var routeSpeedsPlan = GetWellRouteSpeedStats(wellOperationsGroupedBySections, 0).ToList(); var routeSpeedsFact = GetWellRouteSpeedStats(wellOperationsGroupedBySections, 1).ToList(); var dtos = new List(); for (int i = 0; i < wellOperationsGroupedBySections.Count; i++) { var dto = new WellSectionDto { SectionType = wellOperationsGroupedBySections[i] .FirstOrDefault().WellSectionType.Caption, WellDepthPlan = depthsPlanList[i], WellDepthFact = depthsFactList[i], DurationPlan = durationsPlanList[i], DurationFact = durationsFactList[i], MechSpeedPlan = mechSpeedsPlanList[i], MechSpeedFact = mechSpeedsFactList[i], BhaUpSpeedPlan = bhaUpSpeedPlanList[i], BhaUpSpeedFact = bhaUpSpeedFactList[i], BhaDownSpeedPlan = bhaDownSpeedPlanList[i], BhaDownSpeedFact = bhaDownSpeedFactList[i], CasingDownSpeedPlan = casingDownPlanList[i], CasingDownSpeedFact = casingDownFactList[i], RouteSpeedPlan = routeSpeedsPlan[i], RouteSpeedFact = routeSpeedsFact[i] }; dtos.Add(dto); } return dtos.OrderBy(d => d.WellDepthPlan); } private static IEnumerable GetWellDepthStats( IEnumerable> groupedOperations, int type) { return groupedOperations.Select(group => group.Where(o => o.IdType == type) .DefaultIfEmpty().Max(w => w?.WellDepth ?? 0.0)); } private static IEnumerable GetWellDurationStats( IEnumerable> groupedOperations, int type) { var durationsPlanFactsBase = groupedOperations.Select(group => new { DurationMax = group.Where(o => o.IdType == type).DefaultIfEmpty() .Max(op => op?.StartDate + TimeSpan.FromHours(op?.DurationHours ?? 0)) ?? default, DurationMin = group.Where(o => o.IdType == type).DefaultIfEmpty() .Min(op => op?.StartDate) ?? default }); return durationsPlanFactsBase.Select(o => (o.DurationMax - o.DurationMin).TotalHours); } private static IEnumerable GetWellStats( IEnumerable> groupedOperations, int idCategory, int type) { var mechSpeedBase = groupedOperations.Select(g => ( DepthDifferenceSum: g.Where(o => o.IdType == type && o.IdCategory == idCategory) .Select((el, i) => i > 0 ? el.WellDepth - g.ElementAt(i - 1).WellDepth : 0).Sum(), DurationDifferenceSum: g.Where(o => o.IdType == type && o.IdCategory == idCategory) .Select(el => el.DurationHours).Sum() )); return CalculateResult(mechSpeedBase); } private static IEnumerable GetWellRouteSpeedStats( IEnumerable> groupedOperations, int type) { var bhaRaiseDecreaseCollection = new List<(WellOperation FirstBhaPositionDecrease, WellOperation LastBhaPositionIncrease)>(); foreach (var group in groupedOperations) { var firstBhaPositionDecrease = group.Any(o => o.IdCategory == 1046 && o.IdType == type) ? group.First(o => o.IdCategory == 1046 && o.IdType == type) : null; var lastBhaPositionIncrease = group.Any(o => o.IdCategory == 1047 && o.IdType == type) ? group.Last(o => o.IdCategory == 1047 && o.IdType == type) : null; bhaRaiseDecreaseCollection.Add((firstBhaPositionDecrease, lastBhaPositionIncrease)); } var routeSpeedsBase = bhaRaiseDecreaseCollection.Select(el => ( RouteDepth: (el.LastBhaPositionIncrease?.WellDepth - el.FirstBhaPositionDecrease?.WellDepth) ?? 0, RouteDuration: (el.LastBhaPositionIncrease?.StartDate + TimeSpan.FromHours(el.LastBhaPositionIncrease?.DurationHours ?? 0) - el.FirstBhaPositionDecrease?.StartDate)?.TotalHours ?? 0 )); return CalculateResult(routeSpeedsBase); } private static IEnumerable CalculateResult(IEnumerable<(double, double)> rawData) { return rawData.Select(el => (el.Item1 / el.Item2) is double.NaN ? 0 : (el.Item1 / el.Item2) ); } } }