DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/DetectOperations/Detectors/FragmentDetector.cs

131 lines
5.3 KiB
C#
Raw Normal View History

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,
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);
}
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 12:43:55 +05:00
// Поиск окончания соответствия критерию
var positionEnd = positionStart + stepLength;
while (telemetryFragment.Length > positionEnd + FragmentLength)
{
2022-06-27 12:43:55 +05:00
if (detectEnd(telemetryFragment, positionEnd))
{
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 12:43:55 +05:00
break;
}
2022-06-27 12:43:55 +05:00
positionEnd += stepLength;
}
}
2022-06-27 12:43:55 +05:00
else
{
operations = Enumerable.Empty<DetectedOperation>();
return false;
}
operations = operationsList;
return operationsList.Any();
}
}
#nullable disable
}