using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMap; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudApp.Services.Subsystems; using AsbCloudDb.Model; using AsbCloudInfrastructure.Background; using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services { #nullable enable public class WellInfoService { class WellMapInfoWithComanies : WellMapInfoDto { public IEnumerable IdsCompanies { get; set; } = null!; } private const string workId = "Well statistics update"; private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30); private static IEnumerable WellMapInfo = Enumerable.Empty(); public static WorkPeriodic MakeWork() { var workPeriodic = new WorkPeriodic(workId, WorkAction, workPeriod) { Timeout = TimeSpan.FromMinutes(30) }; return workPeriodic; } private static async Task WorkAction(string workName, IServiceProvider serviceProvider, CancellationToken token) { var db = serviceProvider.GetRequiredService(); var wellService = serviceProvider.GetRequiredService(); var operationsStatService = serviceProvider.GetRequiredService(); var processMapRepository = serviceProvider.GetRequiredService(); var subsystemOperationTimeService = serviceProvider.GetRequiredService(); var activeWells = await wellService.GetAsync(new() {IdState = 1}, token); IEnumerable activeWellsIds = activeWells .Select(w => w.Id); var idTelemetries = activeWells .Where(w => w.IdTelemetry != null) .Select(t => t.IdTelemetry); var lastTelemetryInfo = await db.TelemetryDataSaub .Where(t => idTelemetries.Contains(t.IdTelemetry)) .Select(t => new { t.IdTelemetry, t.WellDepth, t.DateTime, }) .GroupBy(t => t.IdTelemetry) .Select(g => g.OrderByDescending(t => t.DateTime) .First() ) .AsNoTracking() .ToArrayAsync(token); var processMapRequests = activeWellsIds.Select(id => new ProcessMapRequest { IdWell = id }); var processMaps = await processMapRepository.GetProcessMapAsync(processMapRequests, token); var wellDepthByProcessMap = processMaps .GroupBy(p => p.IdWell) .Select(g => new { Id = g.Key, DepthEnd = g.Max(p => p.DepthEnd) }); var operationsStat = await operationsStatService.GetWellsStatAsync(activeWellsIds, token); var subsystemStat = await subsystemOperationTimeService.GetStatByActiveWells(activeWellsIds, token); WellMapInfo = activeWells.Select(well => { var wellMapInfo = well.Adapt(); var wellLastTelemetryInfo = lastTelemetryInfo.FirstOrDefault(t => t.IdTelemetry == well.IdTelemetry); var wellOperationsStat = operationsStat.FirstOrDefault(s => s.Id == well.Id); var wellLastFactSection = wellOperationsStat?.Sections.LastOrDefault(s => s.Fact is not null); var wellSubsystemStat = subsystemStat.FirstOrDefault(s => s.Well.Id == well.Id); double currentDepth = wellLastTelemetryInfo?.WellDepth ?? wellLastFactSection?.Fact?.WellDepthEnd ?? 0d; var wellProcessMaps = processMaps .Where(p => p.IdWell == well.Id) .OrderBy(p => p.DepthEnd); int? idSection = wellLastFactSection?.Id; ProcessMapDto? welllProcessMap; if (idSection is not null) { welllProcessMap = wellProcessMaps.FirstOrDefault(p => p.IdWellSectionType == idSection); } else { welllProcessMap = wellProcessMaps.FirstOrDefault(p => p.DepthStart <= currentDepth && p.DepthEnd >= currentDepth); idSection ??= welllProcessMap?.IdWellSectionType; } wellMapInfo.LastTelemetryDate = wellLastTelemetryInfo?.DateTime.ToRemoteDateTime(5) ?? new DateTime(); wellMapInfo.WellDepth = new() { Plan = wellDepthByProcessMap.FirstOrDefault(p => p.Id == well.Id)?.DepthEnd, Fact = currentDepth, }; wellMapInfo.ROP = new() { Plan = welllProcessMap?.RopPlan, Fact = wellOperationsStat?.Total.Fact?.Rop, }; wellMapInfo.RaceSpeed = new() { Plan = wellOperationsStat?.Total.Plan?.RouteSpeed, Fact = wellOperationsStat?.Total.Fact?.RouteSpeed, }; wellMapInfo.SaubUsage = wellSubsystemStat?.SubsystemAKB?.KUsage ?? 0d; wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d; wellMapInfo.TvdLagPercent = wellOperationsStat?.TvdLagDays ?? 0d; wellMapInfo.IdsCompanies = well.Companies.Select(c => c.Id); return wellMapInfo; }).ToArray(); } public static IEnumerable Where(Func predicate) => WellMapInfo.Where(predicate); public static WellMapInfoDto? FirstOrDefault(Func predicate) => WellMapInfo.FirstOrDefault(predicate); } #nullable disable }