forked from ddrilling/AsbCloudServer
Operation detection algorithm adapt.
This commit is contained in:
parent
93c293a11c
commit
69ac4c74d5
6083
AsbCloudDb/Migrations/20220629122922_Add_new_well_operations_17_18.Designer.cs
generated
Normal file
6083
AsbCloudDb/Migrations/20220629122922_Add_new_well_operations_17_18.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Migrations
|
||||||
|
{
|
||||||
|
public partial class Add_new_well_operations_17_18 : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "t_well_operation_category",
|
||||||
|
columns: new[] { "id", "code", "name" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ 18, 0, "Проработка перед наращиванием" },
|
||||||
|
{ 19, 0, "Шаблонировка перед наращиванием" }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_well_operation_category",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 18);
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_well_operation_category",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 19);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
@ -52,7 +51,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnType("double precision")
|
.HasColumnType("double precision")
|
||||||
.HasColumnName("longitude");
|
.HasColumnName("longitude");
|
||||||
|
|
||||||
b.Property<SimpleTimezone>("Timezone")
|
b.Property<string>("Timezone")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("timezone")
|
.HasColumnName("timezone")
|
||||||
.HasComment("Смещение часового пояса от UTC");
|
.HasComment("Смещение часового пояса от UTC");
|
||||||
@ -149,7 +148,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnName("start_date")
|
.HasColumnName("start_date")
|
||||||
.HasComment("Дата отчёта");
|
.HasComment("Дата отчёта");
|
||||||
|
|
||||||
b.Property<DailyReportInfo>("Info")
|
b.Property<string>("Info")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("info")
|
.HasColumnName("info")
|
||||||
.HasComment("Список параметров для отчёта");
|
.HasComment("Список параметров для отчёта");
|
||||||
@ -184,7 +183,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnType("double precision")
|
.HasColumnType("double precision")
|
||||||
.HasColumnName("longitude");
|
.HasColumnName("longitude");
|
||||||
|
|
||||||
b.Property<SimpleTimezone>("Timezone")
|
b.Property<string>("Timezone")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("timezone")
|
.HasColumnName("timezone")
|
||||||
.HasComment("Смещение часового пояса от UTC");
|
.HasComment("Смещение часового пояса от UTC");
|
||||||
@ -704,7 +703,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnName("name")
|
.HasColumnName("name")
|
||||||
.HasComment("Название файла");
|
.HasComment("Название файла");
|
||||||
|
|
||||||
b.Property<FilePublishInfo>("PublishInfo")
|
b.Property<string>("PublishInfo")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("publish_info")
|
.HasColumnName("publish_info")
|
||||||
.HasComment("Информация о файле в облаке");
|
.HasComment("Информация о файле в облаке");
|
||||||
@ -791,7 +790,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
b.Property<RawData>("Data")
|
b.Property<string>("Data")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("data")
|
.HasColumnName("data")
|
||||||
.HasComment("Данные таблицы последних данных");
|
.HasComment("Данные таблицы последних данных");
|
||||||
@ -2727,7 +2726,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnName("obsolescence")
|
.HasColumnName("obsolescence")
|
||||||
.HasComment("сек. до устаревания");
|
.HasComment("сек. до устаревания");
|
||||||
|
|
||||||
b.Property<Dictionary<string, double>>("Setpoints")
|
b.Property<string>("Setpoints")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("setpoint_set")
|
.HasColumnName("setpoint_set")
|
||||||
.HasComment("Набор уставок");
|
.HasComment("Набор уставок");
|
||||||
@ -2756,7 +2755,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
b.Property<TelemetryInfo>("Info")
|
b.Property<string>("Info")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("info")
|
.HasColumnName("info")
|
||||||
.HasComment("Информация с панели о скважине");
|
.HasComment("Информация с панели о скважине");
|
||||||
@ -2766,7 +2765,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnName("remote_uid")
|
.HasColumnName("remote_uid")
|
||||||
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
|
.HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв.");
|
||||||
|
|
||||||
b.Property<SimpleTimezone>("TimeZone")
|
b.Property<string>("TimeZone")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("timezone")
|
.HasColumnName("timezone")
|
||||||
.HasComment("Смещение часового пояса от UTC");
|
.HasComment("Смещение часового пояса от UTC");
|
||||||
@ -3912,7 +3911,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnType("double precision")
|
.HasColumnType("double precision")
|
||||||
.HasColumnName("longitude");
|
.HasColumnName("longitude");
|
||||||
|
|
||||||
b.Property<SimpleTimezone>("Timezone")
|
b.Property<string>("Timezone")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("timezone")
|
.HasColumnName("timezone")
|
||||||
.HasComment("Смещение часового пояса от UTC");
|
.HasComment("Смещение часового пояса от UTC");
|
||||||
@ -4164,6 +4163,18 @@ namespace AsbCloudDb.Migrations
|
|||||||
Name = "На поверхности"
|
Name = "На поверхности"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
|
{
|
||||||
|
Id = 18,
|
||||||
|
Code = 0,
|
||||||
|
Name = "Проработка перед наращиванием"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = 19,
|
||||||
|
Code = 0,
|
||||||
|
Name = "Шаблонировка перед наращиванием"
|
||||||
|
},
|
||||||
|
new
|
||||||
{
|
{
|
||||||
Id = 1001,
|
Id = 1001,
|
||||||
Code = 0,
|
Code = 0,
|
||||||
|
@ -680,6 +680,9 @@ namespace AsbCloudDb.Model
|
|||||||
new WellOperationCategory {Id = 15, Name = "Неподвижное состояние", Code = 0 },
|
new WellOperationCategory {Id = 15, Name = "Неподвижное состояние", Code = 0 },
|
||||||
new WellOperationCategory {Id = 16, Name = "Вращение без циркуляции", Code = 0 },
|
new WellOperationCategory {Id = 16, Name = "Вращение без циркуляции", Code = 0 },
|
||||||
new WellOperationCategory {Id = 17, Name = "На поверхности", Code = 0 },
|
new WellOperationCategory {Id = 17, Name = "На поверхности", Code = 0 },
|
||||||
|
new WellOperationCategory {Id = 18, Name = "Проработка перед наращиванием", Code = 0 },
|
||||||
|
new WellOperationCategory {Id = 19, Name = "Шаблонировка перед наращиванием", Code = 0 },
|
||||||
|
|
||||||
// Операции ручного ввода
|
// Операции ручного ввода
|
||||||
new WellOperationCategory {Id = 1001, Name = "Бурение", Code = 0 },
|
new WellOperationCategory {Id = 1001, Name = "Бурение", Code = 0 },
|
||||||
new WellOperationCategory {Id = 1002, Name = "ГИС", Code = 0 },
|
new WellOperationCategory {Id = 1002, Name = "ГИС", Code = 0 },
|
||||||
|
@ -6,11 +6,11 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
{
|
{
|
||||||
public DateTimeOffset DateTime { get; set; }
|
public DateTimeOffset DateTime { get; set; }
|
||||||
public int? IdUser { get; set; }
|
public int? IdUser { get; set; }
|
||||||
public float? WellDepth { get; set; }
|
public float WellDepth { get; set; }
|
||||||
public float? Pressure { get; set; }
|
public float Pressure { get; set; }
|
||||||
public float? HookWeight { get; set; }
|
public float HookWeight { get; set; }
|
||||||
public float? BlockPosition { get; set; }
|
public float BlockPosition { get; set; }
|
||||||
public float? BitDepth { get; set; }
|
public float BitDepth { get; set; }
|
||||||
public float? RotorSpeed { get; set; }
|
public float RotorSpeed { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
internal abstract class DetectorAbstract
|
||||||
|
{
|
||||||
|
private readonly int idOperation;
|
||||||
|
private readonly int stepLength = 3;
|
||||||
|
|
||||||
|
protected DetectorAbstract(int idOperation)
|
||||||
|
{
|
||||||
|
this.idOperation = idOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation, out OperationDetectorResult? result)
|
||||||
|
{
|
||||||
|
// Проверка соответствия критерию начала операции
|
||||||
|
if (DetectBegin(telemetry, begin, previousOperation))
|
||||||
|
{
|
||||||
|
// Поиск окончания соответствия критерию
|
||||||
|
var positionEnd = begin;
|
||||||
|
while (positionEnd < end)
|
||||||
|
{
|
||||||
|
positionEnd += stepLength;
|
||||||
|
if ((positionEnd > end))
|
||||||
|
positionEnd = end;
|
||||||
|
|
||||||
|
if ((positionEnd == end) || DetectEnd(telemetry, positionEnd, previousOperation))
|
||||||
|
{
|
||||||
|
result = MakeOperation(idTelemetry, telemetry, begin, positionEnd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation);
|
||||||
|
protected virtual bool DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
|
=> !DetectBegin(telemetry, position, previousOperation);
|
||||||
|
|
||||||
|
private OperationDetectorResult MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
var result = new OperationDetectorResult
|
||||||
|
{
|
||||||
|
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(telemetry, begin, end),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract bool IsValid(DetectableTelemetry[] telemetry, int begin, int end);
|
||||||
|
|
||||||
|
protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end);
|
||||||
|
|
||||||
|
public static InterpolationLine MakeInterpolationLine(
|
||||||
|
Func<DetectableTelemetry, double> yGetter,
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
int begin,
|
||||||
|
int fragmentLength)
|
||||||
|
{
|
||||||
|
DetectableTelemetry[] data;
|
||||||
|
if (fragmentLength > 0 && (begin + fragmentLength) < telemetry.Length)
|
||||||
|
data = telemetry[begin..(begin + fragmentLength)];
|
||||||
|
else
|
||||||
|
data = telemetry[begin..];
|
||||||
|
var line = new InterpolationLine(data.Select(d => (yGetter(d), (d.DateTime - telemetry[0].DateTime).TotalHours)));
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// расчет продолжительности операции
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="end"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static double CalcDeltaTime(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
var result = (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// часто используемый предикат для определения отсутствия изменения глубины ствола скважины
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="end"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static bool IsValidByWellDepthDoesNotChange(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
if (Math.Abs((double)(pBegin.WellDepth - pEnd.WellDepth)) > 0.01)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static bool IsValidByWellDepthIncreasing(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
if (pBegin.WellDepth >= pEnd.WellDepth)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static double CalcRop(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
var result = (double)(pEnd.WellDepth - pBegin.WellDepth) / (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
internal class DetectorDevelopment : DetectorAbstract
|
||||||
|
{
|
||||||
|
public DetectorDevelopment()
|
||||||
|
: base(18) { }
|
||||||
|
|
||||||
|
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
=> CalcDeltaTime(telemetry, begin, end);
|
||||||
|
|
||||||
|
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
|
{
|
||||||
|
if (previousOperation?.IdCategory == 14)
|
||||||
|
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 > 31)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (point0.RotorSpeed < 10)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
internal class DetectorRotor : DetectorAbstract
|
||||||
|
{
|
||||||
|
public DetectorRotor()
|
||||||
|
: base(2) { }
|
||||||
|
|
||||||
|
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
|
{
|
||||||
|
var point0 = telemetry[position];
|
||||||
|
var delta = point0.WellDepth - point0.BitDepth;
|
||||||
|
if (delta > 0.03d)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (point0.Pressure < 25)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (point0.RotorSpeed < 5)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var point1 = telemetry[position + 1];
|
||||||
|
if (point1.WellDepth - point0.WellDepth <= 0.003)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
|
{
|
||||||
|
var point0 = telemetry[position];
|
||||||
|
var delta = point0.WellDepth - point0.BitDepth;
|
||||||
|
if (delta > 0.03d)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (point0.Pressure < 25)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var lineRotorSpeed = MakeInterpolationLine(d => d.RotorSpeed, telemetry, position, 10);
|
||||||
|
|
||||||
|
if (lineRotorSpeed.IsAverageYLessThan(5))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var lineWellDepth = MakeInterpolationLine(d => d.WellDepth, telemetry, position, 30);
|
||||||
|
|
||||||
|
if (!lineWellDepth.IsYIncreases(1))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
internal class DetectorSlide : DetectorAbstract
|
||||||
|
{
|
||||||
|
public DetectorSlide()
|
||||||
|
: base(3) { }
|
||||||
|
|
||||||
|
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
|
{
|
||||||
|
var point0 = telemetry[position];
|
||||||
|
var delta = point0.WellDepth - point0.BitDepth;
|
||||||
|
if (delta > 0.03d)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (point0.Pressure < 25)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (point0.RotorSpeed > 5)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var point1 = telemetry[position + 1];
|
||||||
|
if (point1.WellDepth - point0.WellDepth <= 0.003)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
|
{
|
||||||
|
var point0 = telemetry[position];
|
||||||
|
var delta = point0.WellDepth - point0.BitDepth;
|
||||||
|
if (delta > 0.03d)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (point0.Pressure < 25)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var lineRotorSpeed = MakeInterpolationLine(d => d.RotorSpeed, telemetry, position, 10);
|
||||||
|
|
||||||
|
if (lineRotorSpeed.IsAverageYGreaterThan(5))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var lineWellDepth = MakeInterpolationLine(d => d.WellDepth, telemetry, position, 30);
|
||||||
|
|
||||||
|
if (!lineWellDepth.IsYIncreases(1))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
internal class DetectorSlipsTime : DetectorAbstract
|
||||||
|
{
|
||||||
|
public DetectorSlipsTime()
|
||||||
|
: base(14) { }
|
||||||
|
|
||||||
|
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
=> CalcDeltaTime(telemetry, begin, end);
|
||||||
|
|
||||||
|
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.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
internal class DetectorTemplating : DetectorAbstract
|
||||||
|
{
|
||||||
|
public DetectorTemplating()
|
||||||
|
: base(19) { }
|
||||||
|
|
||||||
|
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
=> CalcDeltaTime(telemetry, begin, end);
|
||||||
|
|
||||||
|
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
|
{
|
||||||
|
if(previousOperation?.IdCategory == 14)
|
||||||
|
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 > 31)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (point0.RotorSpeed > 10)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
|
|
@ -1,162 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
#nullable enable
|
|
||||||
internal class FragmentDetector : IFragmentDetector
|
|
||||||
{
|
|
||||||
private int fragmentLength = 12;
|
|
||||||
private int stepLength = 3;
|
|
||||||
protected IEnumerable<IDetector> detectors = Enumerable.Empty<IDetector>();
|
|
||||||
|
|
||||||
protected Func<DetectableTelemetry[], int, bool> detectStart;
|
|
||||||
protected Func<DetectableTelemetry[], int, bool> 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<DetectableTelemetry[], int, bool> detectStart,
|
|
||||||
IFragmentDetector detector,
|
|
||||||
params IFragmentDetector[] detectors)
|
|
||||||
{
|
|
||||||
this.detectStart = detectStart;
|
|
||||||
this.detectors = JoinDetectors(detector, detectors);
|
|
||||||
detectEnd = (f, i) => !detectStart(f, i);
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
public FragmentDetector(
|
|
||||||
string name,
|
|
||||||
Func<DetectableTelemetry[], int, bool> detectStart,
|
|
||||||
Func<DetectableTelemetry[], int, bool> detectEnd,
|
|
||||||
IFragmentDetector detector,
|
|
||||||
params IFragmentDetector[] detectors)
|
|
||||||
{
|
|
||||||
this.detectStart = detectStart;
|
|
||||||
this.detectEnd = detectEnd;
|
|
||||||
this.detectors = JoinDetectors(detector, detectors);
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FragmentDetector(
|
|
||||||
string name,
|
|
||||||
Func<DetectableTelemetry[], int, bool> detectStart,
|
|
||||||
IOperationDetector operation)
|
|
||||||
{
|
|
||||||
this.detectStart = detectStart;
|
|
||||||
detectors = new IOperationDetector[] { operation };
|
|
||||||
detectEnd = (f, i) => !detectStart(f, i);
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FragmentDetector(
|
|
||||||
string name,
|
|
||||||
Func<DetectableTelemetry[], int, bool> detectStart,
|
|
||||||
Func<DetectableTelemetry[], int, bool> detectEnd,
|
|
||||||
IOperationDetector operation)
|
|
||||||
{
|
|
||||||
this.detectStart = detectStart;
|
|
||||||
this.detectEnd = detectEnd;
|
|
||||||
detectors = new IOperationDetector[] { operation };
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<IFragmentDetector> 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<DetectableTelemetry[], int, bool> MakeInstantDelegate(
|
|
||||||
Func<DetectableTelemetry, bool> instantValueCondition
|
|
||||||
)
|
|
||||||
{
|
|
||||||
var detect = (DetectableTelemetry[] telemetry, int position) =>
|
|
||||||
{
|
|
||||||
var firstItem = telemetry[position];
|
|
||||||
var result = instantValueCondition(firstItem);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
return detect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Func<DetectableTelemetry[], int, bool> MakeInterpolationDelegate(
|
|
||||||
Func<DetectableTelemetry, double> yGetter,
|
|
||||||
Func<InterpolationLine, bool> interpolationValueCondition,
|
|
||||||
int fragmentLength)
|
|
||||||
{
|
|
||||||
var detect = (DetectableTelemetry[] telemetry, int position) =>
|
|
||||||
{
|
|
||||||
DetectableTelemetry[] data;
|
|
||||||
if (fragmentLength > 0 && (position + fragmentLength) < telemetry.Length)
|
|
||||||
data = telemetry[position..(position + fragmentLength)];
|
|
||||||
else
|
|
||||||
data = telemetry[position..];
|
|
||||||
var line = new InterpolationLine(data.Select(d => (yGetter(d), (d.DateTime - telemetry[0].DateTime).TotalHours)));
|
|
||||||
var result = interpolationValueCondition(line);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
return detect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, out IEnumerable<OperationDetectorResult> results)
|
|
||||||
{
|
|
||||||
List<OperationDetectorResult>? totaltResultList = null;
|
|
||||||
var positionBegin = begin;
|
|
||||||
// Поиск начала соответствия критерию начала операции
|
|
||||||
while (end > positionBegin + fragmentLength + stepLength)
|
|
||||||
{
|
|
||||||
if (detectStart(telemetry, positionBegin))
|
|
||||||
{
|
|
||||||
// Поиск окончания соответствия критерию
|
|
||||||
var positionEnd = positionBegin;
|
|
||||||
while (positionEnd < end)
|
|
||||||
{
|
|
||||||
positionEnd += stepLength;
|
|
||||||
if ((positionEnd > end))
|
|
||||||
positionEnd = end;
|
|
||||||
|
|
||||||
if ((positionEnd == end) || detectEnd(telemetry, positionEnd))
|
|
||||||
{
|
|
||||||
totaltResultList = totaltResultList ?? new List<OperationDetectorResult>();
|
|
||||||
var detectorsEnumerator = detectors.GetEnumerator();
|
|
||||||
while (detectorsEnumerator.MoveNext())
|
|
||||||
if (detectorsEnumerator.Current.TryDetect(idTelemetry, telemetry, positionBegin, positionEnd, out IEnumerable<OperationDetectorResult> innerResult))
|
|
||||||
totaltResultList.AddRange(innerResult);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
positionBegin = positionEnd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
positionBegin += stepLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(totaltResultList?.Any() == true)
|
|
||||||
{
|
|
||||||
results = totaltResultList!;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
results = Enumerable.Empty<OperationDetectorResult>();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override string ToString()
|
|
||||||
=> $"frame detector {Name}";
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
internal interface IDetector
|
|
||||||
{
|
|
||||||
bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, int begin, int end, out IEnumerable<OperationDetectorResult> operations);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal interface IOperationDetector : IDetector
|
|
||||||
{ }
|
|
||||||
|
|
||||||
internal interface IFragmentDetector: IDetector
|
|
||||||
{ }
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
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<DetectableTelemetry[], int, int, bool> isValid = (_,_,_) => true;
|
|
||||||
|
|
||||||
protected Func<DetectableTelemetry[], int, int, double> calcValue = (_, _, _) => 0d;
|
|
||||||
|
|
||||||
public OperationDetector(int idOperation)
|
|
||||||
{
|
|
||||||
this.idOperation = idOperation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, int begin, int end, out IEnumerable<OperationDetectorResult> operations)
|
|
||||||
{
|
|
||||||
if(!telemetryFragment.Any() || !isValid(telemetryFragment, begin, end))
|
|
||||||
{
|
|
||||||
operations = Enumerable.Empty<OperationDetectorResult>();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var operation = MakeOperation(idTelemetry, telemetryFragment, begin, end);
|
|
||||||
|
|
||||||
operations = new List<OperationDetectorResult> { operation };
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private OperationDetectorResult MakeOperation(int idTelemetry, DetectableTelemetry[] telemetryFragment, int begin, int end)
|
|
||||||
{
|
|
||||||
var pBegin = telemetryFragment[begin];
|
|
||||||
var pEnd = telemetryFragment[end];
|
|
||||||
var result = new OperationDetectorResult
|
|
||||||
{
|
|
||||||
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 result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,11 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
class OperationDetectorResult
|
||||||
|
{
|
||||||
|
public int TelemetryBegin { get; set; }
|
||||||
|
public int TelemetryEnd { get; set; }
|
||||||
|
public DetectedOperation Operation { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
|
|
||||||
internal class OperationDrilling : OperationDetector
|
|
||||||
{
|
|
||||||
public OperationDrilling(int idOperation)
|
|
||||||
:base(idOperation)
|
|
||||||
{
|
|
||||||
isValid = (DetectableTelemetry[] fragment, int begin, int end) =>
|
|
||||||
{
|
|
||||||
var pBegin = fragment[begin];
|
|
||||||
var pEnd = fragment[end];
|
|
||||||
if (pBegin.WellDepth >= pEnd.WellDepth)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
calcValue = (DetectableTelemetry[] fragment, int begin, int end) =>
|
|
||||||
{
|
|
||||||
var pBegin = fragment[begin];
|
|
||||||
var pEnd = fragment[end];
|
|
||||||
var result = (double)(pEnd.WellDepth - pBegin.WellDepth) / (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
internal class OperationSlipsTime : OperationDetector
|
|
||||||
{
|
|
||||||
public OperationSlipsTime()
|
|
||||||
: base(14)
|
|
||||||
{
|
|
||||||
isValid = (DetectableTelemetry[] fragment, int begin, int end) =>
|
|
||||||
{
|
|
||||||
var pBegin = fragment[begin];
|
|
||||||
var pEnd = fragment[end];
|
|
||||||
if (Math.Abs((double)(pBegin.WellDepth - pEnd.WellDepth)) > 0.01)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
calcValue = (DetectableTelemetry[] fragment, int begin, int end) =>
|
|
||||||
{
|
|
||||||
var pBegin = fragment[begin];
|
|
||||||
var pEnd = fragment[end];
|
|
||||||
var result = (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,38 +14,16 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
{
|
{
|
||||||
public class OperationDetectionBackgroundService : BackgroundService
|
public class OperationDetectionBackgroundService : BackgroundService
|
||||||
{
|
{
|
||||||
private readonly int stepLength = 3;
|
|
||||||
private readonly int fragmentLength = 6;
|
|
||||||
private readonly string connectionString;
|
private readonly string connectionString;
|
||||||
private readonly TimeSpan period = TimeSpan.FromHours(1);
|
private readonly TimeSpan period = TimeSpan.FromHours(1);
|
||||||
|
|
||||||
private static readonly Func<DetectableTelemetry[], int, bool> isBitLt0_03mToBottom = FragmentDetector.MakeInstantDelegate(d =>
|
private static readonly DetectorAbstract[] detectors = new DetectorAbstract[]
|
||||||
(double)(d.WellDepth - d.BitDepth) < 0.03d);
|
|
||||||
private static readonly Func<DetectableTelemetry[], int, bool> isBitLt2_5mToBottom = FragmentDetector.MakeInstantDelegate(d =>
|
|
||||||
(double)(d.WellDepth - d.BitDepth) < 2.5d);
|
|
||||||
private static readonly Func<DetectableTelemetry[], int, bool> isPressureGt25 = FragmentDetector.MakeInstantDelegate(d =>
|
|
||||||
d.Pressure > 25);
|
|
||||||
private static readonly Func<DetectableTelemetry[], int, bool> isPressureLt15 = FragmentDetector.MakeInstantDelegate(d =>
|
|
||||||
d.Pressure < 15);
|
|
||||||
private static readonly Func<DetectableTelemetry[], int, bool> isBlockPositionLt8 = FragmentDetector.MakeInstantDelegate(d =>
|
|
||||||
d.BlockPosition < 8);
|
|
||||||
private static readonly Func<DetectableTelemetry[], int, bool> isHookWeightLt20 = FragmentDetector.MakeInstantDelegate(d =>
|
|
||||||
d.HookWeight < 20);
|
|
||||||
private static readonly Func<DetectableTelemetry[], int, bool> isRotorSpeedAvgGt5 = FragmentDetector.MakeInterpolationDelegate(d => (double)d.RotorSpeed, line =>
|
|
||||||
line.IsAverageYGreaterThan(5), 12);
|
|
||||||
private static readonly Func<DetectableTelemetry[], int, bool> isRotorSpeedAvgLt5 = FragmentDetector.MakeInterpolationDelegate(d => (double)d.RotorSpeed, line =>
|
|
||||||
line.IsAverageYLessThan(5), 12);
|
|
||||||
|
|
||||||
private static readonly List<IDetector> detectors = new List<IDetector>
|
|
||||||
{
|
{
|
||||||
new FragmentDetector("isBitLt2_5mToBottom", isBitLt2_5mToBottom,
|
new DetectorRotor(),
|
||||||
new FragmentDetector("isBitLt0_03mToBottom", isBitLt0_03mToBottom,
|
new DetectorSlide(),
|
||||||
new FragmentDetector("isPressureGt25", isPressureGt25,
|
new DetectorDevelopment(),
|
||||||
new FragmentDetector("isRotorSpeedAvgGt5", isRotorSpeedAvgGt5, new OperationDrilling(2)),
|
new DetectorTemplating(),
|
||||||
new FragmentDetector("isRotorSpeedAvgLt5", isRotorSpeedAvgLt5, new OperationDrilling(3)))),
|
new DetectorSlipsTime(),
|
||||||
new FragmentDetector("isPressureLt15", isPressureLt15,
|
|
||||||
new FragmentDetector("isBlockPositionLt8", isBlockPositionLt8,
|
|
||||||
new FragmentDetector("isHookWeightLt20", isHookWeightLt20, new OperationSlipsTime())))),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public OperationDetectionBackgroundService(IConfiguration configuration)
|
public OperationDetectionBackgroundService(IConfiguration configuration)
|
||||||
@ -136,18 +114,22 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
{
|
{
|
||||||
DateTime = d.DateTime,
|
DateTime = d.DateTime,
|
||||||
IdUser = d.IdUser,
|
IdUser = d.IdUser,
|
||||||
WellDepth = d.WellDepth,
|
WellDepth = (float)d.WellDepth,
|
||||||
Pressure = d.Pressure,
|
Pressure = (float)d.Pressure,
|
||||||
HookWeight = d.HookWeight,
|
HookWeight = (float)d.HookWeight,
|
||||||
BlockPosition = d.BlockPosition,
|
BlockPosition = (float)d.BlockPosition,
|
||||||
BitDepth = d.BitDepth,
|
BitDepth = (float)d.BitDepth,
|
||||||
RotorSpeed = d.RotorSpeed,
|
RotorSpeed = (float)d.RotorSpeed,
|
||||||
})
|
})
|
||||||
.OrderBy(d => d.DateTime);
|
.OrderBy(d => d.DateTime);
|
||||||
|
|
||||||
var take = 4 * 86_400; // 4 дня
|
var take = 4 * 86_400; // 4 дня
|
||||||
var startDate = begin;
|
var startDate = begin;
|
||||||
var detectedOperations = new List<DetectedOperation>(8);
|
var detectedOperations = new List<DetectedOperation>(8);
|
||||||
|
DetectedOperation? lastDetectedOperation = null;
|
||||||
|
const int minOperationLength = 5;
|
||||||
|
const int maxDetectorsInterpolationFrameLength = 30;
|
||||||
|
const int gap = maxDetectorsInterpolationFrameLength + minOperationLength;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@ -156,43 +138,35 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
.Take(take)
|
.Take(take)
|
||||||
.ToArrayAsync(token);
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
if (data.Length < 2 * fragmentLength + stepLength)
|
if (data.Length < gap)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var isDetected = false;
|
var isDetected = false;
|
||||||
var positionBegin = 0;
|
var positionBegin = 0;
|
||||||
var positionEnd = data.Length - fragmentLength;
|
var positionEnd = data.Length - gap;
|
||||||
|
while (positionEnd > positionBegin)
|
||||||
foreach (var detector in detectors)
|
|
||||||
{
|
{
|
||||||
if (detector is FragmentDetector fragmentDetector)
|
for (int i = 0; i < detectors.Length; i++)
|
||||||
{
|
{
|
||||||
var minLengthToDetect = fragmentDetector.StepLength + fragmentDetector.FragmentLength;
|
if (detectors[i].TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out OperationDetectorResult result))
|
||||||
if (data.Length < positionBegin + minLengthToDetect)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fragmentDetector.TryDetect(idTelemetry, data, positionBegin, positionEnd, out IEnumerable<OperationDetectorResult> results))
|
|
||||||
{
|
{
|
||||||
|
detectedOperations.Add(result.Operation);
|
||||||
|
lastDetectedOperation = result.Operation;
|
||||||
isDetected = true;
|
isDetected = true;
|
||||||
var operations = results.Select(r => r.Operation);
|
positionBegin = result.TelemetryEnd;
|
||||||
detectedOperations.AddRange(operations);
|
|
||||||
positionBegin = results.Max(r=>r.TelemetryEnd) + 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
positionBegin++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDetected)
|
if (isDetected)
|
||||||
{
|
{
|
||||||
startDate = detectedOperations.Max(o => o.DateEnd);
|
startDate = detectedOperations.Last().DateEnd;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i = positionEnd - (int)(data.Length * 0.8);
|
startDate = data[positionEnd].DateTime;
|
||||||
if (i < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
startDate = data[i].DateTime;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user