From 85c253b82b266a5a35669d6ad681534165272caf Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 22 Jun 2022 10:02:00 +0500 Subject: [PATCH 1/4] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=B5=D1=82=D0=B5=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D0=B2=20=D1=81=D0=BE=D0=B2=D0=BC=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=BD=D0=BE=20=D1=81=20=D0=90=D0=9F=D0=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Detectors/DetectorAbstract.cs | 44 ++++++++-- .../Detectors/DetectorDrillingBase.cs | 86 +++++++++++++++++++ .../Detectors/DetectorDrillingRotor.cs | 54 ++---------- .../Detectors/DetectorDrillingSlide.cs | 56 ++---------- .../Detectors/DetectorSlipsTime.cs | 11 ++- ConsoleApp1/Program.cs | 20 +++++ ConsoleApp1/Properties/launchSettings.json | 8 -- 7 files changed, 163 insertions(+), 116 deletions(-) create mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingBase.cs delete mode 100644 ConsoleApp1/Properties/launchSettings.json diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs index 0924849a..3da8d5d0 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs @@ -25,16 +25,16 @@ namespace AsbCloudInfrastructure.Services.DetectOperations this.IdCategory = IdCategory; } - public virtual DetectedOperation? DetectOrDefault(DetectableTelemetry[] telemetry, ref int position) + public virtual DetectedOperation? DetectOrDefault(DetectableTelemetry[] telemetry, ref int positionStart) { - if ((telemetry.Length > position + FragmentLength + StepLength) && DetectStart(telemetry, position)) + if ((telemetry.Length > positionStart + FragmentLength + StepLength) && DetectStart(telemetry, positionStart)) { - var skip = position + StepLength; + var skip = positionStart + StepLength; while (telemetry.Length > skip + FragmentLength) { if (DetectEnd(telemetry, skip)) { - var dateStart = telemetry[position].DateTime; + var dateStart = telemetry[positionStart].DateTime; var dateEnd = telemetry[skip].DateTime; var durationSec = (dateEnd - dateStart).TotalSeconds; if (durationSec < MinDurationSeconds || durationSec > MaxDurationSeconds) @@ -43,14 +43,18 @@ namespace AsbCloudInfrastructure.Services.DetectOperations var result = new DetectedOperation { IdCategory = IdCategory, - IdUsersAtStart = telemetry[position].IdUser ?? -1, + IdUsersAtStart = telemetry[positionStart].IdUser ?? -1, DateStart = dateStart, DateEnd = dateEnd, - DepthStart = telemetry[position].WellDepth ?? -1d, + DepthStart = telemetry[positionStart].WellDepth ?? -1d, DepthEnd = telemetry[skip].WellDepth ?? -1d, + Value = CalcValue(telemetry, positionStart, skip), }; - CalcValue(ref result); - position = skip + FragmentLength; + + if (!IsValid(result)) + return null; + + positionStart = skip;// + FragmentLength; return result; } @@ -60,12 +64,34 @@ namespace AsbCloudInfrastructure.Services.DetectOperations return null; } - protected abstract void CalcValue(ref DetectedOperation result); + /// + /// Расчет ключевого параметра + /// + /// + 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 new file mode 100644 index 00000000..258bdd2e --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingBase.cs @@ -0,0 +1,86 @@ +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 index 6810a05b..73cf8675 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingRotor.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingRotor.cs @@ -4,57 +4,15 @@ using System.Linq; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors { #nullable enable - class DetectorDrillingRotor : DetectorAbstract + class DetectorDrillingRotor : DetectorDrillingAbstract { - const double minRop = 5; //м/час - const double minRotorSpeed = 5; //об/мин - const double ticksPerHour = 60 * 60 * 10_000_000d; - const double minPressure = 25; - const double minDeltaDepth = 0.02; + public DetectorDrillingRotor() + : base(2){} - public DetectorDrillingRotor() : base(2) + protected override bool ModeCondition(DetectableTelemetry[] telemetryFragment) { - FragmentLength = 15; - StepLength = 10; - } - - 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.RotorSpeed > minRotorSpeed) - 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.Ticks / ticksPerHour))); - if (!lineBlockPosition.IsYDecreases(minRop)) - return false; - - var lineWellDepth = new InterpolationLine(fragment.Select(d => (d.WellDepth ?? 0d, d.DateTime.Ticks / ticksPerHour))); - if (!lineWellDepth.IsYIncreases(minRop)) - return false; - - return true; - } - - protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position) - => !DetectStart(telemetry, position); - - /// - /// Рассчитываем МСП, м/час - /// - /// - protected override void CalcValue(ref DetectedOperation result) - { - result.Value = (result.DepthEnd - result.DepthStart) / (result.DateEnd - result.DateStart).TotalHours; + 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 index 89f20ae6..d072e5bd 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingSlide.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingSlide.cs @@ -1,59 +1,17 @@ -using AsbCloudDb.Model; -using System.Linq; +using System.Linq; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors { #nullable enable - class DetectorDrillingSlide : DetectorAbstract + class DetectorDrillingSlide : DetectorDrillingAbstract { - const double minRop = 5; //м/час - const double minRotorSpeed = 5; //об/мин - const double ticksPerHour = 60 * 60 * 10_000_000d; - const double minPressure = 25; - const double minDeltaDepth = 0.02; + public DetectorDrillingSlide() + : base(3){} - public DetectorDrillingSlide() : base(3) + protected override bool ModeCondition(DetectableTelemetry[] telemetryFragment) { - FragmentLength = 10; - } - - 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.RotorSpeed < minRotorSpeed) - 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.Ticks / ticksPerHour))); - if (!lineBlockPosition.IsYDecreases(minRop)) - return false; - - var lineWellDepth = new InterpolationLine(fragment.Select(d => (d.WellDepth ?? 0d, d.DateTime.Ticks / ticksPerHour))); - if (!lineWellDepth.IsYIncreases(minRop)) - return false; - - return true; - } - - protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position) - => !DetectStart(telemetry, position); - - /// - /// Рассчитываем МСП, м/час - /// - /// - protected override void CalcValue(ref DetectedOperation result) - { - result.Value = (result.DepthEnd - result.DepthStart) / (result.DateEnd - result.DateStart).TotalHours; + 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 index ba8b70c6..870cd7bd 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs @@ -34,10 +34,17 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors return result; } - protected override void CalcValue(ref DetectedOperation result) + protected override double CalcValue(DetectableTelemetry[] telemetry, int positionBegin, int positionEnd) { - result.Value = result.DurationMinutes; + 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/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index c4f6f029..0e85aa5f 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -12,6 +12,26 @@ namespace ConsoleApp1 // use ServiceFactory to make services static void Main(/*string[] args*/) { + System.Collections.Generic.List<(double, double)> data = new() { + (22.52400016784668, 17715023.435277779) , + (22.52400016784668, 17715023.435555555) , + (22.52400016784668, 17715023.435833335) , + (22.52400016784668, 17715023.436111111) , + (22.547000885009766, 17715023.436388887) , + (22.833000183105469, 17715023.436666667) , + (23.063999176025391, 17715023.436944444) , + (23.298999786376953, 17715023.437222224) , + (23.5310001373291, 17715023.4375) , + (23.763999938964844, 17715023.437777776) , + (23.993999481201172, 17715023.438055556) , + (24.229999542236328, 17715023.438333333) , + (24.459999084472656, 17715023.438611113) , + (24.694999694824219, 17715023.438888889) , + (24.926000595092773, 17715023.439166665) , + }; + + var il = new AsbCloudInfrastructure.Services.DetectOperations.InterpolationLine(data); + Console.WriteLine("hit keyboard to start"); Console.ReadLine(); diff --git a/ConsoleApp1/Properties/launchSettings.json b/ConsoleApp1/Properties/launchSettings.json deleted file mode 100644 index 33504c94..00000000 --- a/ConsoleApp1/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "WSL": { - "commandName": "WSL2", - "distributionName": "" - } - } -} \ No newline at end of file From d0386b01826d8f583b6e343e0ef77cbfd66ec0b0 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 27 Jun 2022 10:20:54 +0500 Subject: [PATCH 2/4] doesn't work. Wrong handle begin of operation. --- .../Detectors/DetectorAbstract.cs | 97 ------------ .../Detectors/DetectorDrillingBase.cs | 86 ----------- .../Detectors/DetectorDrillingRotor.cs | 19 --- .../Detectors/DetectorDrillingSlide.cs | 18 --- .../Detectors/DetectorSlipsTime.cs | 50 ------ .../Detectors/FragmentDetector.cs | 144 ++++++++++++++++++ .../DetectOperations/Detectors/IDetector.cs | 17 +++ .../Detectors/OperationDetector.cs | 66 ++++++++ .../Detectors/OperationDrilling.cs | 30 ++++ .../Detectors/OperationSlipsTime.cs | 30 ++++ .../DetectOperations/Detectors/readme.md | 1 + .../DetectOperations/InterpolationLine.cs | 4 +- .../OperationDetectionBackgroundService.cs | 80 ++++------ 13 files changed, 322 insertions(+), 320 deletions(-) delete mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs delete mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingBase.cs delete mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingRotor.cs delete mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrillingSlide.cs delete mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs create mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs create mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs create mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetector.cs create mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDrilling.cs create mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationSlipsTime.cs create mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/readme.md 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); } } From 9ab41cd24efa8a99ad917f1d6d0f8738370a5ed0 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 27 Jun 2022 12:43:55 +0500 Subject: [PATCH 3/4] slow detection --- .../Detectors/FragmentDetector.cs | 58 +++++++------------ .../DetectOperations/Detectors/IDetector.cs | 2 +- .../OperationDetectionBackgroundService.cs | 39 ++++++++----- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs index ca6115e9..5cb663e3 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs @@ -19,15 +19,14 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors public int StepLength { get => stepLength; set => stepLength = value; } public FragmentDetector( - Func detectStart, - IFragmentDetector detector, + Func detectStart, + IFragmentDetector detector, params IFragmentDetector[] detectors) { this.detectStart = detectStart; this.detectors = JoinDetectors(detector, detectors); - detectEnd = (f, i) => !detectStart(f,i); + detectEnd = (f, i) => !detectStart(f, i); } - public FragmentDetector( Func detectStart, Func detectEnd, @@ -92,49 +91,36 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors 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)) { - if (detectStart(telemetryFragment, positionStart)) + // Поиск окончания соответствия критерию + var positionEnd = positionStart + stepLength; + while (telemetryFragment.Length > positionEnd + FragmentLength) { - // Поиск окончания соответствия критерию - var positionEnd = positionStart + stepLength; - while (telemetryFragment.Length > positionEnd + FragmentLength) + if (detectEnd(telemetryFragment, positionEnd)) { - 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); + 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; + break; } - positionStart = positionEnd; - } - else - { - positionStart += stepLength; + positionEnd += stepLength; } } + else + { + operations = Enumerable.Empty(); + return false; + } + operations = operationsList; return operationsList.Any(); } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs index 96640006..5db7005d 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs @@ -13,5 +13,5 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors { } internal interface IFragmentDetector: IDetector - { } + { } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs b/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs index bc22de01..b0a2f97d 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs @@ -136,7 +136,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations }) .OrderBy(d => d.DateTime); - var take = 4 * 86_400;// 4 дня + var take = 4 * 86_400; // 4 дня var startDate = begin; var detectedOperations = new List(8); @@ -151,23 +151,36 @@ namespace AsbCloudInfrastructure.Services.DetectOperations break; var isDetected = false; - - foreach (var detector in detectors) + var positionStart = 0; + while (data.Length > positionStart + minFragmentLength + minStepLength) { - if (detector is FragmentDetector fragmentDetector) + var telemetryFragment = data[positionStart..]; + var isDetected1 = false; + foreach (var detector in detectors) { - var minLengthToDetect = fragmentDetector.StepLength + fragmentDetector.FragmentLength; - if (data.Length < minLengthToDetect) - continue; - - if (fragmentDetector.TryDetect(idTelemetry, data, out IEnumerable operations)) + if (detector is FragmentDetector fragmentDetector) { - isDetected = true; - detectedOperations.AddRange(operations); - startDate = operations.Last().DateEnd; - break; + var minLengthToDetect = fragmentDetector.StepLength + fragmentDetector.FragmentLength; + if (telemetryFragment.Length < minLengthToDetect) + continue; + + if (fragmentDetector.TryDetect(idTelemetry, data, out IEnumerable operations)) + { + isDetected = true; + isDetected1 = true; + detectedOperations.AddRange(operations); + startDate = operations.Last().DateEnd; + positionStart = 0; + data = data + .Where(d => d.DateTime > startDate) + .ToArray(); + break; + } } } + + if (!isDetected1) + positionStart += minStepLength; } if (!isDetected) From 050711c34b82da0943ee311c59c6b826fd35ac03 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 29 Jun 2022 13:40:06 +0500 Subject: [PATCH 4/4] =?UTF-8?q?=D0=9E=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F=D1=8E?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=B5=D0=B5=20=D0=B8=20=D0=B1=D1=8B=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=B5=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Detectors/FragmentDetector.cs | 90 +++++++++++----- .../DetectOperations/Detectors/IDetector.cs | 2 +- .../Detectors/OperationDetector.cs | 64 +++++------ .../Detectors/OperationDrilling.cs | 12 +-- .../Detectors/OperationSlipsTime.cs | 12 +-- .../OperationDetectionBackgroundService.cs | 102 +++++++++--------- 6 files changed, 159 insertions(+), 123 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs index 5cb663e3..17f8b9dc 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs @@ -1,7 +1,7 @@ -using AsbCloudDb.Model; -using System; +using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors { @@ -15,10 +15,13 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors protected Func detectStart; protected Func detectEnd; + public string Name { get; set; } + public int FragmentLength { get => fragmentLength; set => fragmentLength = value; } public int StepLength { get => stepLength; set => stepLength = value; } public FragmentDetector( + string name, Func detectStart, IFragmentDetector detector, params IFragmentDetector[] detectors) @@ -26,8 +29,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors this.detectStart = detectStart; this.detectors = JoinDetectors(detector, detectors); detectEnd = (f, i) => !detectStart(f, i); + Name = name; } public FragmentDetector( + string name, Func detectStart, Func detectEnd, IFragmentDetector detector, @@ -36,20 +41,30 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors this.detectStart = detectStart; this.detectEnd = detectEnd; this.detectors = JoinDetectors(detector, detectors); + Name = name; } - public FragmentDetector(Func detectStart, IOperationDetector operation) + public FragmentDetector( + string name, + Func detectStart, + IOperationDetector operation) { this.detectStart = detectStart; detectors = new IOperationDetector[] { operation }; detectEnd = (f, i) => !detectStart(f, i); + Name = name; } - public FragmentDetector(Func detectStart, Func detectEnd, IOperationDetector operation) + public FragmentDetector( + string name, + Func detectStart, + Func detectEnd, + IOperationDetector operation) { this.detectStart = detectStart; this.detectEnd = detectEnd; detectors = new IOperationDetector[] { operation }; + Name = name; } private static IEnumerable JoinDetectors(IFragmentDetector detector, params IFragmentDetector[] detectors) @@ -61,7 +76,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors return joined; } - public static Func MakeInstantDelegate(Func instantValueCondition) + public static Func MakeInstantDelegate( + Func instantValueCondition + ) { var detect = (DetectableTelemetry[] telemetry, int position) => { @@ -80,10 +97,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors var detect = (DetectableTelemetry[] telemetry, int position) => { DetectableTelemetry[] data; - if (fragmentLength > 0 && fragmentLength < telemetry.Length) + if (fragmentLength > 0 && (position + fragmentLength) < telemetry.Length) data = telemetry[position..(position + fragmentLength)]; else - data = telemetry; + data = telemetry[position..]; var line = new InterpolationLine(data.Select(d => (yGetter(d), (d.DateTime - telemetry[0].DateTime).TotalHours))); var result = interpolationValueCondition(line); return result; @@ -91,40 +108,55 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors return detect; } - public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable operations) + public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, out IEnumerable results) { - var positionStart = 0; - var operationsList = new List(); - // проверка соответствия критерию начала операции - if (detectStart(telemetryFragment, positionStart)) + List? totaltResultList = null; + var positionBegin = begin; + // Поиск начала соответствия критерию начала операции + while (end > positionBegin + fragmentLength + stepLength) { - // Поиск окончания соответствия критерию - var positionEnd = positionStart + stepLength; - while (telemetryFragment.Length > positionEnd + FragmentLength) + if (detectStart(telemetry, positionBegin)) { - if (detectEnd(telemetryFragment, positionEnd)) + // Поиск окончания соответствия критерию + var positionEnd = positionBegin; + while (positionEnd < end) { - var innerFragment = telemetryFragment[positionStart..positionEnd]; - var detectorEnumerator = detectors.GetEnumerator(); - while (detectorEnumerator.MoveNext()) - if (detectorEnumerator.Current.TryDetect(idTelemetry, innerFragment, out IEnumerable result)) - operationsList.AddRange(result); + positionEnd += stepLength; + if ((positionEnd > end)) + positionEnd = end; - break; + if ((positionEnd == end) || detectEnd(telemetry, positionEnd)) + { + totaltResultList = totaltResultList ?? new List(); + var detectorsEnumerator = detectors.GetEnumerator(); + while (detectorsEnumerator.MoveNext()) + if (detectorsEnumerator.Current.TryDetect(idTelemetry, telemetry, positionBegin, positionEnd, out IEnumerable innerResult)) + totaltResultList.AddRange(innerResult); + + break; + } } - positionEnd += stepLength; + positionBegin = positionEnd; } + else + { + positionBegin += stepLength; + } + } + + if(totaltResultList?.Any() == true) + { + results = totaltResultList!; + return true; } else { - operations = Enumerable.Empty(); + results = Enumerable.Empty(); return false; - } - - operations = operationsList; - return operationsList.Any(); + } } - + public override string ToString() + => $"frame detector {Name}"; } #nullable disable } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs index 5db7005d..f08ff2a9 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/IDetector.cs @@ -6,7 +6,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors { internal interface IDetector { - bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable operations); + bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, int begin, int end, out IEnumerable operations); } internal interface IOperationDetector : IDetector diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetector.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetector.cs index 14451145..07cfb4a4 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetector.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetector.cs @@ -5,62 +5,62 @@ using System.Linq; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors { + class OperationDetectorResult + { + public int TelemetryBegin { get; set; } + public int TelemetryEnd { get; set; } + public DetectedOperation Operation { get; set; } + } + internal class OperationDetector : IOperationDetector { private readonly int idOperation; - protected Func isValid = (_) => true; + protected Func isValid = (_,_,_) => true; - protected Func calcValue = (_) => 0d; + protected Func calcValue = (_, _, _) => 0d; public OperationDetector(int idOperation) { this.idOperation = idOperation; } - public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable operations) + public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, int begin, int end, out IEnumerable operations) { - if(!telemetryFragment.Any() || !isValid(telemetryFragment)) + if(!telemetryFragment.Any() || !isValid(telemetryFragment, begin, end)) { - operations = Enumerable.Empty(); + operations = Enumerable.Empty(); return false; } - var operation = MakeOperation(idTelemetry, telemetryFragment); + var operation = MakeOperation(idTelemetry, telemetryFragment, begin, end); - operations = new List { operation }; + operations = new List { operation }; return true; } - private DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetryFragment) + private OperationDetectorResult MakeOperation(int idTelemetry, DetectableTelemetry[] telemetryFragment, int begin, int end) { - var pBegin = telemetryFragment.First(); - var pEnd = telemetryFragment.Last(); - var operation = new DetectedOperation + var pBegin = telemetryFragment[begin]; + var pEnd = telemetryFragment[end]; + var result = new OperationDetectorResult { - 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), + TelemetryBegin = begin, + TelemetryEnd = end, + 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, begin, end), + }, }; - return operation; - } - - public OperationDetector SetIsValidDelegate(Func isValid) - { - this.isValid = isValid; - return this; - } - - public OperationDetector SetCalcValueDelegate(Func calcValue) - { - this.calcValue = calcValue; - return this; + return result; } } } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDrilling.cs index 2686339d..32dc9201 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDrilling.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDrilling.cs @@ -8,20 +8,20 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors public OperationDrilling(int idOperation) :base(idOperation) { - isValid = (DetectableTelemetry[] telemetryFragment) => + isValid = (DetectableTelemetry[] fragment, int begin, int end) => { - var pBegin = telemetryFragment.First(); - var pEnd = telemetryFragment.Last(); + var pBegin = fragment[begin]; + var pEnd = fragment[end]; if (pBegin.WellDepth >= pEnd.WellDepth) return false; return true; }; - calcValue = (DetectableTelemetry[] telemetryFragment) => + calcValue = (DetectableTelemetry[] fragment, int begin, int end) => { - var pBegin = telemetryFragment.First(); - var pEnd = telemetryFragment.Last(); + var pBegin = fragment[begin]; + var pEnd = fragment[end]; 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 index 98291fec..be2968a3 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationSlipsTime.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationSlipsTime.cs @@ -8,20 +8,20 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors public OperationSlipsTime() : base(14) { - isValid = (DetectableTelemetry[] telemetryFragment) => + isValid = (DetectableTelemetry[] fragment, int begin, int end) => { - var pBegin = telemetryFragment.First(); - var pEnd = telemetryFragment.Last(); + var pBegin = fragment[begin]; + var pEnd = fragment[end]; if (Math.Abs((double)(pBegin.WellDepth - pEnd.WellDepth)) > 0.01) return false; return true; }; - calcValue = (DetectableTelemetry[] telemetryFragment) => + calcValue = (DetectableTelemetry[] fragment, int begin, int end) => { - var pBegin = telemetryFragment.First(); - var pEnd = telemetryFragment.Last(); + var pBegin = fragment[begin]; + var pEnd = fragment[end]; var result = (pEnd.DateTime - pBegin.DateTime).TotalHours; return result; }; diff --git a/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs b/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs index b0a2f97d..8302bc96 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionBackgroundService.cs @@ -14,30 +14,39 @@ namespace AsbCloudInfrastructure.Services.DetectOperations { public class OperationDetectionBackgroundService : BackgroundService { - private readonly int minStepLength = 3; - private readonly int minFragmentLength = 6; + private readonly int stepLength = 3; + private readonly int fragmentLength = 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 Func isBitLt0_03mToBottom = FragmentDetector.MakeInstantDelegate(d => + (double)(d.WellDepth - d.BitDepth) < 0.03d); + private static readonly Func isBitLt2_5mToBottom = FragmentDetector.MakeInstantDelegate(d => + (double)(d.WellDepth - d.BitDepth) < 2.5d); + 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()))) - ) - }; + { + new FragmentDetector("isBitLt2_5mToBottom", isBitLt2_5mToBottom, + new FragmentDetector("isBitLt0_03mToBottom", isBitLt0_03mToBottom, + new FragmentDetector("isPressureGt25", isPressureGt25, + new FragmentDetector("isRotorSpeedAvgGt5", isRotorSpeedAvgGt5, new OperationDrilling(2)), + new FragmentDetector("isRotorSpeedAvgLt5", isRotorSpeedAvgLt5, new OperationDrilling(3)))), + new FragmentDetector("isPressureLt15", isPressureLt15, + new FragmentDetector("isBlockPositionLt8", isBlockPositionLt8, + new FragmentDetector("isHookWeightLt20", isHookWeightLt20, new OperationSlipsTime())))), + }; public OperationDetectionBackgroundService(IConfiguration configuration) { @@ -147,48 +156,43 @@ namespace AsbCloudInfrastructure.Services.DetectOperations .Take(take) .ToArrayAsync(token); - if (data.Length < minFragmentLength) + if (data.Length < 2 * fragmentLength + stepLength) break; var isDetected = false; - var positionStart = 0; - while (data.Length > positionStart + minFragmentLength + minStepLength) + var positionBegin = 0; + var positionEnd = data.Length - fragmentLength; + + foreach (var detector in detectors) { - var telemetryFragment = data[positionStart..]; - var isDetected1 = false; - foreach (var detector in detectors) + if (detector is FragmentDetector fragmentDetector) { - if (detector is FragmentDetector fragmentDetector) - { - var minLengthToDetect = fragmentDetector.StepLength + fragmentDetector.FragmentLength; - if (telemetryFragment.Length < minLengthToDetect) - continue; + var minLengthToDetect = fragmentDetector.StepLength + fragmentDetector.FragmentLength; + if (data.Length < positionBegin + minLengthToDetect) + continue; - if (fragmentDetector.TryDetect(idTelemetry, data, out IEnumerable operations)) - { - isDetected = true; - isDetected1 = true; - detectedOperations.AddRange(operations); - startDate = operations.Last().DateEnd; - positionStart = 0; - data = data - .Where(d => d.DateTime > startDate) - .ToArray(); - break; - } + if (fragmentDetector.TryDetect(idTelemetry, data, positionBegin, positionEnd, out IEnumerable results)) + { + isDetected = true; + var operations = results.Select(r => r.Operation); + detectedOperations.AddRange(operations); + positionBegin = results.Max(r=>r.TelemetryEnd) + 1; + break; } } - - if (!isDetected1) - positionStart += minStepLength; } - if (!isDetected) + if (isDetected) { - if (data.Length < take) + startDate = detectedOperations.Max(o => o.DateEnd); + } + else + { + int i = positionEnd - (int)(data.Length * 0.8); + if (i < 0) break; - startDate = startDate.AddSeconds(0.95 * take); + startDate = data[i].DateTime; } }