diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs deleted file mode 100644 index 3da8d5d0..00000000 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs +++ /dev/null @@ -1,97 +0,0 @@ -using AsbCloudDb.Model; - -namespace AsbCloudInfrastructure.Services.DetectOperations -{ - -#nullable enable - - abstract class DetectorAbstract - { - public int StepLength { get; set; } = 3; - public int FragmentLength { get; set; } = 6; - public int IdCategory { get; } - - // TODO: assert MaxDurationSeconds and MinDurationSeconds - public double MaxDurationSeconds { get; } = 24 * 60 * 60; - public double MinDurationSeconds { get; } = 3; - - /// - /// Конструктор детектора. - /// Словарь с IdCategory в дефолтных данных AsbCloudDbContext для таблицы WellOperationCategory - /// - /// ключ названия/описания операции из таблицы WellOperationCategory - public DetectorAbstract(int IdCategory) - { - this.IdCategory = IdCategory; - } - - public virtual DetectedOperation? DetectOrDefault(DetectableTelemetry[] telemetry, ref int positionStart) - { - if ((telemetry.Length > positionStart + FragmentLength + StepLength) && DetectStart(telemetry, positionStart)) - { - var skip = positionStart + StepLength; - while (telemetry.Length > skip + FragmentLength) - { - if (DetectEnd(telemetry, skip)) - { - var dateStart = telemetry[positionStart].DateTime; - var dateEnd = telemetry[skip].DateTime; - var durationSec = (dateEnd - dateStart).TotalSeconds; - if (durationSec < MinDurationSeconds || durationSec > MaxDurationSeconds) - return null; - - var result = new DetectedOperation - { - IdCategory = IdCategory, - IdUsersAtStart = telemetry[positionStart].IdUser ?? -1, - DateStart = dateStart, - DateEnd = dateEnd, - DepthStart = telemetry[positionStart].WellDepth ?? -1d, - DepthEnd = telemetry[skip].WellDepth ?? -1d, - Value = CalcValue(telemetry, positionStart, skip), - }; - - if (!IsValid(result)) - return null; - - positionStart = skip;// + FragmentLength; - return result; - } - - skip = skip + StepLength; - } - } - return null; - } - - /// - /// Расчет ключевого параметра - /// - /// - protected abstract double CalcValue(DetectableTelemetry[] telemetry, int positionBegin, int positionEnd); - - /// - /// Определение начала операции - /// - /// - /// - /// - protected abstract bool DetectStart(DetectableTelemetry[] telemetry, int position); - - /// - /// Определение окончания операции - /// - /// - /// - /// - protected abstract bool DetectEnd(DetectableTelemetry[] telemetry, int position); - - /// - /// Валидация операции - /// - /// - /// - protected abstract bool IsValid(DetectedOperation result); - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingBase.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingBase.cs deleted file mode 100644 index 258bdd2e..00000000 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingBase.cs +++ /dev/null @@ -1,86 +0,0 @@ -using AsbCloudDb.Model; -using System.Linq; - -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors -{ - internal abstract class DetectorDrillingAbstract : DetectorAbstract - { - /* # РАСЧЕТ minRop - * шаг энкодера = 0.006м; - * 2 шага за 10 секунд не считается, так как может быть простым шумом; - * minRop = 0.006 * 2 / 10 = 0.0012 м/сек - * minRop > 4.32 м/ч & minRop < 6.48 м/ч (3 шага за 10 сек); - */ - protected const double minRop = 5.4; //м/час - protected const double minRotorSpeed = 5; //об/мин - protected const double minPressure = 25; - protected const double minDeltaDepth = 0.01; - - public DetectorDrillingAbstract(int IdCategory) : base(IdCategory) - { - FragmentLength = 12; - StepLength = 3; - } - - protected override bool DetectStart(DetectableTelemetry[] telemetry, int position) - { - var firstItem = telemetry[position]; - var deltaDepth = firstItem.WellDepth - firstItem.BitDepth; - if (deltaDepth is not null && - System.Math.Abs((float)deltaDepth) > minDeltaDepth) - return false; - - if (firstItem.Pressure < minPressure) - return false; - - var fragment = telemetry[position..(position + FragmentLength)]; - - var lineBlockPosition = new InterpolationLine(fragment.Select(d => (d.BlockPosition ?? 0d, (d.DateTime - firstItem.DateTime).TotalHours))); - if (!lineBlockPosition.IsYDecreases(-minRop)) - return false; - - var lineWellDepth = new InterpolationLine(fragment.Select(d => ((d.WellDepth - firstItem.WellDepth) ?? 0d, (d.DateTime - firstItem.DateTime).TotalHours))); - if (!lineWellDepth.IsYIncreases(minRop)) - return false; - - if (!ModeCondition(fragment)) - return false; - - return true; - } - - protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position) - { - var firstItem = telemetry[position]; - var deltaDepth = firstItem.WellDepth - firstItem.BitDepth; - if (deltaDepth is not null && - System.Math.Abs((float)deltaDepth) > minDeltaDepth) - return true; - - if (firstItem.Pressure < minPressure) - return true; - - var fragment = telemetry[position..(position + FragmentLength)]; - if (!ModeCondition(fragment)) - return true; - - return false; - } - - protected abstract bool ModeCondition(DetectableTelemetry[] telemetryFragment); - - /// - /// Рассчитываем МСП, м/час - /// - /// - protected override double CalcValue(DetectableTelemetry[] telemetry, int positionBegin, int positionEnd) - { - var pBegin = telemetry[positionBegin]; - var pEnd = telemetry[positionEnd]; - var result = (double)(pEnd.WellDepth - pBegin.WellDepth) / (pEnd.DateTime - pBegin.DateTime).TotalHours; - return result; - } - protected override bool IsValid(DetectedOperation result) - => result.Value > 0; - } -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingRotor.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingRotor.cs deleted file mode 100644 index 73cf8675..00000000 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingRotor.cs +++ /dev/null @@ -1,19 +0,0 @@ -using AsbCloudDb.Model; -using System.Linq; - -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors -{ -#nullable enable - class DetectorDrillingRotor : DetectorDrillingAbstract - { - public DetectorDrillingRotor() - : base(2){} - - protected override bool ModeCondition(DetectableTelemetry[] telemetryFragment) - { - var lineRotorSpeed = new InterpolationLine(telemetryFragment.Select(d => (d.RotorSpeed ?? 0d, (d.DateTime - telemetryFragment[0].DateTime).TotalHours))); - return lineRotorSpeed.IsAverageYMoreThanBound(minRotorSpeed); - } - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingSlide.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingSlide.cs deleted file mode 100644 index d072e5bd..00000000 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingSlide.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Linq; - -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors -{ -#nullable enable - class DetectorDrillingSlide : DetectorDrillingAbstract - { - public DetectorDrillingSlide() - : base(3){} - - protected override bool ModeCondition(DetectableTelemetry[] telemetryFragment) - { - var lineRotorSpeed = new InterpolationLine(telemetryFragment.Select(d => (d.RotorSpeed ?? 0d, (d.DateTime - telemetryFragment[0].DateTime).TotalHours))); - return lineRotorSpeed.IsAverageYLessThanBound(minRotorSpeed); - } - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs deleted file mode 100644 index 870cd7bd..00000000 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs +++ /dev/null @@ -1,50 +0,0 @@ -using AsbCloudDb.Model; - -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors -{ -#nullable enable - class DetectorSlipsTime : DetectorAbstract - { - public DetectorSlipsTime() : base(14) { } - public double HookWeightSP { get; set; } = 20; - public double PressureSP { get; set; } = 15; - public double PosisionSP { get; set; } = 8; - public double DeltaWellDepthMax { get; set; } = 2.5; - - protected override bool DetectStart(DetectableTelemetry[] telemetry, int position) - { - var item = telemetry[position]; - - var result = - item.HookWeight < HookWeightSP && - item.Pressure < PressureSP && - item.BlockPosition < PosisionSP && - (item.WellDepth - item.BitDepth) < DeltaWellDepthMax; - - return result; - } - - protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position) - { - var item = telemetry[position]; - - var result = item.Pressure > PressureSP && - item.BlockPosition > PosisionSP; - - return result; - } - - protected override double CalcValue(DetectableTelemetry[] telemetry, int positionBegin, int positionEnd) - { - var pBegin = telemetry[positionBegin]; - var pEnd = telemetry[positionEnd]; - var result = (pEnd.DateTime - pBegin.DateTime).TotalMinutes; - return result; - } - - protected override bool IsValid(DetectedOperation result) - => result.Value > 0; - - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs new file mode 100644 index 00000000..ca6115e9 --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs @@ -0,0 +1,144 @@ +using AsbCloudDb.Model; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +{ +#nullable enable + internal class FragmentDetector : IFragmentDetector + { + private int fragmentLength = 12; + private int stepLength = 3; + protected IEnumerable detectors = Enumerable.Empty(); + + protected Func detectStart; + protected Func detectEnd; + + public int FragmentLength { get => fragmentLength; set => fragmentLength = value; } + public int StepLength { get => stepLength; set => stepLength = value; } + + public FragmentDetector( + Func detectStart, + IFragmentDetector detector, + params IFragmentDetector[] detectors) + { + this.detectStart = detectStart; + this.detectors = JoinDetectors(detector, detectors); + detectEnd = (f, i) => !detectStart(f,i); + } + + public FragmentDetector( + Func detectStart, + Func detectEnd, + IFragmentDetector detector, + params IFragmentDetector[] detectors) + { + this.detectStart = detectStart; + this.detectEnd = detectEnd; + this.detectors = JoinDetectors(detector, detectors); + } + + public FragmentDetector(Func detectStart, IOperationDetector operation) + { + this.detectStart = detectStart; + detectors = new IOperationDetector[] { operation }; + detectEnd = (f, i) => !detectStart(f, i); + } + + public FragmentDetector(Func detectStart, Func detectEnd, IOperationDetector operation) + { + this.detectStart = detectStart; + this.detectEnd = detectEnd; + detectors = new IOperationDetector[] { operation }; + } + + private static IEnumerable JoinDetectors(IFragmentDetector detector, params IFragmentDetector[] detectors) + { + var joined = new IFragmentDetector[1 + detectors.Length]; + joined[0] = detector; + if (detectors.Length > 0) + detectors.CopyTo(joined, 1); + return joined; + } + + public static Func MakeInstantDelegate(Func instantValueCondition) + { + var detect = (DetectableTelemetry[] telemetry, int position) => + { + var firstItem = telemetry[position]; + var result = instantValueCondition(firstItem); + return result; + }; + return detect; + } + + public static Func MakeInterpolationDelegate( + Func yGetter, + Func interpolationValueCondition, + int fragmentLength) + { + var detect = (DetectableTelemetry[] telemetry, int position) => + { + DetectableTelemetry[] data; + if (fragmentLength > 0 && fragmentLength < telemetry.Length) + data = telemetry[position..(position + fragmentLength)]; + else + data = telemetry; + var line = new InterpolationLine(data.Select(d => (yGetter(d), (d.DateTime - telemetry[0].DateTime).TotalHours))); + var result = interpolationValueCondition(line); + return result; + }; + return detect; + } + + public IFragmentDetector AddChildDetector(params IFragmentDetector[] detectors) + { + throw new NotImplementedException(); + } + + public IDetector AddOperationDetector(IOperationDetector operation) + { + detectors = new IOperationDetector[] { operation}; + return this; + } + + public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable operations) + { + var positionStart = 0; + var operationsList = new List(); + // поиск начала соответствия критерию + while (telemetryFragment.Length > positionStart + FragmentLength + stepLength) + { + if (detectStart(telemetryFragment, positionStart)) + { + // Поиск окончания соответствия критерию + var positionEnd = positionStart + stepLength; + while (telemetryFragment.Length > positionEnd + FragmentLength) + { + if (detectEnd(telemetryFragment, positionEnd)) + { + var innerFragment = telemetryFragment[positionStart..positionEnd]; + var detectorEnumerator = detectors.GetEnumerator(); + while(detectorEnumerator.MoveNext()) + if (detectorEnumerator.Current.TryDetect(idTelemetry, innerFragment, out IEnumerable result)) + operationsList.AddRange(result); + + break; + } + positionEnd += stepLength; + } + positionStart = positionEnd; + } + else + { + positionStart += stepLength; + } + } + operations = operationsList; + return operationsList.Any(); + } + + } +#nullable disable +} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs new file mode 100644 index 00000000..96640006 --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs @@ -0,0 +1,17 @@ +using AsbCloudDb.Model; +using System.Collections.Generic; +using System.Linq; + +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +{ + internal interface IDetector + { + bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable operations); + } + + internal interface IOperationDetector : IDetector + { } + + internal interface IFragmentDetector: IDetector + { } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetector.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetector.cs new file mode 100644 index 00000000..14451145 --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetector.cs @@ -0,0 +1,66 @@ +using AsbCloudDb.Model; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +{ + internal class OperationDetector : IOperationDetector + { + private readonly int idOperation; + + protected Func isValid = (_) => true; + + protected Func calcValue = (_) => 0d; + + public OperationDetector(int idOperation) + { + this.idOperation = idOperation; + } + + public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable operations) + { + if(!telemetryFragment.Any() || !isValid(telemetryFragment)) + { + operations = Enumerable.Empty(); + return false; + } + + var operation = MakeOperation(idTelemetry, telemetryFragment); + + operations = new List { operation }; + + return true; + } + + private DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetryFragment) + { + var pBegin = telemetryFragment.First(); + var pEnd = telemetryFragment.Last(); + var operation = new DetectedOperation + { + IdTelemetry = idTelemetry, + IdCategory = idOperation, + IdUsersAtStart = pBegin.IdUser ?? -1, + DateStart = pBegin.DateTime, + DateEnd = pEnd.DateTime, + DepthStart = (double)pBegin.WellDepth, + DepthEnd = (double)pEnd.WellDepth, + Value = calcValue(telemetryFragment), + }; + return operation; + } + + public OperationDetector SetIsValidDelegate(Func isValid) + { + this.isValid = isValid; + return this; + } + + public OperationDetector SetCalcValueDelegate(Func calcValue) + { + this.calcValue = calcValue; + return this; + } + } +} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDrilling.cs new file mode 100644 index 00000000..2686339d --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDrilling.cs @@ -0,0 +1,30 @@ +using System.Linq; + +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +{ + + internal class OperationDrilling : OperationDetector + { + public OperationDrilling(int idOperation) + :base(idOperation) + { + isValid = (DetectableTelemetry[] telemetryFragment) => + { + var pBegin = telemetryFragment.First(); + var pEnd = telemetryFragment.Last(); + if (pBegin.WellDepth >= pEnd.WellDepth) + return false; + + return true; + }; + + calcValue = (DetectableTelemetry[] telemetryFragment) => + { + var pBegin = telemetryFragment.First(); + var pEnd = telemetryFragment.Last(); + var result = (double)(pEnd.WellDepth - pBegin.WellDepth) / (pEnd.DateTime - pBegin.DateTime).TotalHours; + return result; + }; + } + } +} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationSlipsTime.cs new file mode 100644 index 00000000..98291fec --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationSlipsTime.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq; + +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +{ + internal class OperationSlipsTime : OperationDetector + { + public OperationSlipsTime() + : base(14) + { + isValid = (DetectableTelemetry[] telemetryFragment) => + { + var pBegin = telemetryFragment.First(); + var pEnd = telemetryFragment.Last(); + if (Math.Abs((double)(pBegin.WellDepth - pEnd.WellDepth)) > 0.01) + return false; + + return true; + }; + + calcValue = (DetectableTelemetry[] telemetryFragment) => + { + var pBegin = telemetryFragment.First(); + var pEnd = telemetryFragment.Last(); + var result = (pEnd.DateTime - pBegin.DateTime).TotalHours; + return result; + }; + } + } +} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/readme.md b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/readme.md new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/readme.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/InterpolationLine.cs b/AsbCloudInfrastructure/Services/DetectOperations/InterpolationLine.cs index e7ab4fec..1dc99547 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/InterpolationLine.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/InterpolationLine.cs @@ -46,10 +46,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations public bool IsYDecreases(double bound = 0d) => A < bound; - public bool IsAverageYLessThanBound(double bound) => + public bool IsAverageYLessThan(double bound) => (ySum / count) < bound; - public bool IsAverageYMoreThanBound(double bound) => + public bool IsAverageYGreaterThan(double bound) => (ySum / count) >= bound; } } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs b/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs index 16e414ae..bc22de01 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs @@ -8,31 +8,39 @@ using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudInfrastructure.Services.DetectOperations.Detectors; namespace AsbCloudInfrastructure.Services.DetectOperations { public class OperationDetectionBackgroundService : BackgroundService { - private readonly IEnumerable detectors = new List - { - new Detectors.DetectorSlipsTime(), - new Detectors.DetectorDrillingRotor(), - new Detectors.DetectorDrillingSlide(), - }; - - private readonly int minStepLength; - private readonly int minFragmentLength; + private readonly int minStepLength = 3; + private readonly int minFragmentLength = 6; private readonly string connectionString; private readonly TimeSpan period = TimeSpan.FromHours(1); + private static readonly Func isBitAtTheBottom = FragmentDetector.MakeInstantDelegate(d => (double)(d.WellDepth - d.BitDepth) < 0.001d); + private static readonly Func isPressureGt25 = FragmentDetector.MakeInstantDelegate(d => d.Pressure > 25); + private static readonly Func isPressureLt15 = FragmentDetector.MakeInstantDelegate(d => d.Pressure < 15); + private static readonly Func isBlockPositionLt8 = FragmentDetector.MakeInstantDelegate(d => d.BlockPosition < 8); + private static readonly Func isHookWeightLt20 = FragmentDetector.MakeInstantDelegate(d => d.HookWeight < 20); + private static readonly Func isRotorSpeedAvgGt5 = FragmentDetector.MakeInterpolationDelegate(d => (double)d.RotorSpeed, line => line.IsAverageYGreaterThan(5), 12); + private static readonly Func isRotorSpeedAvgLt5 = FragmentDetector.MakeInterpolationDelegate(d => (double)d.RotorSpeed, line => line.IsAverageYLessThan(5), 12); + private static readonly List detectors = new List + { + new FragmentDetector(isBitAtTheBottom, + new FragmentDetector(isPressureGt25, + new FragmentDetector(isRotorSpeedAvgGt5, new OperationDrilling(3)), + new FragmentDetector(isRotorSpeedAvgLt5, new OperationDrilling(2)) + ), + new FragmentDetector(isPressureLt15, + new FragmentDetector(isBlockPositionLt8, + new FragmentDetector(isHookWeightLt20, new OperationSlipsTime()))) + ) + }; + public OperationDetectionBackgroundService(IConfiguration configuration) { - minStepLength = detectors.Min(d => d.StepLength); - minStepLength = minStepLength > 0 ? minStepLength : 3; - - minFragmentLength = detectors.Min(d => d.FragmentLength); - minFragmentLength = minFragmentLength > 0 ? minFragmentLength : 6; - connectionString = configuration.GetConnectionString("DefaultConnection"); } @@ -128,70 +136,46 @@ namespace AsbCloudInfrastructure.Services.DetectOperations }) .OrderBy(d => d.DateTime); - var take = 4 * 86_400; + var take = 4 * 86_400;// 4 дня var startDate = begin; var detectedOperations = new List(8); - var dbRequests_ = 0; - var dbTime_ = 0d; - var sw_ = new Stopwatch(); - var otherTime_ = 0d; - while (true) { - sw_.Restart(); var data = await query .Where(d => d.DateTime > startDate) .Take(take) .ToArrayAsync(token); - sw_.Stop(); - dbTime_ += sw_.ElapsedMilliseconds; - dbRequests_++; - sw_.Restart(); - if (data.Length < minFragmentLength) break; - var skip = 0; - var isDetected = false; - while (data.Length > skip + minFragmentLength) + foreach (var detector in detectors) { - var isDetected1 = false; - - foreach (var detector in detectors) + if (detector is FragmentDetector fragmentDetector) { - if (data.Length < skip + detector.StepLength + detector.FragmentLength) + var minLengthToDetect = fragmentDetector.StepLength + fragmentDetector.FragmentLength; + if (data.Length < minLengthToDetect) continue; - var detectedOperation = detector.DetectOrDefault(data, ref skip); - if (detectedOperation is not null) + if (fragmentDetector.TryDetect(idTelemetry, data, out IEnumerable operations)) { - isDetected1 = true; isDetected = true; - detectedOperation.IdTelemetry = idTelemetry; - detectedOperations.Add(detectedOperation); - startDate = detectedOperation.DateEnd; + detectedOperations.AddRange(operations); + startDate = operations.Last().DateEnd; break; } } - - if (!isDetected1) - skip += minStepLength; } - sw_.Stop(); - otherTime_ += sw_.ElapsedMilliseconds; - if (!isDetected) { if (data.Length < take) break; - var lastPartDate = data.Last().DateTime; - startDate = startDate + (0.75 * (lastPartDate - startDate)); + startDate = startDate.AddSeconds(0.95 * take); } }