using AsbCloudApp.Data; using AsbCloudApp.Data.DataSaubStat; using AsbCloudApp.Data.DetectedOperation; using AsbCloudApp.Data.SAUB; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services; public class DataSaubStatDrillingQualityService : IDataSaubStatService { private IDataSaubStatRepository dataSaubStatRepository; private ITelemetryDataCache telemetryDataCache; private ITelemetryDataSaubService dataSaubService; private IDetectedOperationRepository detectedOperationRepository; public DataSaubStatDrillingQualityService( IDataSaubStatRepository dataSaubStatRepository, ITelemetryDataCache telemetryDataCache, ITelemetryDataSaubService dataSaubService, IDetectedOperationRepository detectedOperationRepository) { this.dataSaubStatRepository = dataSaubStatRepository; this.telemetryDataCache = telemetryDataCache; this.dataSaubService = dataSaubService; this.detectedOperationRepository = detectedOperationRepository; } public async Task CreateStatAsync(int lastDaysFilter, Action onProgressCallback, CancellationToken token) { //to do var cacheRequest = new TelemetryDataRequest() { GeDate = DateTime.UtcNow.AddDays(-5000) }; var idTelemetries = telemetryDataCache.GetIds(cacheRequest).ToArray(); if (!idTelemetries.Any()) return; var stats = new List(); //await dataSaubStatRepository.GetLastsAsync(idTelemetries, token); //for (var i = 0; i < idTelemetries.Length; i++) //{ // var idTelemetry = idTelemetries[i]; // var lastDate = stats.FirstOrDefault(s => s.IdTelemetry == idTelemetry)?.DateEnd.ToUniversalTime() ?? DateTimeOffset.UnixEpoch; // var statsCount = await CreateStatForTelemetryFromDate(idTelemetry, lastDate, token); // if(onProgressCallback != null) // onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 1d * i / idTelemetries.Length); //} } private async Task CreateStatForTelemetryFromDate( int idTelemetry, DateTimeOffset geDate, CancellationToken token) { var leDate = DateTimeOffset.UtcNow; var dataSaub = await dataSaubService.Get([idTelemetry], true, geDate, leDate, 100_000, token); if (!dataSaub.Any()) return 0; if (dataSaub is not TelemetryDataSaubDto[] dataSaubArray) dataSaubArray = dataSaub.ToArray(); var dataSaubStats = CreateDataSaubStat(dataSaubArray); return 0; //return await dataSaubStatRepository.InsertRangeAsync(dataSaubStats, token); } private static IEnumerable CreateDataSaubStat2(int idFeedRegulator, TelemetryDataSaubDto[] dataSaub) { var result = new List(); var indexStart = 0; var indexEnd = 0; while (indexEnd < dataSaub.Count()) { indexStart = Array.FindIndex(dataSaub, indexEnd, t => t.IdFeedRegulator == idFeedRegulator); if (indexStart < 0) break; indexEnd = Array.FindIndex(dataSaub, indexStart, t => t.IdFeedRegulator != idFeedRegulator); if (indexEnd < 0) indexEnd = dataSaub.Length - 1; if (indexEnd == indexStart) { continue; } var length = indexEnd - indexStart + 1; var subset = dataSaub.AsSpan(indexStart, length); if (length <= 2 || (subset[^1].WellDepth - subset[0].WellDepth) < 0.001) continue; // мелкие выборки не учитываем. var stats = CalcStats(subset); result.Add(stats); } return result; } private static Dictionary> CreateDataSaubStat(TelemetryDataSaubDto[] dataSaub) { var dict = new Dictionary>() { { 1, new List() }, { 2, new List() }, { 3, new List() }, { 4, new List() }, }; foreach (var item in dict) { var data = CreateDataSaubStat2(item.Key, dataSaub); item.Value.AddRange(data); } return dict; } private static DataSaubStatDrillingQualityDto CalcStats(Span dataSaub) { var depthDrillingQuality = CalcAggregate(dataSaub); var result = new DataSaubStatDrillingQualityDto(); result.DepthStart = dataSaub[0].WellDepth; result.DepthEnd = dataSaub[^1].WellDepth; result.DateStart = dataSaub[0].DateTime; result.DateEnd = dataSaub[^1].DateTime; result.DepthDrillingQuality = depthDrillingQuality; return result; } private static DataSaubStatDto CalcStat(DetectedOperationDto operation, Span span) { var aggregatedValues = CalcAggregate(span); var dateStart = span[0].DateTime; var dateEnd = span[^1].DateTime; var depthStart = span[0].WellDepth; var depthEnd = span[^1].WellDepth; var speed = ((depthEnd - depthStart) / (dateEnd - dateStart).TotalHours); var processMapDrillingCacheItem = new DataSaubStatDto { DateStart = dateStart, DateEnd = dateEnd, DepthStart = depthStart, DepthEnd = depthEnd, Speed = speed, BlockSpeedSp = span[0].BlockSpeedSp, Pressure = aggregatedValues.Pressure, PressureIdle = span[0].PressureIdle, PressureSp = span[0].PressureSp, AxialLoad = aggregatedValues.AxialLoad, AxialLoadSp = span[0].AxialLoadSp, AxialLoadLimitMax = span[0].AxialLoadLimitMax, RotorTorque = aggregatedValues.RotorTorque, RotorTorqueSp = span[0].RotorTorqueSp, RotorTorqueLimitMax = span[0].RotorTorqueLimitMax, IdFeedRegulator = span[0].IdFeedRegulator, RotorSpeed = aggregatedValues.RotorSpeed, IdCategory = operation.IdCategory, EnabledSubsystems = operation.EnabledSubsystems, HasOscillation = operation.EnabledSubsystems.IsAutoOscillation, IdTelemetry = operation.IdTelemetry, Flow = aggregatedValues.Flow }; return processMapDrillingCacheItem; } private static ( double Pressure, double AxialLoad, double RotorTorque, double RotorSpeed, double Flow ) CalcAggregate(Span span) { var sumPressure = 0.0; var sumAxialLoad = 0.0; var sumRotorTorque = 0.0; var sumRotorSpeed = 0.0; var flow = span[0].Flow ?? 0.0; var diffDepthTotal = span[^1].WellDepth - span[0].WellDepth; for (var i = 0; i < span.Length - 1; i++) { var diffDepth = span[i + 1].WellDepth - span[i].WellDepth; sumPressure += diffDepth * span[i].Pressure; sumAxialLoad += diffDepth * span[i].AxialLoad; sumRotorTorque += diffDepth * span[i].RotorTorque; sumRotorSpeed += diffDepth * span[i].RotorSpeed; flow = span[i + 1].Flow > flow ? span[i + 1].Flow ?? 0.0 : flow; } return ( Pressure: sumPressure / diffDepthTotal, AxialLoad: sumAxialLoad / diffDepthTotal, RotorTorque: sumRotorTorque / diffDepthTotal, RotorSpeed: sumRotorSpeed / diffDepthTotal, Flow: flow ); } private static bool IsNewCacheItem(TelemetryDataSaubDto previous, TelemetryDataSaubDto current) { return !(current.Mode == previous.Mode) || !(current.WellDepth >= previous.WellDepth) || !(current.BlockSpeedSp == previous.BlockSpeedSp) || !(current.PressureIdle == previous.PressureIdle) || !(current.PressureSp == previous.PressureSp) || !(current.AxialLoadSp == previous.AxialLoadSp) || !(current.AxialLoadLimitMax == previous.AxialLoadLimitMax) || !(current.HookWeightIdle == previous.HookWeightIdle) || !(current.RotorTorqueIdle == previous.RotorTorqueIdle) || !(current.RotorTorqueSp == previous.RotorTorqueSp) || !(current.RotorTorqueLimitMax == previous.RotorTorqueLimitMax) || !(current.IdFeedRegulator == previous.IdFeedRegulator); } }