forked from ddrilling/AsbCloudServer
145 lines
5.8 KiB
C#
145 lines
5.8 KiB
C#
|
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(
|
|||
|
Func<DetectableTelemetry[], int, bool> detectStart,
|
|||
|
IFragmentDetector detector,
|
|||
|
params IFragmentDetector[] detectors)
|
|||
|
{
|
|||
|
this.detectStart = detectStart;
|
|||
|
this.detectors = JoinDetectors(detector, detectors);
|
|||
|
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 IFragmentDetector AddChildDetector(params IFragmentDetector[] detectors)
|
|||
|
{
|
|||
|
throw new NotImplementedException();
|
|||
|
}
|
|||
|
|
|||
|
public IDetector AddOperationDetector(IOperationDetector operation)
|
|||
|
{
|
|||
|
detectors = new IOperationDetector[] { operation};
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable<DetectedOperation> operations)
|
|||
|
{
|
|||
|
var positionStart = 0;
|
|||
|
var operationsList = new List<DetectedOperation>();
|
|||
|
// поиск начала соответствия критерию
|
|||
|
while (telemetryFragment.Length > positionStart + FragmentLength + stepLength)
|
|||
|
{
|
|||
|
if (detectStart(telemetryFragment, positionStart))
|
|||
|
{
|
|||
|
// Поиск окончания соответствия критерию
|
|||
|
var positionEnd = positionStart + stepLength;
|
|||
|
while (telemetryFragment.Length > positionEnd + FragmentLength)
|
|||
|
{
|
|||
|
if (detectEnd(telemetryFragment, positionEnd))
|
|||
|
{
|
|||
|
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);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
positionEnd += stepLength;
|
|||
|
}
|
|||
|
positionStart = positionEnd;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
positionStart += stepLength;
|
|||
|
}
|
|||
|
}
|
|||
|
operations = operationsList;
|
|||
|
return operationsList.Any();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
#nullable disable
|
|||
|
}
|