forked from ddrilling/AsbCloudServer
операции определяются правильнее и быстрее
This commit is contained in:
commit
93c293a11c
@ -1,71 +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 position)
|
|
||||||
{
|
|
||||||
if ((telemetry.Length > position + FragmentLength + StepLength) && DetectStart(telemetry, position))
|
|
||||||
{
|
|
||||||
var skip = position + StepLength;
|
|
||||||
while (telemetry.Length > skip + FragmentLength)
|
|
||||||
{
|
|
||||||
if (DetectEnd(telemetry, skip))
|
|
||||||
{
|
|
||||||
var dateStart = telemetry[position].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[position].IdUser ?? -1,
|
|
||||||
DateStart = dateStart,
|
|
||||||
DateEnd = dateEnd,
|
|
||||||
DepthStart = telemetry[position].WellDepth ?? -1d,
|
|
||||||
DepthEnd = telemetry[skip].WellDepth ?? -1d,
|
|
||||||
};
|
|
||||||
CalcValue(ref result);
|
|
||||||
position = skip + FragmentLength;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
skip = skip + StepLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void CalcValue(ref DetectedOperation result);
|
|
||||||
|
|
||||||
protected abstract bool DetectStart(DetectableTelemetry[] telemetry, int position);
|
|
||||||
|
|
||||||
protected abstract bool DetectEnd(DetectableTelemetry[] telemetry, int position);
|
|
||||||
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
#nullable enable
|
|
||||||
class DetectorDrillingRotor : DetectorAbstract
|
|
||||||
{
|
|
||||||
const double minRop = 5; //м/час
|
|
||||||
const double minRotorSpeed = 5; //об/мин
|
|
||||||
const double ticksPerHour = 60 * 60 * 10_000_000d;
|
|
||||||
const double minPressure = 25;
|
|
||||||
const double minDeltaDepth = 0.02;
|
|
||||||
|
|
||||||
public DetectorDrillingRotor() : base(2)
|
|
||||||
{
|
|
||||||
FragmentLength = 15;
|
|
||||||
StepLength = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.RotorSpeed > minRotorSpeed)
|
|
||||||
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.Ticks / ticksPerHour)));
|
|
||||||
if (!lineBlockPosition.IsYDecreases(minRop))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var lineWellDepth = new InterpolationLine(fragment.Select(d => (d.WellDepth ?? 0d, d.DateTime.Ticks / ticksPerHour)));
|
|
||||||
if (!lineWellDepth.IsYIncreases(minRop))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position)
|
|
||||||
=> !DetectStart(telemetry, position);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Рассчитываем МСП, м/час
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="result"></param>
|
|
||||||
protected override void CalcValue(ref DetectedOperation result)
|
|
||||||
{
|
|
||||||
result.Value = (result.DepthEnd - result.DepthStart) / (result.DateEnd - result.DateStart).TotalHours;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|
||||||
{
|
|
||||||
#nullable enable
|
|
||||||
class DetectorDrillingSlide : DetectorAbstract
|
|
||||||
{
|
|
||||||
const double minRop = 5; //м/час
|
|
||||||
const double minRotorSpeed = 5; //об/мин
|
|
||||||
const double ticksPerHour = 60 * 60 * 10_000_000d;
|
|
||||||
const double minPressure = 25;
|
|
||||||
const double minDeltaDepth = 0.02;
|
|
||||||
|
|
||||||
public DetectorDrillingSlide() : base(3)
|
|
||||||
{
|
|
||||||
FragmentLength = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.RotorSpeed < minRotorSpeed)
|
|
||||||
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.Ticks / ticksPerHour)));
|
|
||||||
if (!lineBlockPosition.IsYDecreases(minRop))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var lineWellDepth = new InterpolationLine(fragment.Select(d => (d.WellDepth ?? 0d, d.DateTime.Ticks / ticksPerHour)));
|
|
||||||
if (!lineWellDepth.IsYIncreases(minRop))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position)
|
|
||||||
=> !DetectStart(telemetry, position);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Рассчитываем МСП, м/час
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="result"></param>
|
|
||||||
protected override void CalcValue(ref DetectedOperation result)
|
|
||||||
{
|
|
||||||
result.Value = (result.DepthEnd - result.DepthStart) / (result.DateEnd - result.DateStart).TotalHours;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -1,43 +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 void CalcValue(ref DetectedOperation result)
|
|
||||||
{
|
|
||||||
result.Value = result.DurationMinutes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
@ -0,0 +1,162 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
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 string Name { get; set; }
|
||||||
|
|
||||||
|
public int FragmentLength { get => fragmentLength; set => fragmentLength = value; }
|
||||||
|
public int StepLength { get => stepLength; set => stepLength = value; }
|
||||||
|
|
||||||
|
public FragmentDetector(
|
||||||
|
string name,
|
||||||
|
Func<DetectableTelemetry[], int, bool> detectStart,
|
||||||
|
IFragmentDetector detector,
|
||||||
|
params IFragmentDetector[] detectors)
|
||||||
|
{
|
||||||
|
this.detectStart = detectStart;
|
||||||
|
this.detectors = JoinDetectors(detector, detectors);
|
||||||
|
detectEnd = (f, i) => !detectStart(f, i);
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
public FragmentDetector(
|
||||||
|
string name,
|
||||||
|
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);
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FragmentDetector(
|
||||||
|
string name,
|
||||||
|
Func<DetectableTelemetry[], int, bool> detectStart,
|
||||||
|
IOperationDetector operation)
|
||||||
|
{
|
||||||
|
this.detectStart = detectStart;
|
||||||
|
detectors = new IOperationDetector[] { operation };
|
||||||
|
detectEnd = (f, i) => !detectStart(f, i);
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FragmentDetector(
|
||||||
|
string name,
|
||||||
|
Func<DetectableTelemetry[], int, bool> detectStart,
|
||||||
|
Func<DetectableTelemetry[], int, bool> detectEnd,
|
||||||
|
IOperationDetector operation)
|
||||||
|
{
|
||||||
|
this.detectStart = detectStart;
|
||||||
|
this.detectEnd = detectEnd;
|
||||||
|
detectors = new IOperationDetector[] { operation };
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 && (position + fragmentLength) < telemetry.Length)
|
||||||
|
data = telemetry[position..(position + fragmentLength)];
|
||||||
|
else
|
||||||
|
data = telemetry[position..];
|
||||||
|
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[] telemetry, int begin, int end, out IEnumerable<OperationDetectorResult> results)
|
||||||
|
{
|
||||||
|
List<OperationDetectorResult>? totaltResultList = null;
|
||||||
|
var positionBegin = begin;
|
||||||
|
// Поиск начала соответствия критерию начала операции
|
||||||
|
while (end > positionBegin + fragmentLength + stepLength)
|
||||||
|
{
|
||||||
|
if (detectStart(telemetry, positionBegin))
|
||||||
|
{
|
||||||
|
// Поиск окончания соответствия критерию
|
||||||
|
var positionEnd = positionBegin;
|
||||||
|
while (positionEnd < end)
|
||||||
|
{
|
||||||
|
positionEnd += stepLength;
|
||||||
|
if ((positionEnd > end))
|
||||||
|
positionEnd = end;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
positionBegin = positionEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
positionBegin += stepLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(totaltResultList?.Any() == true)
|
||||||
|
{
|
||||||
|
results = totaltResultList!;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
results = Enumerable.Empty<OperationDetectorResult>();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
=> $"frame detector {Name}";
|
||||||
|
}
|
||||||
|
#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, int begin, int end, out IEnumerable<OperationDetectorResult> 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
|
||||||
|
{
|
||||||
|
class OperationDetectorResult
|
||||||
|
{
|
||||||
|
public int TelemetryBegin { get; set; }
|
||||||
|
public int TelemetryEnd { get; set; }
|
||||||
|
public DetectedOperation Operation { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class OperationDetector : IOperationDetector
|
||||||
|
{
|
||||||
|
private readonly int idOperation;
|
||||||
|
|
||||||
|
protected Func<DetectableTelemetry[], int, int, bool> isValid = (_,_,_) => true;
|
||||||
|
|
||||||
|
protected Func<DetectableTelemetry[], int, int, double> calcValue = (_, _, _) => 0d;
|
||||||
|
|
||||||
|
public OperationDetector(int idOperation)
|
||||||
|
{
|
||||||
|
this.idOperation = idOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetryFragment, int begin, int end, out IEnumerable<OperationDetectorResult> operations)
|
||||||
|
{
|
||||||
|
if(!telemetryFragment.Any() || !isValid(telemetryFragment, begin, end))
|
||||||
|
{
|
||||||
|
operations = Enumerable.Empty<OperationDetectorResult>();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var operation = MakeOperation(idTelemetry, telemetryFragment, begin, end);
|
||||||
|
|
||||||
|
operations = new List<OperationDetectorResult> { operation };
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OperationDetectorResult MakeOperation(int idTelemetry, DetectableTelemetry[] telemetryFragment, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetryFragment[begin];
|
||||||
|
var pEnd = telemetryFragment[end];
|
||||||
|
var result = new OperationDetectorResult
|
||||||
|
{
|
||||||
|
TelemetryBegin = begin,
|
||||||
|
TelemetryEnd = end,
|
||||||
|
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, begin, end),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
|
{
|
||||||
|
|
||||||
|
internal class OperationDrilling : OperationDetector
|
||||||
|
{
|
||||||
|
public OperationDrilling(int idOperation)
|
||||||
|
:base(idOperation)
|
||||||
|
{
|
||||||
|
isValid = (DetectableTelemetry[] fragment, int begin, int end) =>
|
||||||
|
{
|
||||||
|
var pBegin = fragment[begin];
|
||||||
|
var pEnd = fragment[end];
|
||||||
|
if (pBegin.WellDepth >= pEnd.WellDepth)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
calcValue = (DetectableTelemetry[] fragment, int begin, int end) =>
|
||||||
|
{
|
||||||
|
var pBegin = fragment[begin];
|
||||||
|
var pEnd = fragment[end];
|
||||||
|
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[] fragment, int begin, int end) =>
|
||||||
|
{
|
||||||
|
var pBegin = fragment[begin];
|
||||||
|
var pEnd = fragment[end];
|
||||||
|
if (Math.Abs((double)(pBegin.WellDepth - pEnd.WellDepth)) > 0.01)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
calcValue = (DetectableTelemetry[] fragment, int begin, int end) =>
|
||||||
|
{
|
||||||
|
var pBegin = fragment[begin];
|
||||||
|
var pEnd = fragment[end];
|
||||||
|
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,48 @@ 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 stepLength = 3;
|
||||||
{
|
private readonly int fragmentLength = 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> isBitLt0_03mToBottom = FragmentDetector.MakeInstantDelegate(d =>
|
||||||
|
(double)(d.WellDepth - d.BitDepth) < 0.03d);
|
||||||
|
private static readonly Func<DetectableTelemetry[], int, bool> isBitLt2_5mToBottom = FragmentDetector.MakeInstantDelegate(d =>
|
||||||
|
(double)(d.WellDepth - d.BitDepth) < 2.5d);
|
||||||
|
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("isBitLt2_5mToBottom", isBitLt2_5mToBottom,
|
||||||
|
new FragmentDetector("isBitLt0_03mToBottom", isBitLt0_03mToBottom,
|
||||||
|
new FragmentDetector("isPressureGt25", isPressureGt25,
|
||||||
|
new FragmentDetector("isRotorSpeedAvgGt5", isRotorSpeedAvgGt5, new OperationDrilling(2)),
|
||||||
|
new FragmentDetector("isRotorSpeedAvgLt5", isRotorSpeedAvgLt5, new OperationDrilling(3)))),
|
||||||
|
new FragmentDetector("isPressureLt15", isPressureLt15,
|
||||||
|
new FragmentDetector("isBlockPositionLt8", isBlockPositionLt8,
|
||||||
|
new FragmentDetector("isHookWeightLt20", 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,7 +145,7 @@ 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);
|
||||||
|
|
||||||
@ -139,47 +156,42 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
.Take(take)
|
.Take(take)
|
||||||
.ToArrayAsync(token);
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
if (data.Length < minFragmentLength)
|
if (data.Length < 2 * fragmentLength + stepLength)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var skip = 0;
|
|
||||||
|
|
||||||
var isDetected = false;
|
var isDetected = false;
|
||||||
|
var positionBegin = 0;
|
||||||
while (data.Length > skip + minFragmentLength)
|
var positionEnd = data.Length - fragmentLength;
|
||||||
{
|
|
||||||
var isDetected1 = false;
|
|
||||||
|
|
||||||
foreach (var detector in detectors)
|
foreach (var detector in detectors)
|
||||||
{
|
{
|
||||||
if (data.Length < skip + detector.StepLength + detector.FragmentLength)
|
if (detector is FragmentDetector fragmentDetector)
|
||||||
|
{
|
||||||
|
var minLengthToDetect = fragmentDetector.StepLength + fragmentDetector.FragmentLength;
|
||||||
|
if (data.Length < positionBegin + minLengthToDetect)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var detectedOperation = detector.DetectOrDefault(data, ref skip);
|
if (fragmentDetector.TryDetect(idTelemetry, data, positionBegin, positionEnd, out IEnumerable<OperationDetectorResult> results))
|
||||||
if (detectedOperation is not null)
|
|
||||||
{
|
{
|
||||||
isDetected1 = true;
|
|
||||||
isDetected = true;
|
isDetected = true;
|
||||||
detectedOperation.IdTelemetry = idTelemetry;
|
var operations = results.Select(r => r.Operation);
|
||||||
detectedOperations.Add(detectedOperation);
|
detectedOperations.AddRange(operations);
|
||||||
startDate = detectedOperation.DateEnd;
|
positionBegin = results.Max(r=>r.TelemetryEnd) + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDetected1)
|
|
||||||
skip += minStepLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDetected)
|
if (isDetected)
|
||||||
{
|
{
|
||||||
var i = skip - minFragmentLength;
|
startDate = detectedOperations.Max(o => o.DateEnd);
|
||||||
i = i > data.Length
|
}
|
||||||
? data.Length - minStepLength
|
else
|
||||||
: i;
|
{
|
||||||
i = i < minFragmentLength
|
int i = positionEnd - (int)(data.Length * 0.8);
|
||||||
? minFragmentLength
|
if (i < 0)
|
||||||
: i;
|
break;
|
||||||
|
|
||||||
startDate = data[i].DateTime;
|
startDate = data[i].DateTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,26 @@ namespace ConsoleApp1
|
|||||||
// use ServiceFactory to make services
|
// use ServiceFactory to make services
|
||||||
static void Main(/*string[] args*/)
|
static void Main(/*string[] args*/)
|
||||||
{
|
{
|
||||||
|
System.Collections.Generic.List<(double, double)> data = new() {
|
||||||
|
(22.52400016784668, 17715023.435277779) ,
|
||||||
|
(22.52400016784668, 17715023.435555555) ,
|
||||||
|
(22.52400016784668, 17715023.435833335) ,
|
||||||
|
(22.52400016784668, 17715023.436111111) ,
|
||||||
|
(22.547000885009766, 17715023.436388887) ,
|
||||||
|
(22.833000183105469, 17715023.436666667) ,
|
||||||
|
(23.063999176025391, 17715023.436944444) ,
|
||||||
|
(23.298999786376953, 17715023.437222224) ,
|
||||||
|
(23.5310001373291, 17715023.4375) ,
|
||||||
|
(23.763999938964844, 17715023.437777776) ,
|
||||||
|
(23.993999481201172, 17715023.438055556) ,
|
||||||
|
(24.229999542236328, 17715023.438333333) ,
|
||||||
|
(24.459999084472656, 17715023.438611113) ,
|
||||||
|
(24.694999694824219, 17715023.438888889) ,
|
||||||
|
(24.926000595092773, 17715023.439166665) ,
|
||||||
|
};
|
||||||
|
|
||||||
|
var il = new AsbCloudInfrastructure.Services.DetectOperations.InterpolationLine(data);
|
||||||
|
|
||||||
Console.WriteLine("hit keyboard to start");
|
Console.WriteLine("hit keyboard to start");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"profiles": {
|
|
||||||
"WSL": {
|
|
||||||
"commandName": "WSL2",
|
|
||||||
"distributionName": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user