diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs
index aeb18fe2..50d6dd14 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs
@@ -4,14 +4,53 @@ namespace AsbCloudInfrastructure.Services.DetectOperations;
public class DetectableTelemetry
{
+ ///
+ /// Дата начала
+ ///
public DateTimeOffset DateTime { get; set; }
+
+ ///
+ /// Режим
+ ///
public int Mode { get; set; }
+
+ ///
+ /// Ключ пользователя
+ ///
public int? IdUser { get; set; }
+
+ ///
+ /// Глубина забоя
+ ///
public float WellDepth { get; set; }
+
+ ///
+ /// Давление
+ ///
public float Pressure { get; set; }
+
+ ///
+ /// Вес на крюке
+ ///
public float HookWeight { get; set; }
+
+ ///
+ /// Положение талевого блока
+ ///
public float BlockPosition { get; set; }
+
+ ///
+ /// Глубина долота
+ ///
public float BitDepth { get; set; }
+
+ ///
+ /// Обороты ротора
+ ///
public float RotorSpeed { get; set; }
+
+ ///
+ /// Осевая нагрузка
+ ///
public float AxialLoad { get; set; }
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs
index b53b1cd0..16eea6d7 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs
@@ -25,14 +25,15 @@ public class DetectedOperationService : IDetectedOperationService
private static readonly DetectorAbstract[] detectors = {
new DetectorDrilling(),
- new DetectorSlipsTime()
+ new DetectorSlipsTime(),
+ new DetectorFlashing(),
};
-
+
public DetectedOperationService(
IDetectedOperationRepository operationRepository,
IWellOperationCategoryRepository wellOperationCategoryRepository,
IWellService wellService,
- IRepositoryWellRelated operationValueRepository,
+ IRepositoryWellRelated operationValueRepository,
IScheduleRepository scheduleRepository,
ITelemetryDataSaubService telemetryDataSaubService)
{
@@ -86,9 +87,9 @@ public class DetectedOperationService : IDetectedOperationService
if (well?.IdTelemetry is null)
return Enumerable.Empty();
- var request = new DetectedOperationByTelemetryRequest()
- {
- IdTelemetry = well.IdTelemetry.Value
+ var request = new DetectedOperationByTelemetryRequest()
+ {
+ IdTelemetry = well.IdTelemetry.Value
};
var operations = await operationRepository.Get(request, token);
@@ -111,7 +112,7 @@ public class DetectedOperationService : IDetectedOperationService
if (!operations.Any())
return Enumerable.Empty();
-
+
var dtos = operations
.GroupBy(o => (o.IdCategory, o.OperationCategory.Name))
.OrderBy(g => g.Key)
@@ -135,39 +136,39 @@ public class DetectedOperationService : IDetectedOperationService
public async Task> DetectOperationsAsync(int idTelemetry, DateTimeOffset? beginDate, CancellationToken token)
{
const int take = 4 * 86_400;
-
+
var detectedOperations = new List();
DetectedOperationDto? lastDetectedOperation = null;
const int minOperationLength = 5;
const int maxDetectorsInterpolationFrameLength = 30;
const int gap = maxDetectorsInterpolationFrameLength + minOperationLength;
-
+
while (true)
{
var request = new TelemetryDataRequest
{
GeDate = beginDate,
Take = take,
- Order = 0
+ Order = 0
};
-
+
var detectableTelemetries = (await telemetryDataSaubService.GetByTelemetryAsync(idTelemetry, request, token))
.Where(t => t.BlockPosition >= 0)
.Select(t => new DetectableTelemetry
- {
- DateTime = t.DateTime,
- IdUser = t.IdUser,
- Mode = t.Mode,
- WellDepth = t.WellDepth,
- Pressure = t.Pressure,
- HookWeight = t.HookWeight,
- BlockPosition = t.BlockPosition,
- BitDepth = t.BitDepth,
- RotorSpeed = t.RotorSpeed,
- AxialLoad = t.AxialLoad,
- }).ToArray();
-
- if (detectableTelemetries.Length < gap)
+ {
+ DateTime = t.DateTime,
+ IdUser = t.IdUser,
+ Mode = t.Mode,
+ WellDepth = t.WellDepth,
+ Pressure = t.Pressure,
+ HookWeight = t.HookWeight,
+ BlockPosition = t.BlockPosition,
+ BitDepth = t.BitDepth,
+ RotorSpeed = t.RotorSpeed,
+ AxialLoad = t.AxialLoad,
+ }).ToArray();
+
+ if (detectableTelemetries.Length <= gap)
break;
var isDetected = false;
@@ -179,14 +180,14 @@ public class DetectedOperationService : IDetectedOperationService
{
if (!detector.TryDetect(idTelemetry, detectableTelemetries, positionBegin, positionEnd, lastDetectedOperation, out var result))
continue;
-
+
detectedOperations.Add(result!.Operation);
lastDetectedOperation = result.Operation;
isDetected = true;
positionBegin = result.TelemetryEnd;
break;
}
-
+
positionBegin += 1;
}
@@ -263,7 +264,7 @@ public class DetectedOperationService : IDetectedOperationService
dto.OperationValue = operationValues.FirstOrDefault(v => v.IdOperationCategory == dto.IdCategory
&& v.DepthStart <= dto.DepthStart
&& v.DepthEnd > dto.DepthStart);
-
+
var dateStart = dto.DateStart;
var timeStart = new TimeDto(dateStart);
var driller = schedules.FirstOrDefault(s =>
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs
index 559e1dc4..44b47554 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs
@@ -32,6 +32,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
protected const int IdReasonOfEnd_ChangeBithDepthAndAxiloadLessHookWeight = 700;
+ protected const int IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo = 800;
+
+ protected const int IdReasonOfEnd_BithDepthIsLo = 900;
+
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperationDto? previousOperation,
out OperationDetectorResult? result)
{
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs
index ac93fd45..e6d8a0dd 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs
@@ -1,59 +1,67 @@
-// using AsbCloudDb.Model;
-//
-// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
-// {
-//
-// ///
-// /// Промывка
-// ///
-// internal class DetectorFlashing : DetectorAbstract
-// {
-// public DetectorFlashing()
-// : base(WellOperationCategory.IdFlashing)
-// { }
-//
-// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
-// => CalcDeltaMinutes(telemetry, begin, end);
-//
-// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
-// {
-// if (!((previousOperation?.IdCategory == WellOperationCategory.IdRotor) ||
-// (previousOperation?.IdCategory == WellOperationCategory.IdSlide)))
-// return false;
-//
-// var point0 = telemetry[position];
-// var delta = point0.WellDepth - point0.BitDepth;
-// if (delta > 0.05d)
-// return false;
-//
-// if (point0.Pressure < 15)
-// return false;
-//
-// if (point0.BlockPosition < 3)
-// return false;
-//
-// if (ContainsDeviationApprox(telemetry, t => t.WellDepth, position, 150, 0.0001))
-// 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 )
-// && (point0.Pressure > 15)
-// && ContainsDeviationApprox(telemetry, t=>t.BlockPosition, position, 60, 0.03))
-// return IdReasonOfEnd_Custom1;
-//
-// return IdReasonOfEnd_NotDetected;
-// }
-//
-// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
-// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
-// }
-//
-//
-// }
-//
+using AsbCloudApp.Data.DetectedOperation;
+using AsbCloudDb.Model;
+using System;
+using System.Collections.Generic;
+
+namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
+{
+
+ ///
+ /// Промывка
+ ///
+ public class DetectorFlashing : DetectorAbstract
+ {
+
+ protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
+ => CalcDeltaMinutes(telemetry, begin, end);
+
+ protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
+ {
+
+ var currentPoint = telemetry[position];
+ if (currentPoint.Pressure < 10)
+ return false;
+
+ var delta = currentPoint.WellDepth - currentPoint.BitDepth;
+ if (delta < 0.03d)
+ return false;
+
+ if (currentPoint.RotorSpeed > 8)
+ return false;
+
+ var nextIndexPoint = telemetry.Length <= position ? position : position + 1;
+ var nextPoint = telemetry[nextIndexPoint];
+ if (Math.Abs(currentPoint.WellDepth - nextPoint.WellDepth) > 0)
+ return false;
+
+ if (currentPoint.BitDepth < 150)
+ return false;
+
+ return true;
+
+ }
+
+ protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
+ {
+ var currentPoint = telemetry[position];
+
+ if (currentPoint.Pressure < 10)
+ return IdReasonOfEnd_PressureIsLo;
+ if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.03d)
+ return IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo;
+ if (currentPoint.RotorSpeed > 8)
+ return IdReasonOfEnd_RotorSpeedIsHi;
+ if (currentPoint.BitDepth < 150)
+ return IdReasonOfEnd_BithDepthIsLo;
+ return IdReasonOfEnd_NotDetected;
+ }
+
+ protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry,
+ int begin,
+ int end)
+ {
+ return (WellOperationCategory.IdFlashing, new Dictionary());
+ }
+ }
+}
+
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Промывка.md b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Промывка.md
index 9a57a784..760d28cb 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Промывка.md
+++ b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Промывка.md
@@ -2,25 +2,26 @@
## Описание
-Промывка – операция, во время которой после добуривания очередной трубы происходит снижение осевой нагрузки и дифференциального давления, талевый блок остается условно неподвижным.
+Промывка – операция, во время которой давление условно постоянное, а вращение колонны отсутствует, талевый блок при этом может быть как в движении, так и статичным.
-Проработка перед наращиванием определяется как время между:
-- окончанием операции бурения (ротор/ слайд/ ручное бурение)
-- началом операции проработки/ шаблонировки перед наращивании
+Промывка определяется как время между:
+- окончанием операции бурения или выходом на режим буровых насосов (рост давления)
+- началом операции проработки/шаблонировки перед наращиванием или остановкой буровых насосов (снижение давления).
## Метод определения
Признак начала операции =
- ( предыдущая операция == бурение в роторе или слайде)
- ( расстояние от долота до забоя < 0,05м ) И
- ( давление > 15 атм ) И
- ( положение блока > 3м ) И
- ( глубина забоя изменяется менее чем на 0,0001м в течении 150 сек)
-
+ ( давление >= 10 атм ) И
+ ( обороты ротора <= 8 об/мин) И
+ ( расстояние от долота до забоя >= 0.03 м) И
+ ( глубина забоя не изменяется) И
+ ( глубина долота >= 150 м);
+
Признак окончания операции =
- ( расстояние от долота до забоя > 0.03м ) И
- ( давление > 15 атм ) И
- ( высота блока изменяется больше чем на 0.03м в течении 60 сек с начала операции);
+ ( давление < 10 атм ) ИЛИ
+ ( расстояние от долота до забоя < 0.03 м ) ИЛИ
+ ( обороты ротора > 8 об/мин) ИЛИ
+ ( глубина долота < 150 м);
## Ключевой параметр
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs
index f562e744..d001471e 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs
@@ -44,7 +44,7 @@ public class WorkOperationDetection: Work
var beginDate = lastDetectedDates.TryGetValue(telemetryId, out var date) ? date : (DateTimeOffset?)null;
- onProgressCallback($"Start detecting telemetry: {telemetryId} from {beginDate}", i++ / telemetryIds.Length);
+ onProgressCallback($"Start detecting telemetry: {telemetryId} from {beginDate}", i / telemetryIds.Length);
var detectedOperations = await detectedOperationService.DetectOperationsAsync(telemetryId, beginDate, token);
if (detectedOperations.Any())
diff --git a/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorFlashingTests.cs b/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorFlashingTests.cs
new file mode 100644
index 00000000..43203db9
--- /dev/null
+++ b/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorFlashingTests.cs
@@ -0,0 +1,110 @@
+using AsbCloudDb.Model;
+using AsbCloudInfrastructure.Services.DetectOperations;
+using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
+using Xunit;
+
+namespace AsbCloudWebApi.Tests.Services.DetectedOperations.Detectors;
+
+///
+/// Тестирование автоопределения операции "Промывка"
+///
+public class DetectorFlashingTests : DetectorFlashing
+{
+ private readonly DetectorFlashing detector = new();
+
+ ///
+ /// Операция, попадающая под автоопределение операции промывки
+ ///
+ private readonly DetectableTelemetry telemetry = new()
+ {
+ Pressure = 21,
+ WellDepth = 152,
+ BitDepth = 151,
+ RotorSpeed = 8,
+ DateTime = System.DateTimeOffset.Now
+ };
+
+
+ [Fact]
+ public void DetectOperation_find_startOperation_notFind_endOperation()
+ {
+ //arrange
+ var point0 = telemetry.Copy();
+ var point1 = telemetry.Copy();
+ point1.DateTime = System.DateTimeOffset.Now.AddMinutes(5);
+
+ var telemetries = new[] { point0, point1 };
+
+ //act
+ var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);
+
+ //assert
+ Assert.True(isDetectOperation);
+ Assert.NotNull(result);
+ Assert.Equal(WellOperationCategory.IdFlashing, result.Operation.IdCategory);
+ Assert.Equal(IdReasonOfEnd_NotDetected, result.Operation.ExtraData["IdReasonOfEnd"]);
+ }
+
+ [Fact]
+ public void DetectOperation_with_BitDepth_LE_150_is_fail()
+ {
+ //arrange
+ var point0 = telemetry.Copy();
+ point0.BitDepth = 150;
+
+ var point1 = telemetry.Copy();
+
+ var telemetries = new[] { point0, point1 };
+
+ //act
+
+ var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);
+
+ //assert
+ Assert.False(isDetectOperation);
+ Assert.NotNull(result);
+ Assert.Equal(WellOperationCategory.IdFlashing, result.Operation.IdCategory);
+ Assert.Equal(IdReasonOfEnd_NotDetected, result.Operation.ExtraData["IdReasonOfEnd"]);
+ }
+
+
+ [Fact]
+ public void DetectOperation_with_DeltaWellDepth_NotEqual_0_is_fail()
+ {
+ //arrange
+ var point0 = telemetry.Copy();
+ var point1 = telemetry.Copy();
+ point1.WellDepth = point0.WellDepth + 10;
+
+ var telemetries = new[] { point0, point1 };
+
+ //act
+ var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);
+
+ //assert
+ Assert.False(isDetectOperation);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void DetectOperations_Begin_And_End_by_Pressure_Less_10_is_success()
+ {
+ //arrange
+ var point0 = telemetry.Copy();
+ var point1 = telemetry.Copy();
+ point1.Pressure = 9;
+ point1.BitDepth = 140.0001f;
+ point1.RotorSpeed = 10;
+
+ var telemetries = new[] { point0, point1 };
+
+ //act
+ var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);
+
+ //assert
+ Assert.False(isDetectOperation);
+ Assert.NotNull(result);
+ Assert.Equal(WellOperationCategory.IdFlashing, result.Operation.IdCategory);
+ Assert.Equal(IdReasonOfEnd_PressureIsLo, result.Operation.ExtraData["IdReasonOfEnd"]);
+ }
+}
\ No newline at end of file