2024-07-04 11:02:45 +05:00
|
|
|
using System;
|
2023-12-04 17:36:00 +05:00
|
|
|
using System.Collections.Generic;
|
2023-12-18 13:51:40 +05:00
|
|
|
using AsbCloudApp.Data.DetectedOperation;
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
|
|
|
|
|
|
|
public abstract class DetectorAbstract
|
2022-06-30 17:37:57 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_NotDetected = 0;
|
|
|
|
protected const int IdReasonOfEnd_NotDetectBegin = 1;
|
2022-08-09 18:00:22 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_DeltaDepthIsLo = 100;
|
|
|
|
protected const int IdReasonOfEnd_DeltaDepthIsHi = 101;
|
|
|
|
protected const int IdReasonOfEnd_DeltaDepthOutOfRange = 102;
|
|
|
|
protected const int IdReasonOfEnd_WellDepthDeviates = 200;
|
2022-08-09 18:00:22 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_PressureIsLo = 300;
|
|
|
|
protected const int IdReasonOfEnd_PressureIsHi = 301;
|
|
|
|
protected const int IdReasonOfEnd_PressureOutOfRange = 302;
|
|
|
|
protected const int IdReasonOfEnd_PressureIsRising = 303;
|
2022-08-09 18:00:22 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_RotorSpeedIsLo = 400;
|
|
|
|
protected const int IdReasonOfEnd_RotorSpeedIsHi = 401;
|
|
|
|
protected const int IdReasonOfEnd_AvgRotorSpeedIsHi = 402;
|
|
|
|
protected const int IdReasonOfEnd_AvgRotorSpeedIsLo = 403;
|
2022-08-09 18:00:22 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_BlockPositionIsLo = 500;
|
|
|
|
protected const int IdReasonOfEnd_BlockPositionIsHi = 501;
|
|
|
|
protected const int IdReasonOfEnd_BlockPositionDeviates = 502;
|
2022-08-09 18:00:22 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_Drilling = 600;
|
2022-08-09 18:00:22 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_ChangeBitDepthAndAxiLoadLessHookWeight = 700;
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_DeltaWellDepthAndBitDepthIsLo = 800;
|
2024-03-15 14:51:13 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected const int IdReasonOfEnd_BitDepthIsLo = 900;
|
2024-03-15 14:51:13 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperationDto? previousOperation,
|
|
|
|
out OperationDetectorResult? result)
|
|
|
|
{
|
|
|
|
// Проверка соответствия критерию начала операции
|
|
|
|
if (DetectBegin(telemetry, begin, previousOperation))
|
2022-06-30 17:37:57 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
// Поиск окончания соответствия критерию
|
|
|
|
int idReasonOfEnd = 0;
|
|
|
|
var positionEnd = begin;
|
|
|
|
|
|
|
|
while (positionEnd < end)
|
2023-11-22 14:47:17 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
positionEnd += 1;
|
|
|
|
if (positionEnd > end)
|
|
|
|
break;
|
2024-03-01 09:32:02 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
//TODO: поиск провалов телеметрий. Следует обсудить, так как алгоритмы теряют в точности.
|
2023-12-04 17:36:00 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation);
|
|
|
|
|
|
|
|
if (idReasonOfEnd != IdReasonOfEnd_NotDetected)
|
|
|
|
break;
|
2022-06-30 17:37:57 +05:00
|
|
|
}
|
2024-07-26 16:56:36 +05:00
|
|
|
|
|
|
|
var (Begin, End) = RefineEdges(telemetry, begin, positionEnd);
|
|
|
|
|
|
|
|
result = MakeOperationDetectorResult(idTelemetry, telemetry, Begin, End, idReasonOfEnd);
|
2023-11-22 14:47:17 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
return IsValidOperationDetectorResult(result);
|
2022-06-30 17:37:57 +05:00
|
|
|
}
|
2023-12-04 17:36:00 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
result = null;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual (int Begin, int End) RefineEdges(DetectableTelemetry[] telemetry, int begin, int end)
|
|
|
|
=> (begin, end);
|
|
|
|
|
|
|
|
protected virtual bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult)
|
|
|
|
=> operationDetectorResult.Operation.DateEnd - operationDetectorResult.Operation.DateStart > TimeSpan.FromSeconds(3);
|
|
|
|
|
|
|
|
protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation);
|
|
|
|
|
|
|
|
protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
|
|
|
|
=> DetectBegin(telemetry, position, previousOperation)
|
|
|
|
? IdReasonOfEnd_NotDetected
|
|
|
|
: IdReasonOfEnd_NotDetectBegin;
|
|
|
|
|
|
|
|
private OperationDetectorResult MakeOperationDetectorResult(
|
|
|
|
int idTelemetry,
|
|
|
|
DetectableTelemetry[] telemetry,
|
|
|
|
int begin,
|
|
|
|
int end,
|
|
|
|
int idReasonOfEnd)
|
|
|
|
{
|
|
|
|
var operation = MakeDetectedOperation(idTelemetry, telemetry, begin, end);
|
2023-11-22 14:47:17 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
operation.ExtraData["IdReasonOfEnd"] = idReasonOfEnd;
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
var result = new OperationDetectorResult
|
2022-06-30 17:37:57 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
TelemetryBegin = begin,
|
|
|
|
TelemetryEnd = end,
|
|
|
|
Operation = operation,
|
|
|
|
};
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
return result;
|
|
|
|
}
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
private DetectedOperationDto MakeDetectedOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end)
|
|
|
|
{
|
|
|
|
var pBegin = telemetry[begin];
|
|
|
|
var pEnd = telemetry[end];
|
|
|
|
var (IdCategory, ExtraData) = GetSpecificInformation(telemetry, begin, end);
|
|
|
|
var operation = new DetectedOperationDto
|
2023-12-04 17:36:00 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
IdCategory = IdCategory,
|
|
|
|
IdTelemetry = idTelemetry,
|
|
|
|
IdUserAtStart = pBegin.IdUser ?? -1,
|
|
|
|
DateStart = pBegin.DateTime,
|
|
|
|
DateEnd = pEnd.DateTime,
|
|
|
|
DepthStart = (double)pBegin.WellDepth,
|
|
|
|
DepthEnd = (double)pEnd.WellDepth,
|
|
|
|
ExtraData = ExtraData,
|
|
|
|
Value = CalcValue(telemetry, begin, end),
|
|
|
|
EnabledSubsystems = DetectEnabledSubsystems(telemetry, begin, end, ExtraData)
|
|
|
|
};
|
|
|
|
|
|
|
|
return operation;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Получение информации специфичной для конкретного детектора
|
|
|
|
/// IdCategory - одна из констант WellOperationCategory
|
|
|
|
/// ExtraData - дополнительная информация для отладки алгоритмов авто определения
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
|
|
|
protected abstract (int IdCategory, IDictionary<string, object> ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end);
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Расчет ключевого параметра операции
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="telemetry"></param>
|
|
|
|
/// <param name="begin"></param>
|
|
|
|
/// <param name="end"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end);
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Определение включенных подсистем во время выполнения операции
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="telemetry"></param>
|
|
|
|
/// <param name="begin"></param>
|
|
|
|
/// <param name="end"></param>
|
|
|
|
/// <param name="extraData"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private static int DetectEnabledSubsystems(DetectableTelemetry[] telemetry, int begin, int end, IDictionary<string, object> extraData)
|
|
|
|
{
|
|
|
|
var enabledSubsystems = 0;
|
2023-12-04 17:36:00 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
if (extraData.TryGetValue(DetectorDrilling.ExtraDataKeyHasOscillation, out var hasOscillation)
|
|
|
|
&& hasOscillation is true)
|
|
|
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoOscillation;
|
2023-12-05 10:56:49 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
for (var i = begin; i < end; i += 2)
|
2022-06-30 17:37:57 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
var mode = telemetry[i].Mode;
|
2023-12-05 10:56:49 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
if(mode == 1)
|
|
|
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoRotor;
|
2023-12-18 13:51:40 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
if (mode == 3)
|
|
|
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoSlide;
|
2023-12-05 10:56:49 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
if (mode == 2)
|
|
|
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoConditionig;
|
2023-12-05 10:56:49 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
if (mode == 4)
|
|
|
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoSinking;
|
2023-12-05 10:56:49 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
if (mode == 5)
|
|
|
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoLifting;
|
2023-12-05 10:56:49 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
if (mode == 6)
|
|
|
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoLiftingWithConditionig;
|
2023-12-05 10:56:49 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
if (mode == 10)
|
|
|
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoBlocknig;
|
|
|
|
}
|
2023-12-05 10:56:49 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
return enabledSubsystems;
|
|
|
|
}
|
2023-11-22 14:47:17 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
/// <summary>
|
|
|
|
/// расчет продолжительности операции
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="telemetry"></param>
|
|
|
|
/// <param name="begin"></param>
|
|
|
|
/// <param name="end"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
protected static double CalcDeltaMinutes(DetectableTelemetry[] telemetry, int begin, int end)
|
|
|
|
{
|
|
|
|
var pBegin = telemetry[begin];
|
|
|
|
var pEnd = telemetry[end];
|
|
|
|
var result = (pEnd.DateTime - pBegin.DateTime).TotalMinutes;
|
|
|
|
return result;
|
|
|
|
}
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
/// <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;
|
|
|
|
}
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
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;
|
|
|
|
}
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Расчет статистики по массиву данных за интервал
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="telemetry"></param>
|
|
|
|
/// <param name="getter"></param>
|
|
|
|
/// <param name="begin"></param>
|
|
|
|
/// <param name="count"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
protected static (double min, double max, double sum, int count) CalcStat(
|
|
|
|
DetectableTelemetry[] telemetry,
|
|
|
|
Func<DetectableTelemetry, double> getter,
|
|
|
|
int begin,
|
|
|
|
int count)
|
|
|
|
{
|
|
|
|
var sum = 0d;
|
|
|
|
var min = double.MaxValue;
|
|
|
|
var max = double.MinValue;
|
|
|
|
var end = begin + count;
|
|
|
|
end = end < telemetry.Length ? end : telemetry.Length;
|
2022-06-30 17:37:57 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
for (var i = begin; i < end; i++)
|
2022-06-30 17:37:57 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
var item = telemetry[i];
|
|
|
|
var itemValue = getter(item);
|
|
|
|
if (min > itemValue)
|
|
|
|
min = itemValue;
|
|
|
|
if (max < itemValue)
|
|
|
|
max = itemValue;
|
|
|
|
sum += itemValue;
|
2022-06-30 17:37:57 +05:00
|
|
|
}
|
2022-07-01 17:04:44 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
return (min, max, sum, end - begin);
|
|
|
|
}
|
2022-07-01 17:04:44 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
/// <summary>
|
|
|
|
/// Максимальное отклонение от среднего за интервал
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="telemetry"></param>
|
|
|
|
/// <param name="getter"></param>
|
|
|
|
/// <param name="begin"></param>
|
|
|
|
/// <param name="count"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
protected static double CalcMaxDeviation(
|
|
|
|
DetectableTelemetry[] telemetry,
|
|
|
|
Func<DetectableTelemetry, double> getter,
|
|
|
|
int begin,
|
|
|
|
int count)
|
|
|
|
{
|
|
|
|
var stat = CalcStat(telemetry, getter, begin, count);
|
|
|
|
var avg = stat.sum / stat.count;
|
|
|
|
var dev1 = avg - stat.min;
|
|
|
|
var dev2 = stat.max - avg;
|
|
|
|
var dev = dev1 > dev2 ? dev1 : dev2;
|
|
|
|
return dev;
|
|
|
|
}
|
2023-11-22 14:47:17 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
/// <summary>
|
|
|
|
/// Определяет наличие разброса значений в интервале большего указанного значения.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="telemetry"></param>
|
|
|
|
/// <param name="getter"></param>
|
|
|
|
/// <param name="begin"></param>
|
|
|
|
/// <param name="count"></param>
|
|
|
|
/// <param name="deviation"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
protected static bool ContainsDeviation(
|
|
|
|
DetectableTelemetry[] telemetry,
|
|
|
|
Func<DetectableTelemetry, double> getter,
|
|
|
|
int begin,
|
|
|
|
int count,
|
|
|
|
double deviation)
|
|
|
|
{
|
|
|
|
var min = double.MaxValue;
|
|
|
|
var max = double.MinValue;
|
|
|
|
var end = begin + count;
|
|
|
|
end = end < telemetry.Length ? end : telemetry.Length;
|
2022-07-01 17:04:44 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
for (var i = begin; i < end; i++)
|
2022-07-01 17:04:44 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
var item = telemetry[i];
|
|
|
|
var itemValue = getter(item);
|
|
|
|
if (min > itemValue)
|
|
|
|
min = itemValue;
|
|
|
|
if (max < itemValue)
|
|
|
|
max = itemValue;
|
|
|
|
if (max - min > deviation)
|
|
|
|
return true;
|
2022-07-01 17:04:44 +05:00
|
|
|
}
|
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
return false;
|
|
|
|
}
|
2022-07-01 17:04:44 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
/// <summary>
|
|
|
|
/// Определяет наличие разброса значений в интервале большего указанного значения. По нескольким значениям из интервала.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="telemetry"></param>
|
|
|
|
/// <param name="getter"></param>
|
|
|
|
/// <param name="begin"></param>
|
|
|
|
/// <param name="count"></param>
|
|
|
|
/// <param name="deviation"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
protected static bool ContainsDeviationApprox(
|
|
|
|
DetectableTelemetry[] telemetry,
|
|
|
|
Func<DetectableTelemetry, double> getter,
|
|
|
|
int begin,
|
|
|
|
int count,
|
|
|
|
double deviation)
|
|
|
|
{
|
|
|
|
var min = double.MaxValue;
|
|
|
|
var max = double.MinValue;
|
|
|
|
var end = begin + count;
|
|
|
|
end = end < telemetry.Length ? end : telemetry.Length;
|
|
|
|
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
|
|
|
for (var i = begin; i < end; i += step)
|
2022-07-01 17:04:44 +05:00
|
|
|
{
|
2024-07-26 16:56:36 +05:00
|
|
|
var item = telemetry[i];
|
|
|
|
var itemValue = getter(item);
|
|
|
|
if (min > itemValue)
|
|
|
|
min = itemValue;
|
|
|
|
if (max < itemValue)
|
|
|
|
max = itemValue;
|
|
|
|
if (max - min > deviation)
|
|
|
|
return true;
|
2022-07-01 17:04:44 +05:00
|
|
|
}
|
2022-07-19 10:29:38 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
return false;
|
|
|
|
}
|
2023-11-22 14:47:17 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected static bool DeviatesFromBegin(
|
|
|
|
DetectableTelemetry[] telemetry,
|
|
|
|
Func<DetectableTelemetry, double> getter,
|
|
|
|
int begin,
|
|
|
|
int count,
|
|
|
|
double deviation)
|
|
|
|
{
|
|
|
|
var beginPointValue = getter(telemetry[begin]);
|
|
|
|
var end = begin + count;
|
|
|
|
end = end < telemetry.Length ? end : telemetry.Length;
|
|
|
|
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
|
|
|
for (var i = begin; i < end; i += step)
|
|
|
|
{
|
|
|
|
var item = telemetry[i];
|
|
|
|
var itemValue = getter(item);
|
|
|
|
if (Math.Abs(beginPointValue - itemValue) > deviation)
|
|
|
|
return true;
|
2022-07-19 10:29:38 +05:00
|
|
|
}
|
2022-07-20 09:49:36 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
return false;
|
|
|
|
}
|
2023-11-22 14:47:17 +05:00
|
|
|
|
2024-07-26 16:56:36 +05:00
|
|
|
protected static bool RisesFromBegin(
|
|
|
|
DetectableTelemetry[] telemetry,
|
|
|
|
Func<DetectableTelemetry, double> getter,
|
|
|
|
int begin,
|
|
|
|
int count,
|
|
|
|
double deviation)
|
|
|
|
{
|
|
|
|
var beginPointValue = getter(telemetry[begin]);
|
|
|
|
var end = begin + count;
|
|
|
|
end = end < telemetry.Length ? end : telemetry.Length;
|
|
|
|
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
|
|
|
for (var i = begin; i < end; i += step)
|
|
|
|
{
|
|
|
|
var item = telemetry[i];
|
|
|
|
var itemValue = getter(item);
|
|
|
|
if (itemValue - beginPointValue > deviation)
|
|
|
|
return true;
|
2022-07-20 09:49:36 +05:00
|
|
|
}
|
2024-07-26 16:56:36 +05:00
|
|
|
|
|
|
|
return false;
|
2022-06-30 17:37:57 +05:00
|
|
|
}
|
|
|
|
}
|