forked from ddrilling/AsbCloudServer
Новые расчёты для автоматического определения операций
1. Поправел excel шаблон 2. Доработаны алгоритмы определения операций бурения 3. Небольшой рефакторинг DetectorAbstract, добавил метод для валидации 4. Закомментированы неиспользуемые детекторы. 5. Обновлена спецификация определения операций бурения 6. Добавлены тесты для определения операций бурения
This commit is contained in:
parent
afccdafebc
commit
8bbaca0d0c
Binary file not shown.
@ -14,7 +14,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations;
|
||||
|
||||
public class DetectedOperationExportService
|
||||
{
|
||||
private readonly DetectorAbstract[] detectors = { new DetectorDrilling(), new DetectorSlipsTime() };
|
||||
private readonly DetectorAbstract[] detectors = { new DetectorDrilling() };
|
||||
|
||||
private readonly IDictionary<int, string> domains = new Dictionary<int, string>
|
||||
{
|
||||
@ -122,10 +122,17 @@ public class DetectedOperationExportService
|
||||
row.Cell(columnDepthStart).Value = detectedOperations[i].DepthStart;
|
||||
row.Cell(columnDepthEnd).Value = detectedOperations[i].DepthEnd;
|
||||
row.Cell(columnDepth).Value = detectedOperations[i].DepthEnd - detectedOperations[i].DepthStart;
|
||||
row.Cell(columnIdReasonOfEnd).Value = detectedOperations[i].IdReasonOfEnd;
|
||||
row.Cell(columnIdReasonOfEnd).Value = detectedOperations[i].IdReasonOfEnd switch
|
||||
{
|
||||
0 => "Не определена",
|
||||
1 => "Не определено начало операции",
|
||||
101 => "Разница глубин забоя и положением долота",
|
||||
300 => "Низкое давление",
|
||||
_ => detectedOperations[i].IdReasonOfEnd
|
||||
};
|
||||
|
||||
var link =
|
||||
$"{domains[idDomain]}/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(3544).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=3600";
|
||||
$"{domains[idDomain]}/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(1800 * 0.9).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=1800";
|
||||
|
||||
row.Cell(columnDateStart).Value = dateStart;
|
||||
row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link));
|
||||
@ -191,10 +198,8 @@ public class DetectedOperationExportService
|
||||
var isDetected = false;
|
||||
var positionBegin = 0;
|
||||
var positionEnd = data.Length - gap;
|
||||
var step = 10;
|
||||
while (positionEnd > positionBegin)
|
||||
{
|
||||
step++;
|
||||
foreach (var detector in detectors)
|
||||
{
|
||||
if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result))
|
||||
@ -203,14 +208,11 @@ public class DetectedOperationExportService
|
||||
detectedOperations.Add(result!.Operation);
|
||||
lastDetectedOperation = result.Operation;
|
||||
isDetected = true;
|
||||
step = 1;
|
||||
positionBegin = result.TelemetryEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
if (step > 20)
|
||||
step = 10;
|
||||
positionBegin += step;
|
||||
positionBegin += 1;
|
||||
}
|
||||
|
||||
if (isDetected)
|
||||
|
@ -4,8 +4,7 @@ using System.Linq;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
internal abstract class DetectorAbstract
|
||||
public abstract class DetectorAbstract
|
||||
{
|
||||
private readonly int stepLength = 3;
|
||||
|
||||
@ -35,9 +34,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
|
||||
protected const int IdReasonOfEnd_Custom1 = 10_000;
|
||||
|
||||
public abstract Func<DetectableTelemetry[], int, int, int> GetIdOperation { get; }
|
||||
protected abstract Func<DetectableTelemetry[], int, int, int> GetIdOperation { get; }
|
||||
|
||||
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation, out OperationDetectorResult? result)
|
||||
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation,
|
||||
out OperationDetectorResult? result)
|
||||
{
|
||||
// Проверка соответствия критерию начала операции
|
||||
if (DetectBegin(telemetry, begin, previousOperation))
|
||||
@ -53,29 +53,30 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
|
||||
idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation);
|
||||
|
||||
if(idReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo &&
|
||||
!IsValidByWellDepthDoesNotChange(telemetry, begin, positionEnd))
|
||||
break;
|
||||
|
||||
if (idReasonOfEnd != IdReasonOfEnd_NotDetected)
|
||||
break;
|
||||
}
|
||||
|
||||
result = null;
|
||||
result = MakeOperation(idTelemetry, telemetry, begin, positionEnd, idReasonOfEnd);
|
||||
return true;
|
||||
return result is not null;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) =>
|
||||
operationDetectorResult.Operation.IdReasonOfEnd != IdReasonOfEnd_NotDetected;
|
||||
|
||||
protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation);
|
||||
|
||||
protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
=> DetectBegin(telemetry, position, previousOperation)
|
||||
? IdReasonOfEnd_NotDetected
|
||||
: IdReasonOfEnd_NotDetectBegin;
|
||||
|
||||
private OperationDetectorResult MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, int idReasonOfEnd)
|
||||
private OperationDetectorResult? MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end,
|
||||
int idReasonOfEnd)
|
||||
{
|
||||
var pBegin = telemetry[begin];
|
||||
var pEnd = telemetry[end];
|
||||
@ -96,10 +97,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
IdReasonOfEnd = idReasonOfEnd,
|
||||
},
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract bool IsValid(DetectableTelemetry[] telemetry, int begin, int end);
|
||||
return !IsValidOperationDetectorResult(result) ? null : result;
|
||||
}
|
||||
|
||||
protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end);
|
||||
|
||||
@ -210,6 +210,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
max = itemValue;
|
||||
sum += itemValue;
|
||||
}
|
||||
|
||||
return (min, max, sum, end - begin);
|
||||
}
|
||||
|
||||
@ -267,6 +268,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
if (max - min > deviation)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -302,6 +304,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
if (max - min > deviation)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -323,6 +326,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
if (Math.Abs(beginPointValue - itemValue) > deviation)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -344,10 +348,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
if (itemValue - beginPointValue > deviation)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,68 +1,66 @@
|
||||
using System;
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Проработка перед наращиванием
|
||||
/// </summary>
|
||||
internal class DetectorDevelopment : DetectorAbstract
|
||||
{
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
|
||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _)
|
||||
=> WellOperationCategory.IdDevelopment;
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
if (previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime)
|
||||
return false;
|
||||
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta < 0.03d || delta > 30)
|
||||
return false;
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return false;
|
||||
|
||||
if (point0.BlockPosition > 2.5)
|
||||
return false;
|
||||
|
||||
if (point0.RotorSpeed < 10)
|
||||
return false;
|
||||
|
||||
if (!ContainsDeviationApprox(telemetry, d => d.BlockPosition, position, 60, 0.03))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta < 0.03d || delta > 30)
|
||||
return IdReasonOfEnd_DeltaDepthOutOfRange;
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return IdReasonOfEnd_PressureIsLo;
|
||||
|
||||
if (point0.BlockPosition > 31)
|
||||
return IdReasonOfEnd_BlockPositionIsHi;
|
||||
|
||||
if (point0.RotorSpeed < 10)
|
||||
return IdReasonOfEnd_RotorSpeedIsLo;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using System;
|
||||
// using AsbCloudDb.Model;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Проработка перед наращиванием
|
||||
// /// </summary>
|
||||
// internal class DetectorDevelopment : DetectorAbstract
|
||||
// {
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcDeltaMinutes(telemetry, begin, end);
|
||||
//
|
||||
// public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _)
|
||||
// => WellOperationCategory.IdDevelopment;
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// if (previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime)
|
||||
// return false;
|
||||
//
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta < 0.03d || delta > 30)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.BlockPosition > 2.5)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.RotorSpeed < 10)
|
||||
// return false;
|
||||
//
|
||||
// if (!ContainsDeviationApprox(telemetry, d => d.BlockPosition, position, 60, 0.03))
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta < 0.03d || delta > 30)
|
||||
// return IdReasonOfEnd_DeltaDepthOutOfRange;
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return IdReasonOfEnd_PressureIsLo;
|
||||
//
|
||||
// if (point0.BlockPosition > 31)
|
||||
// return IdReasonOfEnd_BlockPositionIsHi;
|
||||
//
|
||||
// if (point0.RotorSpeed < 10)
|
||||
// return IdReasonOfEnd_RotorSpeedIsLo;
|
||||
//
|
||||
// return IdReasonOfEnd_NotDetected;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
@ -4,9 +4,9 @@ using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||
|
||||
internal class DetectorDrilling : DetectorAbstract
|
||||
public class DetectorDrilling : DetectorAbstract
|
||||
{
|
||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => DefineDrillingOperation;
|
||||
protected override Func<DetectableTelemetry[], int, int, int> GetIdOperation => DefineDrillingOperation;
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
@ -18,9 +18,6 @@ internal class DetectorDrilling : DetectorAbstract
|
||||
if (point0.Pressure < 25)
|
||||
return false;
|
||||
|
||||
if (point0.RotorSpeed < 5)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -38,25 +35,37 @@ internal class DetectorDrilling : DetectorAbstract
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthIncreasing(telemetry, begin, end);
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcRop(telemetry, begin, end);
|
||||
|
||||
protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) =>
|
||||
operationDetectorResult.Operation.IdReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo &&
|
||||
Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01;
|
||||
|
||||
private static int DefineDrillingOperation(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
{
|
||||
const int idSlideWithOscillation = 12000;
|
||||
|
||||
var telemetryRange = telemetry[begin.. end];
|
||||
var telemetryRange = telemetry[begin.. end]
|
||||
.OrderBy(x => x.DateTime).ToList();
|
||||
|
||||
for (var i = telemetryRange.Count - 1; i >= 0 && telemetryRange.Count > 1; i--)
|
||||
{
|
||||
if (Math.Abs(telemetryRange[i].WellDepth - telemetryRange[i - 1].WellDepth) < 0.001d)
|
||||
{
|
||||
telemetryRange.RemoveAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed);
|
||||
|
||||
if (avgRotorSpeed < 10)
|
||||
return WellOperationCategory.IdSlide;
|
||||
|
||||
var despersion = telemetryRange
|
||||
.Average(t => Math.Pow((t.RotorSpeed - avgRotorSpeed) / avgRotorSpeed, 2));
|
||||
var despersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed/avgRotorSpeed - 1, 2));
|
||||
|
||||
return despersion < 0.2d ? WellOperationCategory.IdRotor : idSlideWithOscillation;
|
||||
}
|
||||
|
@ -1,39 +1,39 @@
|
||||
using System;
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
internal class DetectorSlipsTime : DetectorAbstract
|
||||
{
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
|
||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime;
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 2.5d)
|
||||
return false;
|
||||
|
||||
if (point0.Pressure > 15)
|
||||
return false;
|
||||
|
||||
if (point0.BlockPosition > 8)
|
||||
return false;
|
||||
|
||||
if (point0.HookWeight > 20)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using System;
|
||||
// using AsbCloudDb.Model;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
// internal class DetectorSlipsTime : DetectorAbstract
|
||||
// {
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcDeltaMinutes(telemetry, begin, end);
|
||||
//
|
||||
// public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime;
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 2.5d)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.Pressure > 15)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.BlockPosition > 8)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.HookWeight > 20)
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
@ -1,29 +1,27 @@
|
||||
Метод определения бурения
|
||||
# Алгоритм определения бурения в роторе, слайде, слайде с осцилляцией
|
||||
|
||||
## Метод определения операции бурения
|
||||
|
||||
Признак начала операции =
|
||||
|
||||
расстояние от долота до забоя < 0.03м И
|
||||
|
||||
давление > 25атм
|
||||
(расстояние от долота до забоя < 0.03м) И
|
||||
(давление > 25атм)
|
||||
|
||||
Признак окончания операции =
|
||||
(расстояние от долота до забоя > 0.03м) ИЛИ
|
||||
(давление < 25атм)
|
||||
|
||||
расстояние от долота до забоя > 0.03м ИЛИ
|
||||
## Валидация
|
||||
Для точного определения операции бурения, необходимо убрать диапазон в которых сработал признак окончания операции и не менялась глубина:
|
||||
Определили точку окончания операции исходя из Признак окончания операции.
|
||||
Определяем временной интервал, когда не менялась глубина (т.е. время шло, а глубина была неизменна)
|
||||
Определив начальную точку и точку окончания операции
|
||||
Исключаем этот интервал из операции.
|
||||
|
||||
давление < 25атм
|
||||
## Метод определения бурения в слайде
|
||||
Необходимо рассчитать средние обороты ротора за всю операцию бурения.
|
||||
Если среднее арифметическое больше константы (10 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде.
|
||||
|
||||
Находим границы
|
||||
|
||||
После того когда мы нашли границы, мы должны определить операцию, тогда мы смотрим на забой точки окончания операций сравниваем с забоем точками начала операций:
|
||||
|
||||
Если они равны друг другу, то мы эту операцию дальше не обрабатываем, а выбрасываем.
|
||||
|
||||
Если они не равны, то у нас произошло увеличение забоя, значит эта операция бурения.
|
||||
|
||||
Дальше мы определяем как мы бурили в роторе или слайде, для этого нам необходимо рассчитать среднюю скорость(среднее арифметическое) за всю операцию бурения . Если среднее арифметическое больше константы (10 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде.
|
||||
|
||||
Если бурение в роторе, то мы считаем только дисперсию нормированных оборотов ротора(по среднему значению). (Так как это может быть бурение в слайде с осцилляцией и выглядеть как бурение в роторе):
|
||||
|
||||
Если полученное значение меньше константы(0,2), то мы подтвердили что бурение в роторе.
|
||||
|
||||
Если полученное значение больше константы, то это бурение в слайде с осцилляцией.
|
||||
## Метод определения бурения в роторе, слайде с осцилляцией
|
||||
Необходимо рассчитать десперсию нормированных оборотов ротора по(по среднему значению)
|
||||
1. Если полученное значение больше константы(0,2), то мы подтвердили что бурение в роторе.
|
||||
2. Если полученное значение меньше константы, то это бурение в слайде с осцилляцией.
|
@ -16,11 +16,11 @@ public class WorkOperationDetection: Work
|
||||
{
|
||||
private static readonly DetectorAbstract[] detectors = new DetectorAbstract[]
|
||||
{
|
||||
new DetectorDrilling()
|
||||
// new DetectorRotor(),
|
||||
// new DetectorSlide(),
|
||||
//new DetectorDevelopment(),
|
||||
//new DetectorTemplating(),
|
||||
new DetectorSlipsTime(),
|
||||
//new DetectorStaticSurveying(),
|
||||
//new DetectorFlashingBeforeConnection(),
|
||||
//new DetectorFlashing(),
|
||||
@ -116,7 +116,6 @@ public class WorkOperationDetection: Work
|
||||
{
|
||||
var data = await query
|
||||
.Where(d => d.DateTime > startDate)
|
||||
.Take(take)
|
||||
.ToArrayAsync(token);
|
||||
|
||||
if (data.Length < gap)
|
||||
@ -125,25 +124,21 @@ public class WorkOperationDetection: Work
|
||||
var isDetected = false;
|
||||
var positionBegin = 0;
|
||||
var positionEnd = data.Length - gap;
|
||||
var step = 10;
|
||||
while (positionEnd > positionBegin)
|
||||
{
|
||||
step ++;
|
||||
for (int i = 0; i < detectors.Length; i++)
|
||||
{
|
||||
if (detectors[i].TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out OperationDetectorResult? result))
|
||||
foreach (var detector in detectors)
|
||||
{
|
||||
if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result))
|
||||
continue;
|
||||
|
||||
detectedOperations.Add(result!.Operation);
|
||||
lastDetectedOperation = result.Operation;
|
||||
isDetected = true;
|
||||
step = 1;
|
||||
positionBegin = result.TelemetryEnd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (step > 20)
|
||||
step = 10;
|
||||
positionBegin += step;
|
||||
|
||||
positionBegin += 1;
|
||||
}
|
||||
|
||||
if (isDetected)
|
||||
|
@ -0,0 +1,290 @@
|
||||
using System.Collections.Generic;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.DetectOperations;
|
||||
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.Tests.Services.DetectedOperations.Detectors;
|
||||
|
||||
public class DetectorDrillingTests : DetectorDrilling
|
||||
{
|
||||
private const int idSlide = 5002;
|
||||
private const int idRotor = 5003;
|
||||
private const int idSlideWithOscillation = 12000;
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TelemetryRangeDrillingRotor))]
|
||||
public void DefineDrillingOperation_ShouldReturn_DrillingRotor(DetectableTelemetry[] telemetryRange)
|
||||
{
|
||||
//act
|
||||
var result = GetIdOperation.Invoke(telemetryRange, 0, telemetryRange.Length);
|
||||
|
||||
//assert
|
||||
Assert.Equal(idRotor, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TelemetryRangeDrillingSlide))]
|
||||
public void DefineDrillingOperation_ShouldReturn_DrillingSlide(DetectableTelemetry[] telemetryRange)
|
||||
{
|
||||
//act
|
||||
var result = GetIdOperation.Invoke(telemetryRange, 0, telemetryRange.Length);
|
||||
|
||||
//assert
|
||||
Assert.Equal(idSlide, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TelemetryRangeDrillingSlideWithOscillation))]
|
||||
public void DefineDrillingOperation_ShouldReturn_DrillingSlideWithOscillation(DetectableTelemetry[] telemetryRange)
|
||||
{
|
||||
//act
|
||||
var result = GetIdOperation.Invoke(telemetryRange, 0, telemetryRange.Length);
|
||||
|
||||
//assert
|
||||
Assert.Equal(idSlideWithOscillation, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsValidOperationDetectorResult_ShouldReturn_True()
|
||||
{
|
||||
//arrange
|
||||
var operationDetectorResult = new OperationDetectorResult
|
||||
{
|
||||
Operation = new DetectedOperation
|
||||
{
|
||||
IdReasonOfEnd = IdReasonOfEnd_PressureIsLo,
|
||||
DepthStart = 5000,
|
||||
DepthEnd = 6000
|
||||
}
|
||||
};
|
||||
|
||||
//act
|
||||
var result = IsValidOperationDetectorResult(operationDetectorResult);
|
||||
|
||||
//assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsValidOperationDetectorResult_ShouldReturn_False()
|
||||
{
|
||||
//arrange
|
||||
var operationDetectorResult = new OperationDetectorResult
|
||||
{
|
||||
Operation = new DetectedOperation
|
||||
{
|
||||
IdReasonOfEnd = IdReasonOfEnd_PressureIsLo,
|
||||
DepthStart = 5000,
|
||||
DepthEnd = 5000
|
||||
}
|
||||
};
|
||||
|
||||
//act
|
||||
var result = IsValidOperationDetectorResult(operationDetectorResult);
|
||||
|
||||
//assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> TelemetryRangeDrillingRotor()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
new[]
|
||||
{
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 4.187f,
|
||||
Pressure = 27.815952f,
|
||||
HookWeight = 34.221367f,
|
||||
BlockPosition = 24.388f,
|
||||
BitDepth = 4.187f,
|
||||
RotorSpeed = 40.3f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 4.232f,
|
||||
Pressure = 28.080372f,
|
||||
HookWeight = 34.162174f,
|
||||
BlockPosition = 24.343f,
|
||||
BitDepth = 4.232f,
|
||||
RotorSpeed = 40.3f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 4.277f,
|
||||
Pressure = 29.047901f,
|
||||
HookWeight = 33.688717f,
|
||||
BlockPosition = 24.298f,
|
||||
BitDepth = 24.298f,
|
||||
RotorSpeed = 40.3f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 4.309f,
|
||||
Pressure = 29.574032f,
|
||||
HookWeight = 33.692104f,
|
||||
BlockPosition = 24.266f,
|
||||
BitDepth = 4.309f,
|
||||
RotorSpeed = 40.4f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 4.324f,
|
||||
Pressure = 24.007977f,
|
||||
HookWeight = 34.838448f,
|
||||
BlockPosition = 24.251f,
|
||||
BitDepth = 4.324f,
|
||||
RotorSpeed = 40.5f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 4.324f,
|
||||
Pressure = 24.04114f,
|
||||
HookWeight = 34.423424f,
|
||||
BlockPosition = 24.252f,
|
||||
BitDepth = 4.323f,
|
||||
RotorSpeed = 40.3f
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> TelemetryRangeDrillingSlide()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
new[]
|
||||
{
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 447.276001f,
|
||||
Pressure = 26.619421f,
|
||||
HookWeight = 40.9143829f,
|
||||
BlockPosition = 4.559f,
|
||||
BitDepth = 477.265991f,
|
||||
RotorSpeed = 0
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 477.289f,
|
||||
Pressure = 28.716f,
|
||||
HookWeight = 38.27f,
|
||||
BlockPosition = 4.5f,
|
||||
BitDepth = 477.289f,
|
||||
RotorSpeed = 0.1f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
WellDepth = 477.30899f,
|
||||
Pressure = 33.953495f,
|
||||
HookWeight = 38.27f,
|
||||
BlockPosition = 4.5359997f,
|
||||
BitDepth = 477.289001f,
|
||||
RotorSpeed = 0.1f
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> TelemetryRangeDrillingSlideWithOscillation()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
new[]
|
||||
{
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.306f,
|
||||
Pressure = 53.731934f,
|
||||
HookWeight = 41.049942f,
|
||||
BlockPosition = 28.666f,
|
||||
BitDepth = 415.293f,
|
||||
RotorSpeed = 0.3f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.311f,
|
||||
Pressure = 57.660595f,
|
||||
HookWeight = 40.898712f,
|
||||
BlockPosition = 28.648f,
|
||||
BitDepth = 415.311f,
|
||||
RotorSpeed = 0.2f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.326f,
|
||||
Pressure = 59.211086f,
|
||||
HookWeight = 40.882797f,
|
||||
BlockPosition = 28.633f,
|
||||
BitDepth = 415.326f,
|
||||
RotorSpeed = 0.1f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.344f,
|
||||
Pressure = 59.484406f,
|
||||
HookWeight = 40.91972f,
|
||||
BlockPosition = 28.615f,
|
||||
BitDepth = 415.344f,
|
||||
RotorSpeed = 0.2f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.364f,
|
||||
Pressure = 60.739918f,
|
||||
HookWeight = 40.795666f,
|
||||
BlockPosition = 28.595f,
|
||||
BitDepth = 415.364f,
|
||||
RotorSpeed = 4.5f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.378f,
|
||||
Pressure = 62.528984f,
|
||||
HookWeight = 40.52114f,
|
||||
BlockPosition = 28.581f,
|
||||
BitDepth = 415.378f,
|
||||
RotorSpeed = 22.6f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.392f,
|
||||
Pressure = 67.0039f,
|
||||
HookWeight = 38.878895f,
|
||||
BlockPosition = 28.569f,
|
||||
BitDepth = 415.39f,
|
||||
RotorSpeed = 50f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.392f,
|
||||
Pressure = 65.72418f,
|
||||
HookWeight = 42.53173f,
|
||||
BlockPosition = 28.622f,
|
||||
BitDepth = 415.337f,
|
||||
RotorSpeed = 93f
|
||||
},
|
||||
new DetectableTelemetry
|
||||
{
|
||||
IdUser = 1,
|
||||
WellDepth = 415.392f,
|
||||
Pressure = 56.82195f,
|
||||
HookWeight = 43.15844f,
|
||||
BlockPosition = 28.704f,
|
||||
BitDepth = 415.255f,
|
||||
RotorSpeed = 71.5f
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user