2022-06-29 13:40:06 +05:00
|
|
|
|
using System;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
2022-06-29 13:40:06 +05:00
|
|
|
|
using System.Runtime.CompilerServices;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2022-06-29 13:40:06 +05:00
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
|
2022-06-27 10:20:54 +05:00
|
|
|
|
public int FragmentLength { get => fragmentLength; set => fragmentLength = value; }
|
|
|
|
|
public int StepLength { get => stepLength; set => stepLength = value; }
|
|
|
|
|
|
|
|
|
|
public FragmentDetector(
|
2022-06-29 13:40:06 +05:00
|
|
|
|
string name,
|
2022-06-27 12:43:55 +05:00
|
|
|
|
Func<DetectableTelemetry[], int, bool> detectStart,
|
|
|
|
|
IFragmentDetector detector,
|
2022-06-27 10:20:54 +05:00
|
|
|
|
params IFragmentDetector[] detectors)
|
|
|
|
|
{
|
|
|
|
|
this.detectStart = detectStart;
|
|
|
|
|
this.detectors = JoinDetectors(detector, detectors);
|
2022-06-27 12:43:55 +05:00
|
|
|
|
detectEnd = (f, i) => !detectStart(f, i);
|
2022-06-29 13:40:06 +05:00
|
|
|
|
Name = name;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
|
|
|
|
public FragmentDetector(
|
2022-06-29 13:40:06 +05:00
|
|
|
|
string name,
|
2022-06-27 10:20:54 +05:00
|
|
|
|
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);
|
2022-06-29 13:40:06 +05:00
|
|
|
|
Name = name;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 13:40:06 +05:00
|
|
|
|
public FragmentDetector(
|
|
|
|
|
string name,
|
|
|
|
|
Func<DetectableTelemetry[], int, bool> detectStart,
|
|
|
|
|
IOperationDetector operation)
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
|
|
|
|
this.detectStart = detectStart;
|
|
|
|
|
detectors = new IOperationDetector[] { operation };
|
|
|
|
|
detectEnd = (f, i) => !detectStart(f, i);
|
2022-06-29 13:40:06 +05:00
|
|
|
|
Name = name;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 13:40:06 +05:00
|
|
|
|
public FragmentDetector(
|
|
|
|
|
string name,
|
|
|
|
|
Func<DetectableTelemetry[], int, bool> detectStart,
|
|
|
|
|
Func<DetectableTelemetry[], int, bool> detectEnd,
|
|
|
|
|
IOperationDetector operation)
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
|
|
|
|
this.detectStart = detectStart;
|
|
|
|
|
this.detectEnd = detectEnd;
|
|
|
|
|
detectors = new IOperationDetector[] { operation };
|
2022-06-29 13:40:06 +05:00
|
|
|
|
Name = name;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 13:40:06 +05:00
|
|
|
|
public static Func<DetectableTelemetry[], int, bool> MakeInstantDelegate(
|
|
|
|
|
Func<DetectableTelemetry, bool> instantValueCondition
|
|
|
|
|
)
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
|
|
|
|
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;
|
2022-06-29 13:40:06 +05:00
|
|
|
|
if (fragmentLength > 0 && (position + fragmentLength) < telemetry.Length)
|
2022-06-27 10:20:54 +05:00
|
|
|
|
data = telemetry[position..(position + fragmentLength)];
|
|
|
|
|
else
|
2022-06-29 13:40:06 +05:00
|
|
|
|
data = telemetry[position..];
|
2022-06-27 10:20:54 +05:00
|
|
|
|
var line = new InterpolationLine(data.Select(d => (yGetter(d), (d.DateTime - telemetry[0].DateTime).TotalHours)));
|
|
|
|
|
var result = interpolationValueCondition(line);
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
return detect;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 13:40:06 +05:00
|
|
|
|
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, out IEnumerable<OperationDetectorResult> results)
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
2022-06-29 13:40:06 +05:00
|
|
|
|
List<OperationDetectorResult>? totaltResultList = null;
|
|
|
|
|
var positionBegin = begin;
|
|
|
|
|
// Поиск начала соответствия критерию начала операции
|
|
|
|
|
while (end > positionBegin + fragmentLength + stepLength)
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
2022-06-29 13:40:06 +05:00
|
|
|
|
if (detectStart(telemetry, positionBegin))
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
2022-06-29 13:40:06 +05:00
|
|
|
|
// Поиск окончания соответствия критерию
|
|
|
|
|
var positionEnd = positionBegin;
|
|
|
|
|
while (positionEnd < end)
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
2022-06-29 13:40:06 +05:00
|
|
|
|
positionEnd += stepLength;
|
|
|
|
|
if ((positionEnd > end))
|
|
|
|
|
positionEnd = end;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
|
2022-06-29 13:40:06 +05:00
|
|
|
|
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;
|
|
|
|
|
}
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
2022-06-29 13:40:06 +05:00
|
|
|
|
positionBegin = positionEnd;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
positionBegin += stepLength;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-29 13:40:06 +05:00
|
|
|
|
|
|
|
|
|
if(totaltResultList?.Any() == true)
|
|
|
|
|
{
|
|
|
|
|
results = totaltResultList!;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2022-06-27 12:43:55 +05:00
|
|
|
|
else
|
|
|
|
|
{
|
2022-06-29 13:40:06 +05:00
|
|
|
|
results = Enumerable.Empty<OperationDetectorResult>();
|
2022-06-27 12:43:55 +05:00
|
|
|
|
return false;
|
2022-06-29 13:40:06 +05:00
|
|
|
|
}
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
2022-06-29 13:40:06 +05:00
|
|
|
|
public override string ToString()
|
|
|
|
|
=> $"frame detector {Name}";
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
|
|
|
|
#nullable disable
|
|
|
|
|
}
|