using System; using System.Linq; using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.Cache; using AsbCloudDb.Model; using System.Collections.Generic; namespace AsbCloudInfrastructure.Services { public class AnalyticsService : IAnalyticsService { private readonly IAsbCloudDbContext db; private readonly ITelemetryService telemetryService; private readonly CacheTable cacheOperations; private readonly OperationDetectorService operationDetectorService; private readonly IEnumerable operations; public AnalyticsService(IAsbCloudDbContext db, ITelemetryService telemetryService, CacheDb cacheDb) { this.db = db; this.telemetryService = telemetryService; cacheOperations = cacheDb.GetCachedTable((AsbCloudDbContext)db); operations = cacheOperations.Select(c => true); operationDetectorService = new OperationDetectorService(operations); } public IEnumerable GetWellDepthToDay(int wellId) { var telemetry = telemetryService.GetTelemetryByWellId(wellId); if (telemetry is null) return null; var depthToTimeData = (from d in db.DataSaubBases where d.IdTelemetry == telemetry.Id select new { d.Id, d.WellDepth, d.BitDepth, d.Date }); var m = (int)Math.Round(1d * depthToTimeData.Count() / 2048); if (m > 1) depthToTimeData = depthToTimeData.Where(d => d.Id % m == 0); return depthToTimeData.Select(d => new WellDepthToDayDto { WellDepth = d.WellDepth ?? 0.0, BitDepth = d.BitDepth ?? 0.0, Date = d.Date }).ToList(); } public IEnumerable GetWellDepthToInterval(int wellId, int intervalHoursTimestamp, int workBeginTimestamp) { intervalHoursTimestamp = intervalHoursTimestamp == 0 ? 86400 : intervalHoursTimestamp; var intervalTime = new TimeSpan(0, 0, intervalHoursTimestamp); var workDayBeginTime = new TimeSpan(0, 0, workBeginTimestamp); var telemetry = telemetryService.GetTelemetryByWellId(wellId); if (telemetry is null) return null; var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId(telemetry.Id); var drillingPeriodsInfo = db.GetDepthToInterval(telemetry.Id, (int)intervalTime.TotalSeconds, (int)workDayBeginTime.TotalSeconds, timezoneOffset); var wellDepthToIntervalData = drillingPeriodsInfo.Select(d => new WellDepthToIntervalDto { IntervalStartDate = d.BeginPeriodDate, IntervalDepthProgress = (d.MaxDepth - d.MinDepth) ?? 0.0 / intervalHoursTimestamp }).OrderBy(d => d.IntervalStartDate).ToList(); return wellDepthToIntervalData; } public IEnumerable GetOperationsSummary(int wellId, DateTime begin = default, DateTime end = default) { return new List { new OperationPercentageDto { ProcessName = "Роторное бурение", Percentage = 19.7 }, new OperationPercentageDto { ProcessName = "Подъем с проработкой", Percentage = 6.2 }, new OperationPercentageDto { ProcessName = "Спуск с проработкой", Percentage = 9.4 }, new OperationPercentageDto { ProcessName = "Подъем с промывкой", Percentage = 18.4 }, new OperationPercentageDto { ProcessName = "Неподвижное состояние", Percentage = 12.1 }, new OperationPercentageDto { ProcessName = "Вращение без циркуляции", Percentage = 7.4 }, new OperationPercentageDto { ProcessName = "Спуск в скважину", Percentage = 16.7 }, new OperationPercentageDto { ProcessName = "На поверхности", Percentage = 10.1 } }; } public IEnumerable GetOperationsToTime(int wellId, DateTime begin = default, DateTime end = default) { return new List { new OperationInfoDto { IntervalBegin = new DateTime(2021, 06, 01, 08, 00, 00), IntervalEnd = new DateTime(2021, 06, 02, 08, 00, 00), OperationData = new List { new OperationDetailsDto { OperationName = "Роторное бурение", OperationStartTime = new DateTime(2021, 06, 01, 10, 00, 00), DurationHours = 1.2 }, new OperationDetailsDto { OperationName = "Подъем с проработкой", OperationStartTime = new DateTime(2021, 06, 01, 11, 00, 00), DurationHours = 3.2 }, new OperationDetailsDto { OperationName = "Роторное бурение", OperationStartTime = new DateTime(2021, 06, 01, 12, 00, 00), DurationHours = 1.5 }, new OperationDetailsDto { OperationName = "Неподвижное состояние", OperationStartTime = new DateTime(2021, 06, 01, 13, 00, 00), DurationHours = 0.2 }, new OperationDetailsDto { OperationName = "Роторное бурение", OperationStartTime = new DateTime(2021, 06, 01, 14, 00, 00), DurationHours = 3.2 } } }, new OperationInfoDto { IntervalBegin = new DateTime(2021, 06, 02, 08, 00, 00), IntervalEnd = new DateTime(2021, 06, 03, 08, 00, 00), OperationData = new List { new OperationDetailsDto { OperationName = "На поверхности", OperationStartTime = new DateTime(2021, 06, 13, 10, 01, 00), DurationHours = 2.2 }, new OperationDetailsDto { OperationName = "Спуск в скважину", OperationStartTime = new DateTime(2021, 06, 13, 11, 10, 00), DurationHours = 0.4 }, new OperationDetailsDto { OperationName = "На поверхности", OperationStartTime = new DateTime(2021, 06, 13, 12, 20, 00), DurationHours = 2.5 }, new OperationDetailsDto { OperationName = "Вращение без циркуляции", OperationStartTime = new DateTime(2021, 06, 13, 13, 00, 00), DurationHours = 1.2 }, new OperationDetailsDto { OperationName = "Роторное бурение", OperationStartTime = new DateTime(2021, 06, 13, 14, 00, 00), DurationHours = 5.2 } } }, new OperationInfoDto { IntervalBegin = new DateTime(2021, 06, 03, 08, 00, 00), IntervalEnd = new DateTime(2021, 06, 04, 08, 00, 00), OperationData = new List { new OperationDetailsDto { OperationName = "Подъем с проработкой", OperationStartTime = new DateTime(2021, 06, 12, 10, 00, 00), DurationHours = 3.2 }, new OperationDetailsDto { OperationName = "Спуск с проработкой", OperationStartTime = new DateTime(2021, 06, 12, 11, 00, 00), DurationHours = 1.4 }, new OperationDetailsDto { OperationName = "Подъем с проработкой", OperationStartTime = new DateTime(2021, 06, 12, 12, 00, 00), DurationHours = 0.5 }, new OperationDetailsDto { OperationName = "На поверхности", OperationStartTime = new DateTime(2021, 06, 12, 13, 00, 00), DurationHours = 3.2 }, new OperationDetailsDto { OperationName = "Роторное бурение", OperationStartTime = new DateTime(2021, 06, 13, 14, 00, 00), DurationHours = 1.2 } } } }; } public DrillingAnalysis GetDrillingAnalysis(IEnumerable dataSaubBases) { var lastSaubDate = dataSaubBases.Last().Date; var saubWellDepths = dataSaubBases.Where(sw => sw.WellDepth is not null) .Select(s => (Value: (double)s.WellDepth, (s.Date - dataSaubBases.First().Date).TotalSeconds)); var saubBitDepths = dataSaubBases.Where(sw => sw.BitDepth is not null) .Select(s => (Value: (double)s.BitDepth, (s.Date - dataSaubBases.First().Date).TotalSeconds)); var saubBlockPositions = dataSaubBases.Where(sw => sw.BlockPosition is not null) .Select(s => (Value: (double)s.BlockPosition, (s.Date - dataSaubBases.First().Date).TotalSeconds)); var saubRotorSpeeds = dataSaubBases.Where(sw => sw.RotorSpeed is not null) .Select(s => (Value: (double)s.RotorSpeed, (s.Date - dataSaubBases.First().Date).TotalSeconds)); var saubPressures = dataSaubBases.Where(sw => sw.Pressure is not null) .Select(s => (Value: (double)s.Pressure, (s.Date - dataSaubBases.First().Date).TotalSeconds)); var saubHookWeights = dataSaubBases.Where(sw => sw.HookWeight is not null) .Select(s => (Value: (double)s.HookWeight, (s.Date - dataSaubBases.First().Date).TotalSeconds)); var wellDepthChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubWellDepths); var bitPositionChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubBitDepths); var blockPositionChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubBlockPositions); var rotorSpeedChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubRotorSpeeds); var pressureChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubPressures); var hookWeightChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubHookWeights); var IsBlockRising = LinearFunctionCalculator.IsValueGoesDown(blockPositionChangingIndex, -0.0001); var IsBlockGoesDown = LinearFunctionCalculator.IsValueGoesUp(blockPositionChangingIndex, 0.0001); var IsBlockStandsStill = LinearFunctionCalculator.IsValueNotChanges(blockPositionChangingIndex, (0.0001, -0.0001)); var drillingAnalysis = new DrillingAnalysis { IdTelemetry = dataSaubBases.First().IdTelemetry, Date = lastSaubDate, IsDepthChanges = LinearFunctionCalculator.IsValueChanges(wellDepthChangingIndex, (0.0001, -0.0001)), IsDepthNotChanges = LinearFunctionCalculator.IsValueNotChanges(wellDepthChangingIndex, (0.0001, -0.0001)), IsBitRising = LinearFunctionCalculator.IsValueGoesDown(bitPositionChangingIndex, -0.0001), IsBitGoesDown = LinearFunctionCalculator.IsValueGoesUp(bitPositionChangingIndex, 0.0001), IsBitStandsStill = LinearFunctionCalculator.IsValueNotChanges(bitPositionChangingIndex, (0.0001, -0.0001)), IsBitDepthLess20 = LinearFunctionCalculator.IsAverageLessThanBound(saubBitDepths, 20), IsBlockRising = LinearFunctionCalculator.IsValueGoesDown(blockPositionChangingIndex, -0.0001), IsBlockGoesDown = LinearFunctionCalculator.IsValueGoesUp(blockPositionChangingIndex, 0.0001), IsBlockStandsStill = LinearFunctionCalculator.IsValueNotChanges(blockPositionChangingIndex, (0.0001, -0.0001)), IsRotorSpeedLess3 = LinearFunctionCalculator.IsAverageLessThanBound(saubRotorSpeeds, 3), IsRotorSpeedMore3 = LinearFunctionCalculator.IsAverageMoreThanBound(saubRotorSpeeds, 3), IsPressureLess20 = LinearFunctionCalculator.IsAverageLessThanBound(saubPressures, 20), IsPressureMore20 = LinearFunctionCalculator.IsAverageMoreThanBound(saubPressures, 20), IsHookWeightNotChanges = LinearFunctionCalculator.IsValueNotChanges(hookWeightChangingIndex, (0.0001, -0.0001)), IsHookWeightLess3 = LinearFunctionCalculator.IsAverageLessThanBound(saubHookWeights, 3), IdOperation = 1 }; drillingAnalysis.IdOperation = operationDetectorService.DetectOperation(drillingAnalysis).Id; return drillingAnalysis; } } }