2022-06-27 10:20:54 +05:00
|
|
|
|
using AsbCloudDb.Model;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
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 int FragmentLength { get => fragmentLength; set => fragmentLength = value; }
|
|
|
|
|
public int StepLength { get => stepLength; set => stepLength = value; }
|
|
|
|
|
|
|
|
|
|
public FragmentDetector(
|
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-27 10:20:54 +05:00
|
|
|
|
}
|
|
|
|
|
public FragmentDetector(
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FragmentDetector(Func<DetectableTelemetry[], int, bool> detectStart, IOperationDetector operation)
|
|
|
|
|
{
|
|
|
|
|
this.detectStart = detectStart;
|
|
|
|
|
detectors = new IOperationDetector[] { operation };
|
|
|
|
|
detectEnd = (f, i) => !detectStart(f, i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FragmentDetector(Func<DetectableTelemetry[], int, bool> detectStart, Func<DetectableTelemetry[], int, bool> detectEnd, IOperationDetector operation)
|
|
|
|
|
{
|
|
|
|
|
this.detectStart = detectStart;
|
|
|
|
|
this.detectEnd = detectEnd;
|
|
|
|
|
detectors = new IOperationDetector[] { operation };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 && fragmentLength < telemetry.Length)
|
|
|
|
|
data = telemetry[position..(position + fragmentLength)];
|
|
|
|
|
else
|
|
|
|
|
data = telemetry;
|
|
|
|
|
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[] telemetryFragment, out IEnumerable<DetectedOperation> operations)
|
|
|
|
|
{
|
|
|
|
|
var positionStart = 0;
|
|
|
|
|
var operationsList = new List<DetectedOperation>();
|
2022-06-27 12:43:55 +05:00
|
|
|
|
// проверка соответствия критерию начала операции
|
|
|
|
|
if (detectStart(telemetryFragment, positionStart))
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
2022-06-27 12:43:55 +05:00
|
|
|
|
// Поиск окончания соответствия критерию
|
|
|
|
|
var positionEnd = positionStart + stepLength;
|
|
|
|
|
while (telemetryFragment.Length > positionEnd + FragmentLength)
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
2022-06-27 12:43:55 +05:00
|
|
|
|
if (detectEnd(telemetryFragment, positionEnd))
|
2022-06-27 10:20:54 +05:00
|
|
|
|
{
|
2022-06-27 12:43:55 +05:00
|
|
|
|
var innerFragment = telemetryFragment[positionStart..positionEnd];
|
|
|
|
|
var detectorEnumerator = detectors.GetEnumerator();
|
|
|
|
|
while (detectorEnumerator.MoveNext())
|
|
|
|
|
if (detectorEnumerator.Current.TryDetect(idTelemetry, innerFragment, out IEnumerable<DetectedOperation> result))
|
|
|
|
|
operationsList.AddRange(result);
|
2022-06-27 10:20:54 +05:00
|
|
|
|
|
2022-06-27 12:43:55 +05:00
|
|
|
|
break;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
2022-06-27 12:43:55 +05:00
|
|
|
|
positionEnd += stepLength;
|
2022-06-27 10:20:54 +05:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-27 12:43:55 +05:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
operations = Enumerable.Empty<DetectedOperation>();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-27 10:20:54 +05:00
|
|
|
|
operations = operationsList;
|
|
|
|
|
return operationsList.Any();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
#nullable disable
|
|
|
|
|
}
|