forked from ddrilling/AsbCloudServer
doesn't work. Wrong handle begin of operation.
This commit is contained in:
parent
85c253b82b
commit
d0386b0182
@ -1,97 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations
|
|
||||||
{
|
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
abstract class DetectorAbstract
|
|
||||||
{
|
|
||||||
public int StepLength { get; set; } = 3;
|
|
||||||
public int FragmentLength { get; set; } = 6;
|
|
||||||
public int IdCategory { get; }
|
|
||||||
|
|
||||||
// TODO: assert MaxDurationSeconds and MinDurationSeconds
|
|
||||||
public double MaxDurationSeconds { get; } = 24 * 60 * 60;
|
|
||||||
public double MinDurationSeconds { get; } = 3;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Конструктор детектора.
|
|
||||||
/// Словарь с IdCategory в дефолтных данных AsbCloudDbContext для таблицы WellOperationCategory
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="IdCategory">ключ названия/описания операции из таблицы WellOperationCategory</param>
|
|
||||||
public DetectorAbstract(int IdCategory)
|
|
||||||
{
|
|
||||||
this.IdCategory = IdCategory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual DetectedOperation? DetectOrDefault(DetectableTelemetry[] telemetry, ref int positionStart)
|
|
||||||
{
|
|
||||||
if ((telemetry.Length > positionStart + FragmentLength + StepLength) && DetectStart(telemetry, positionStart))
|
|
||||||
{
|
|
||||||
var skip = positionStart + StepLength;
|
|
||||||
while (telemetry.Length > skip + FragmentLength)
|
|
||||||
{
|
|
||||||
if (DetectEnd(telemetry, skip))
|
|
||||||
{
|
|
||||||
var dateStart = telemetry[positionStart].DateTime;
|
|
||||||
var dateEnd = telemetry[skip].DateTime;
|
|
||||||
var durationSec = (dateEnd - dateStart).TotalSeconds;
|
|
||||||
if (durationSec < MinDurationSeconds || durationSec > MaxDurationSeconds)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var result = new DetectedOperation
|
|
||||||
{
|
|
||||||
IdCategory = IdCategory,
|
|
||||||
IdUsersAtStart = telemetry[positionStart].IdUser ?? -1,
|
|
||||||
DateStart = dateStart,
|
|
||||||
DateEnd = dateEnd,
|
|
||||||
DepthStart = telemetry[positionStart].WellDepth ?? -1d,
|
|
||||||
DepthEnd = telemetry[skip].WellDepth ?? -1d,
|
|
||||||
Value = CalcValue(telemetry, positionStart, skip),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!IsValid(result))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
positionStart = skip;// + FragmentLength;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
skip = skip + StepLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Расчет ключевого параметра
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="result"></param>
|
|
||||||
protected abstract double CalcValue(DetectableTelemetry[] telemetry, int positionBegin, int positionEnd);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Определение начала операции
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="position"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected abstract bool DetectStart(DetectableTelemetry[] telemetry, int position);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Определение окончания операции
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="position"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected abstract bool DetectEnd(DetectableTelemetry[] telemetry, int position);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Валидация операции
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="result"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected abstract bool IsValid(DetectedOperation result);
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
internal abstract class DetectorDrillingAbstract : DetectorAbstract
|
|
||||||
{
|
|
||||||
/* # РАСЧЕТ minRop
|
|
||||||
* шаг энкодера = 0.006м;
|
|
||||||
* 2 шага за 10 секунд не считается, так как может быть простым шумом;
|
|
||||||
* minRop = 0.006 * 2 / 10 = 0.0012 м/сек
|
|
||||||
* minRop > 4.32 м/ч & minRop < 6.48 м/ч (3 шага за 10 сек);
|
|
||||||
*/
|
|
||||||
protected const double minRop = 5.4; //м/час
|
|
||||||
protected const double minRotorSpeed = 5; //об/мин
|
|
||||||
protected const double minPressure = 25;
|
|
||||||
protected const double minDeltaDepth = 0.01;
|
|
||||||
|
|
||||||
public DetectorDrillingAbstract(int IdCategory) : base(IdCategory)
|
|
||||||
{
|
|
||||||
FragmentLength = 12;
|
|
||||||
StepLength = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool DetectStart(DetectableTelemetry[] telemetry, int position)
|
|
||||||
{
|
|
||||||
var firstItem = telemetry[position];
|
|
||||||
var deltaDepth = firstItem.WellDepth - firstItem.BitDepth;
|
|
||||||
if (deltaDepth is not null &&
|
|
||||||
System.Math.Abs((float)deltaDepth) > minDeltaDepth)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (firstItem.Pressure < minPressure)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var fragment = telemetry[position..(position + FragmentLength)];
|
|
||||||
|
|
||||||
var lineBlockPosition = new InterpolationLine(fragment.Select(d => (d.BlockPosition ?? 0d, (d.DateTime - firstItem.DateTime).TotalHours)));
|
|
||||||
if (!lineBlockPosition.IsYDecreases(-minRop))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var lineWellDepth = new InterpolationLine(fragment.Select(d => ((d.WellDepth - firstItem.WellDepth) ?? 0d, (d.DateTime - firstItem.DateTime).TotalHours)));
|
|
||||||
if (!lineWellDepth.IsYIncreases(minRop))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!ModeCondition(fragment))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position)
|
|
||||||
{
|
|
||||||
var firstItem = telemetry[position];
|
|
||||||
var deltaDepth = firstItem.WellDepth - firstItem.BitDepth;
|
|
||||||
if (deltaDepth is not null &&
|
|
||||||
System.Math.Abs((float)deltaDepth) > minDeltaDepth)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (firstItem.Pressure < minPressure)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var fragment = telemetry[position..(position + FragmentLength)];
|
|
||||||
if (!ModeCondition(fragment))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract bool ModeCondition(DetectableTelemetry[] telemetryFragment);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Рассчитываем МСП, м/час
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="result"></param>
|
|
||||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int positionBegin, int positionEnd)
|
|
||||||
{
|
|
||||||
var pBegin = telemetry[positionBegin];
|
|
||||||
var pEnd = telemetry[positionEnd];
|
|
||||||
var result = (double)(pEnd.WellDepth - pBegin.WellDepth) / (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
protected override bool IsValid(DetectedOperation result)
|
|
||||||
=> result.Value > 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
#nullable enable
|
|
||||||
class DetectorDrillingRotor : DetectorDrillingAbstract
|
|
||||||
{
|
|
||||||
public DetectorDrillingRotor()
|
|
||||||
: base(2){}
|
|
||||||
|
|
||||||
protected override bool ModeCondition(DetectableTelemetry[] telemetryFragment)
|
|
||||||
{
|
|
||||||
var lineRotorSpeed = new InterpolationLine(telemetryFragment.Select(d => (d.RotorSpeed ?? 0d, (d.DateTime - telemetryFragment[0].DateTime).TotalHours)));
|
|
||||||
return lineRotorSpeed.IsAverageYMoreThanBound(minRotorSpeed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
#nullable enable
|
|
||||||
class DetectorDrillingSlide : DetectorDrillingAbstract
|
|
||||||
{
|
|
||||||
public DetectorDrillingSlide()
|
|
||||||
: base(3){}
|
|
||||||
|
|
||||||
protected override bool ModeCondition(DetectableTelemetry[] telemetryFragment)
|
|
||||||
{
|
|
||||||
var lineRotorSpeed = new InterpolationLine(telemetryFragment.Select(d => (d.RotorSpeed ?? 0d, (d.DateTime - telemetryFragment[0].DateTime).TotalHours)));
|
|
||||||
return lineRotorSpeed.IsAverageYLessThanBound(minRotorSpeed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
#nullable enable
|
|
||||||
class DetectorSlipsTime : DetectorAbstract
|
|
||||||
{
|
|
||||||
public DetectorSlipsTime() : base(14) { }
|
|
||||||
public double HookWeightSP { get; set; } = 20;
|
|
||||||
public double PressureSP { get; set; } = 15;
|
|
||||||
public double PosisionSP { get; set; } = 8;
|
|
||||||
public double DeltaWellDepthMax { get; set; } = 2.5;
|
|
||||||
|
|
||||||
protected override bool DetectStart(DetectableTelemetry[] telemetry, int position)
|
|
||||||
{
|
|
||||||
var item = telemetry[position];
|
|
||||||
|
|
||||||
var result =
|
|
||||||
item.HookWeight < HookWeightSP &&
|
|
||||||
item.Pressure < PressureSP &&
|
|
||||||
item.BlockPosition < PosisionSP &&
|
|
||||||
(item.WellDepth - item.BitDepth) < DeltaWellDepthMax;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position)
|
|
||||||
{
|
|
||||||
var item = telemetry[position];
|
|
||||||
|
|
||||||
var result = item.Pressure > PressureSP &&
|
|
||||||
item.BlockPosition > PosisionSP;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int positionBegin, int positionEnd)
|
|
||||||
{
|
|
||||||
var pBegin = telemetry[positionBegin];
|
|
||||||
var pEnd = telemetry[positionEnd];
|
|
||||||
var result = (pEnd.DateTime - pBegin.DateTime).TotalMinutes;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool IsValid(DetectedOperation result)
|
|
||||||
=> result.Value > 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -0,0 +1,144 @@
|
|||||||
|
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
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
internal interface IDetector
|
||||||
|
{
|
||||||
|
bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable<DetectedOperation> operations);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal interface IOperationDetector : IDetector
|
||||||
|
{ }
|
||||||
|
|
||||||
|
internal interface IFragmentDetector: IDetector
|
||||||
|
{ }
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
using AsbCloudDb.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
internal class OperationDetector : IOperationDetector
|
||||||
|
{
|
||||||
|
private readonly int idOperation;
|
||||||
|
|
||||||
|
protected Func<DetectableTelemetry[], bool> isValid = (_) => true;
|
||||||
|
|
||||||
|
protected Func<DetectableTelemetry[], double> calcValue = (_) => 0d;
|
||||||
|
|
||||||
|
public OperationDetector(int idOperation)
|
||||||
|
{
|
||||||
|
this.idOperation = idOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, out IEnumerable<DetectedOperation> operations)
|
||||||
|
{
|
||||||
|
if(!telemetryFragment.Any() || !isValid(telemetryFragment))
|
||||||
|
{
|
||||||
|
operations = Enumerable.Empty<DetectedOperation>();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var operation = MakeOperation(idTelemetry, telemetryFragment);
|
||||||
|
|
||||||
|
operations = new List<DetectedOperation> { operation };
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetryFragment)
|
||||||
|
{
|
||||||
|
var pBegin = telemetryFragment.First();
|
||||||
|
var pEnd = telemetryFragment.Last();
|
||||||
|
var operation = new DetectedOperation
|
||||||
|
{
|
||||||
|
IdTelemetry = idTelemetry,
|
||||||
|
IdCategory = idOperation,
|
||||||
|
IdUsersAtStart = pBegin.IdUser ?? -1,
|
||||||
|
DateStart = pBegin.DateTime,
|
||||||
|
DateEnd = pEnd.DateTime,
|
||||||
|
DepthStart = (double)pBegin.WellDepth,
|
||||||
|
DepthEnd = (double)pEnd.WellDepth,
|
||||||
|
Value = calcValue(telemetryFragment),
|
||||||
|
};
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationDetector SetIsValidDelegate(Func<DetectableTelemetry[], bool> isValid)
|
||||||
|
{
|
||||||
|
this.isValid = isValid;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationDetector SetCalcValueDelegate(Func<DetectableTelemetry[], double> calcValue)
|
||||||
|
{
|
||||||
|
this.calcValue = calcValue;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
|
||||||
|
internal class OperationDrilling : OperationDetector
|
||||||
|
{
|
||||||
|
public OperationDrilling(int idOperation)
|
||||||
|
:base(idOperation)
|
||||||
|
{
|
||||||
|
isValid = (DetectableTelemetry[] telemetryFragment) =>
|
||||||
|
{
|
||||||
|
var pBegin = telemetryFragment.First();
|
||||||
|
var pEnd = telemetryFragment.Last();
|
||||||
|
if (pBegin.WellDepth >= pEnd.WellDepth)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
calcValue = (DetectableTelemetry[] telemetryFragment) =>
|
||||||
|
{
|
||||||
|
var pBegin = telemetryFragment.First();
|
||||||
|
var pEnd = telemetryFragment.Last();
|
||||||
|
var result = (double)(pEnd.WellDepth - pBegin.WellDepth) / (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
internal class OperationSlipsTime : OperationDetector
|
||||||
|
{
|
||||||
|
public OperationSlipsTime()
|
||||||
|
: base(14)
|
||||||
|
{
|
||||||
|
isValid = (DetectableTelemetry[] telemetryFragment) =>
|
||||||
|
{
|
||||||
|
var pBegin = telemetryFragment.First();
|
||||||
|
var pEnd = telemetryFragment.Last();
|
||||||
|
if (Math.Abs((double)(pBegin.WellDepth - pEnd.WellDepth)) > 0.01)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
calcValue = (DetectableTelemetry[] telemetryFragment) =>
|
||||||
|
{
|
||||||
|
var pBegin = telemetryFragment.First();
|
||||||
|
var pEnd = telemetryFragment.Last();
|
||||||
|
var result = (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
|
@ -46,10 +46,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
public bool IsYDecreases(double bound = 0d) =>
|
public bool IsYDecreases(double bound = 0d) =>
|
||||||
A < bound;
|
A < bound;
|
||||||
|
|
||||||
public bool IsAverageYLessThanBound(double bound) =>
|
public bool IsAverageYLessThan(double bound) =>
|
||||||
(ySum / count) < bound;
|
(ySum / count) < bound;
|
||||||
|
|
||||||
public bool IsAverageYMoreThanBound(double bound) =>
|
public bool IsAverageYGreaterThan(double bound) =>
|
||||||
(ySum / count) >= bound;
|
(ySum / count) >= bound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,31 +8,39 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations
|
namespace AsbCloudInfrastructure.Services.DetectOperations
|
||||||
{
|
{
|
||||||
public class OperationDetectionBackgroundService : BackgroundService
|
public class OperationDetectionBackgroundService : BackgroundService
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<DetectorAbstract> detectors = new List<DetectorAbstract>
|
private readonly int minStepLength = 3;
|
||||||
{
|
private readonly int minFragmentLength = 6;
|
||||||
new Detectors.DetectorSlipsTime(),
|
|
||||||
new Detectors.DetectorDrillingRotor(),
|
|
||||||
new Detectors.DetectorDrillingSlide(),
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly int minStepLength;
|
|
||||||
private readonly int minFragmentLength;
|
|
||||||
private readonly string connectionString;
|
private readonly string connectionString;
|
||||||
private readonly TimeSpan period = TimeSpan.FromHours(1);
|
private readonly TimeSpan period = TimeSpan.FromHours(1);
|
||||||
|
|
||||||
|
private static readonly Func<DetectableTelemetry[], int, bool> isBitAtTheBottom = FragmentDetector.MakeInstantDelegate(d => (double)(d.WellDepth - d.BitDepth) < 0.001d);
|
||||||
|
private static readonly Func<DetectableTelemetry[], int, bool> isPressureGt25 = FragmentDetector.MakeInstantDelegate(d => d.Pressure > 25);
|
||||||
|
private static readonly Func<DetectableTelemetry[], int, bool> isPressureLt15 = FragmentDetector.MakeInstantDelegate(d => d.Pressure < 15);
|
||||||
|
private static readonly Func<DetectableTelemetry[], int, bool> isBlockPositionLt8 = FragmentDetector.MakeInstantDelegate(d => d.BlockPosition < 8);
|
||||||
|
private static readonly Func<DetectableTelemetry[], int, bool> isHookWeightLt20 = FragmentDetector.MakeInstantDelegate(d => d.HookWeight < 20);
|
||||||
|
private static readonly Func<DetectableTelemetry[], int, bool> isRotorSpeedAvgGt5 = FragmentDetector.MakeInterpolationDelegate(d => (double)d.RotorSpeed, line => line.IsAverageYGreaterThan(5), 12);
|
||||||
|
private static readonly Func<DetectableTelemetry[], int, bool> isRotorSpeedAvgLt5 = FragmentDetector.MakeInterpolationDelegate(d => (double)d.RotorSpeed, line => line.IsAverageYLessThan(5), 12);
|
||||||
|
private static readonly List<IDetector> detectors = new List<IDetector>
|
||||||
|
{
|
||||||
|
new FragmentDetector(isBitAtTheBottom,
|
||||||
|
new FragmentDetector(isPressureGt25,
|
||||||
|
new FragmentDetector(isRotorSpeedAvgGt5, new OperationDrilling(3)),
|
||||||
|
new FragmentDetector(isRotorSpeedAvgLt5, new OperationDrilling(2))
|
||||||
|
),
|
||||||
|
new FragmentDetector(isPressureLt15,
|
||||||
|
new FragmentDetector(isBlockPositionLt8,
|
||||||
|
new FragmentDetector(isHookWeightLt20, new OperationSlipsTime())))
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
public OperationDetectionBackgroundService(IConfiguration configuration)
|
public OperationDetectionBackgroundService(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
minStepLength = detectors.Min(d => d.StepLength);
|
|
||||||
minStepLength = minStepLength > 0 ? minStepLength : 3;
|
|
||||||
|
|
||||||
minFragmentLength = detectors.Min(d => d.FragmentLength);
|
|
||||||
minFragmentLength = minFragmentLength > 0 ? minFragmentLength : 6;
|
|
||||||
|
|
||||||
connectionString = configuration.GetConnectionString("DefaultConnection");
|
connectionString = configuration.GetConnectionString("DefaultConnection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,70 +136,46 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
})
|
})
|
||||||
.OrderBy(d => d.DateTime);
|
.OrderBy(d => d.DateTime);
|
||||||
|
|
||||||
var take = 4 * 86_400;
|
var take = 4 * 86_400;// 4 дня
|
||||||
var startDate = begin;
|
var startDate = begin;
|
||||||
var detectedOperations = new List<DetectedOperation>(8);
|
var detectedOperations = new List<DetectedOperation>(8);
|
||||||
|
|
||||||
var dbRequests_ = 0;
|
|
||||||
var dbTime_ = 0d;
|
|
||||||
var sw_ = new Stopwatch();
|
|
||||||
var otherTime_ = 0d;
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
sw_.Restart();
|
|
||||||
var data = await query
|
var data = await query
|
||||||
.Where(d => d.DateTime > startDate)
|
.Where(d => d.DateTime > startDate)
|
||||||
.Take(take)
|
.Take(take)
|
||||||
.ToArrayAsync(token);
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
sw_.Stop();
|
|
||||||
dbTime_ += sw_.ElapsedMilliseconds;
|
|
||||||
dbRequests_++;
|
|
||||||
sw_.Restart();
|
|
||||||
|
|
||||||
if (data.Length < minFragmentLength)
|
if (data.Length < minFragmentLength)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var skip = 0;
|
|
||||||
|
|
||||||
var isDetected = false;
|
var isDetected = false;
|
||||||
|
|
||||||
while (data.Length > skip + minFragmentLength)
|
foreach (var detector in detectors)
|
||||||
{
|
{
|
||||||
var isDetected1 = false;
|
if (detector is FragmentDetector fragmentDetector)
|
||||||
|
|
||||||
foreach (var detector in detectors)
|
|
||||||
{
|
{
|
||||||
if (data.Length < skip + detector.StepLength + detector.FragmentLength)
|
var minLengthToDetect = fragmentDetector.StepLength + fragmentDetector.FragmentLength;
|
||||||
|
if (data.Length < minLengthToDetect)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var detectedOperation = detector.DetectOrDefault(data, ref skip);
|
if (fragmentDetector.TryDetect(idTelemetry, data, out IEnumerable<DetectedOperation> operations))
|
||||||
if (detectedOperation is not null)
|
|
||||||
{
|
{
|
||||||
isDetected1 = true;
|
|
||||||
isDetected = true;
|
isDetected = true;
|
||||||
detectedOperation.IdTelemetry = idTelemetry;
|
detectedOperations.AddRange(operations);
|
||||||
detectedOperations.Add(detectedOperation);
|
startDate = operations.Last().DateEnd;
|
||||||
startDate = detectedOperation.DateEnd;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDetected1)
|
|
||||||
skip += minStepLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sw_.Stop();
|
|
||||||
otherTime_ += sw_.ElapsedMilliseconds;
|
|
||||||
|
|
||||||
if (!isDetected)
|
if (!isDetected)
|
||||||
{
|
{
|
||||||
if (data.Length < take)
|
if (data.Length < take)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var lastPartDate = data.Last().DateTime;
|
startDate = startDate.AddSeconds(0.95 * take);
|
||||||
startDate = startDate + (0.75 * (lastPartDate - startDate));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user