forked from ddrilling/AsbCloudServer
Новые алгоритмы авто определения операций. Отладочный вариант
This commit is contained in:
parent
33ac04b304
commit
909f8abb4d
@ -5,9 +5,8 @@ using System.Linq;
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
internal abstract class DetectorAbstract
|
||||
public abstract class DetectorAbstract
|
||||
{
|
||||
private readonly int idOperation;
|
||||
private readonly int stepLength = 3;
|
||||
|
||||
protected const int IdReasonOfEnd_NotDetected = 0;
|
||||
@ -32,12 +31,11 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
protected const int IdReasonOfEnd_BlockPositionIsHi = 501;
|
||||
protected const int IdReasonOfEnd_BlockPositionDeviates = 502;
|
||||
|
||||
protected const int IdReasonOfEnd_Drilling = 600;
|
||||
|
||||
protected const int IdReasonOfEnd_Custom1 = 10_000;
|
||||
|
||||
protected DetectorAbstract(int idOperation)
|
||||
{
|
||||
this.idOperation = idOperation;
|
||||
}
|
||||
public abstract Func<DetectableTelemetry[], int, int, int> GetIdOperation { get; }
|
||||
|
||||
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation, out OperationDetectorResult? result)
|
||||
{
|
||||
@ -45,21 +43,28 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
if (DetectBegin(telemetry, begin, previousOperation))
|
||||
{
|
||||
// Поиск окончания соответствия критерию
|
||||
int idReasonOfEnd = 0;
|
||||
var positionEnd = begin;
|
||||
while (positionEnd < end)
|
||||
{
|
||||
positionEnd += stepLength;
|
||||
if ((positionEnd > end))
|
||||
if (positionEnd > end)
|
||||
break;
|
||||
|
||||
idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation);
|
||||
|
||||
if(idReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo &&
|
||||
!IsValidByWellDepthDoesNotChange(telemetry, begin, positionEnd))
|
||||
break;
|
||||
|
||||
var idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation);
|
||||
if (idReasonOfEnd != IdReasonOfEnd_NotDetected)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = null;
|
||||
result = MakeOperation(idTelemetry, telemetry, begin, positionEnd, idReasonOfEnd);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
@ -81,7 +86,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
Operation = new DetectedOperation
|
||||
{
|
||||
IdTelemetry = idTelemetry,
|
||||
IdCategory = idOperation,
|
||||
IdCategory = GetIdOperation.Invoke(telemetry, begin, end),
|
||||
IdUsersAtStart = pBegin.IdUser ?? -1,
|
||||
DateStart = pBegin.DateTime,
|
||||
DateEnd = pEnd.DateTime,
|
||||
|
@ -1,4 +1,5 @@
|
||||
using AsbCloudDb.Model;
|
||||
using System;
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
@ -8,12 +9,12 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
/// </summary>
|
||||
internal class DetectorDevelopment : DetectorAbstract
|
||||
{
|
||||
public DetectorDevelopment()
|
||||
: base(WellOperationCategory.IdDevelopment) { }
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
|
||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _)
|
||||
=> WellOperationCategory.IdDevelopment;
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
if (previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime)
|
||||
|
@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||
|
||||
public class DetectorDrilling : DetectorAbstract
|
||||
{
|
||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => DefineDrillingOperation;
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 0.03d)
|
||||
return false;
|
||||
|
||||
if (point0.Pressure < 25)
|
||||
return false;
|
||||
|
||||
if (point0.RotorSpeed < 5)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
|
||||
if (delta > 0.03d)
|
||||
return IdReasonOfEnd_DeltaDepthIsHi;
|
||||
|
||||
if (point0.Pressure < 25)
|
||||
return IdReasonOfEnd_PressureIsLo;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthIncreasing(telemetry, begin, end);
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcRop(telemetry, begin, end);
|
||||
|
||||
private static int DefineDrillingOperation(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
{
|
||||
const int idSlideWithOscillation = 12000;
|
||||
|
||||
var telemetryRange = telemetry[begin.. end];
|
||||
|
||||
var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed);
|
||||
|
||||
if (avgRotorSpeed < 10)
|
||||
return WellOperationCategory.IdSlide;
|
||||
|
||||
var despersion = telemetryRange
|
||||
.Average(t => Math.Pow((t.RotorSpeed - avgRotorSpeed) / avgRotorSpeed, 2));
|
||||
|
||||
return despersion < 0.2d ? WellOperationCategory.IdRotor : idSlideWithOscillation;
|
||||
}
|
||||
}
|
@ -1,59 +1,59 @@
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Промывка
|
||||
/// </summary>
|
||||
internal class DetectorFlashing : DetectorAbstract
|
||||
{
|
||||
public DetectorFlashing()
|
||||
: base(WellOperationCategory.IdFlashing)
|
||||
{ }
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
if (!((previousOperation?.IdCategory == WellOperationCategory.IdRotor) ||
|
||||
(previousOperation?.IdCategory == WellOperationCategory.IdSlide)))
|
||||
return false;
|
||||
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 0.05d)
|
||||
return false;
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return false;
|
||||
|
||||
if (point0.BlockPosition < 3)
|
||||
return false;
|
||||
|
||||
if (ContainsDeviationApprox(telemetry, t => t.WellDepth, position, 150, 0.0001))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if ((delta > 0.03d )
|
||||
&& (point0.Pressure > 15)
|
||||
&& ContainsDeviationApprox(telemetry, t=>t.BlockPosition, position, 60, 0.03))
|
||||
return IdReasonOfEnd_Custom1;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using AsbCloudDb.Model;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Промывка
|
||||
// /// </summary>
|
||||
// internal class DetectorFlashing : DetectorAbstract
|
||||
// {
|
||||
// public DetectorFlashing()
|
||||
// : base(WellOperationCategory.IdFlashing)
|
||||
// { }
|
||||
//
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcDeltaMinutes(telemetry, begin, end);
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// if (!((previousOperation?.IdCategory == WellOperationCategory.IdRotor) ||
|
||||
// (previousOperation?.IdCategory == WellOperationCategory.IdSlide)))
|
||||
// return false;
|
||||
//
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 0.05d)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.BlockPosition < 3)
|
||||
// return false;
|
||||
//
|
||||
// if (ContainsDeviationApprox(telemetry, t => t.WellDepth, position, 150, 0.0001))
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if ((delta > 0.03d )
|
||||
// && (point0.Pressure > 15)
|
||||
// && ContainsDeviationApprox(telemetry, t=>t.BlockPosition, position, 60, 0.03))
|
||||
// return IdReasonOfEnd_Custom1;
|
||||
//
|
||||
// return IdReasonOfEnd_NotDetected;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
@ -1,55 +1,55 @@
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Промывка перед наращиванием
|
||||
/// </summary>
|
||||
internal class DetectorFlashingBeforeConnection : DetectorAbstract
|
||||
{
|
||||
public DetectorFlashingBeforeConnection()
|
||||
: base(WellOperationCategory.IdFlashingBeforeConnection) { }
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
if (!((previousOperation?.IdCategory == WellOperationCategory.IdRotor) ||
|
||||
(previousOperation?.IdCategory == WellOperationCategory.IdSlide)))
|
||||
return false;
|
||||
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 0.05d)
|
||||
return false;
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return false;
|
||||
|
||||
if (point0.BlockPosition > 3)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if ((delta > 0.03d )
|
||||
&& (point0.Pressure > 15)
|
||||
&& ContainsDeviationApprox(telemetry, t=>t.BlockPosition, position, 60, 0.03))
|
||||
return IdReasonOfEnd_Custom1;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using AsbCloudDb.Model;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Промывка перед наращиванием
|
||||
// /// </summary>
|
||||
// internal class DetectorFlashingBeforeConnection : DetectorAbstract
|
||||
// {
|
||||
// public DetectorFlashingBeforeConnection()
|
||||
// : base(WellOperationCategory.IdFlashingBeforeConnection) { }
|
||||
//
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcDeltaMinutes(telemetry, begin, end);
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// if (!((previousOperation?.IdCategory == WellOperationCategory.IdRotor) ||
|
||||
// (previousOperation?.IdCategory == WellOperationCategory.IdSlide)))
|
||||
// return false;
|
||||
//
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 0.05d)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.BlockPosition > 3)
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if ((delta > 0.03d )
|
||||
// && (point0.Pressure > 15)
|
||||
// && ContainsDeviationApprox(telemetry, t=>t.BlockPosition, position, 60, 0.03))
|
||||
// return IdReasonOfEnd_Custom1;
|
||||
//
|
||||
// return IdReasonOfEnd_NotDetected;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
@ -1,62 +1,54 @@
|
||||
using AsbCloudDb.Model;
|
||||
using System.Linq;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
internal class DetectorRotor : DetectorAbstract
|
||||
{
|
||||
public DetectorRotor()
|
||||
: base(WellOperationCategory.IdRotor) { }
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 0.03d)
|
||||
return false;
|
||||
|
||||
if (point0.Pressure < 25)
|
||||
return false;
|
||||
|
||||
if (point0.RotorSpeed < 5)
|
||||
return false;
|
||||
|
||||
var point1 = telemetry[position + 1];
|
||||
if (point1.WellDepth - point0.WellDepth <= 0.003)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 0.03d)
|
||||
return IdReasonOfEnd_DeltaDepthIsHi;
|
||||
|
||||
if (point0.Pressure < 25)
|
||||
return IdReasonOfEnd_PressureIsLo;
|
||||
|
||||
var avgRotorSpeed = CalcAvgAppr(d => d.RotorSpeed, telemetry, position, 60);
|
||||
|
||||
if (avgRotorSpeed < 10)
|
||||
return IdReasonOfEnd_AvgRotorSpeedIsLo;
|
||||
|
||||
if (!DeviatesFromBegin(telemetry, t => t.WellDepth, position, 150, 0.003))
|
||||
return IdReasonOfEnd_WellDepthDeviates;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthIncreasing(telemetry, begin, end);
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcRop(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using AsbCloudDb.Model;
|
||||
// using System.Linq;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
// public class DetectorRotor : DetectorAbstract
|
||||
// {
|
||||
// public DetectorRotor()
|
||||
// : base(WellOperationCategory.IdRotor) { }
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 0.03d)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.Pressure < 25)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.RotorSpeed < 5)
|
||||
// return false;
|
||||
//
|
||||
// var point1 = telemetry[position + 1];
|
||||
// if (point1.WellDepth - point0.WellDepth <= 0.003)
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 0.03d)
|
||||
// return IdReasonOfEnd_DeltaDepthIsHi;
|
||||
//
|
||||
// if (point0.Pressure < 25)
|
||||
// return IdReasonOfEnd_PressureIsLo;
|
||||
//
|
||||
// return IdReasonOfEnd_NotDetected;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthIncreasing(telemetry, begin, end);
|
||||
//
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcRop(telemetry, begin, end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
@ -1,61 +1,49 @@
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
internal class DetectorSlide : DetectorAbstract
|
||||
{
|
||||
public DetectorSlide()
|
||||
: base(WellOperationCategory.IdSlide) { }
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 0.03d)
|
||||
return false;
|
||||
|
||||
if (point0.Pressure < 25)
|
||||
return false;
|
||||
|
||||
if (point0.RotorSpeed > 5)
|
||||
return false;
|
||||
|
||||
var point1 = telemetry[position + 1];
|
||||
if (point1.WellDepth - point0.WellDepth <= 0.003)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 0.03d)
|
||||
return IdReasonOfEnd_DeltaDepthIsHi;
|
||||
|
||||
if (point0.Pressure < 25)
|
||||
return IdReasonOfEnd_PressureIsLo;
|
||||
|
||||
var avgRotorSpeed = CalcAvgAppr(d => d.RotorSpeed, telemetry, position, 60);
|
||||
|
||||
if (avgRotorSpeed > 10)
|
||||
return IdReasonOfEnd_AvgRotorSpeedIsHi;
|
||||
|
||||
if (!DeviatesFromBegin(telemetry, t => t.WellDepth, position, 150, 0.003))
|
||||
return IdReasonOfEnd_WellDepthDeviates;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthIncreasing(telemetry, begin, end);
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcRop(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using AsbCloudDb.Model;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
// public class DetectorSlide : DetectorAbstract
|
||||
// {
|
||||
// public DetectorSlide()
|
||||
// : base(WellOperationCategory.IdSlide) { }
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 0.03d)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.Pressure < 25)
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 0.03d)
|
||||
// return IdReasonOfEnd_DeltaDepthIsHi;
|
||||
//
|
||||
// if (point0.Pressure < 25)
|
||||
// return IdReasonOfEnd_PressureIsLo;
|
||||
//
|
||||
// if (!DeviatesFromBegin(telemetry, t => t.WellDepth, position, 150, 0.003))
|
||||
// return IdReasonOfEnd_WellDepthDeviates;
|
||||
//
|
||||
// return IdReasonOfEnd_NotDetected;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthIncreasing(telemetry, begin, end);
|
||||
//
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcRop(telemetry, begin, end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
@ -1,17 +1,16 @@
|
||||
using AsbCloudDb.Model;
|
||||
using System;
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
internal class DetectorSlipsTime : DetectorAbstract
|
||||
public class DetectorSlipsTime : DetectorAbstract
|
||||
{
|
||||
public DetectorSlipsTime()
|
||||
: base(WellOperationCategory.IdSlipsTime)
|
||||
{ }
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
|
||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime;
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
|
@ -1,69 +1,69 @@
|
||||
using AsbCloudDb.Model;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Статический замер телесистемы
|
||||
/// </summary>
|
||||
internal class DetectorStaticSurveying: DetectorAbstract
|
||||
{
|
||||
public DetectorStaticSurveying()
|
||||
: base(WellOperationCategory.IdStaticSurveying) { }
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return false;
|
||||
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 2.5d || delta < 0.15d)
|
||||
return false;
|
||||
|
||||
if (point0.RotorSpeed > 30)
|
||||
return false;
|
||||
|
||||
if (ContainsDeviation(telemetry, t => t.BlockPosition, position, 120, 0.03))
|
||||
return false;
|
||||
|
||||
if (ContainsDeviation(telemetry, t => t.Pressure, position, 60, 10))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta > 2.5d )
|
||||
return IdReasonOfEnd_DeltaDepthIsHi;
|
||||
|
||||
if (point0.RotorSpeed > 30)
|
||||
return IdReasonOfEnd_RotorSpeedIsHi;
|
||||
|
||||
if (RisesFromBegin(telemetry, t => t.Pressure, position, 10, 15))
|
||||
return IdReasonOfEnd_PressureIsRising;
|
||||
|
||||
if (ContainsDeviation(telemetry, t => t.BlockPosition, position, 10, 0.05))
|
||||
return IdReasonOfEnd_BlockPositionDeviates;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using AsbCloudDb.Model;
|
||||
// using System.Linq;
|
||||
// using System;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Статический замер телесистемы
|
||||
// /// </summary>
|
||||
// internal class DetectorStaticSurveying: DetectorAbstract
|
||||
// {
|
||||
// public DetectorStaticSurveying()
|
||||
// : base(WellOperationCategory.IdStaticSurveying) { }
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return false;
|
||||
//
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 2.5d || delta < 0.15d)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.RotorSpeed > 30)
|
||||
// return false;
|
||||
//
|
||||
// if (ContainsDeviation(telemetry, t => t.BlockPosition, position, 120, 0.03))
|
||||
// return false;
|
||||
//
|
||||
// if (ContainsDeviation(telemetry, t => t.Pressure, position, 60, 10))
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
//
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta > 2.5d )
|
||||
// return IdReasonOfEnd_DeltaDepthIsHi;
|
||||
//
|
||||
// if (point0.RotorSpeed > 30)
|
||||
// return IdReasonOfEnd_RotorSpeedIsHi;
|
||||
//
|
||||
// if (RisesFromBegin(telemetry, t => t.Pressure, position, 10, 15))
|
||||
// return IdReasonOfEnd_PressureIsRising;
|
||||
//
|
||||
// if (ContainsDeviation(telemetry, t => t.BlockPosition, position, 10, 0.05))
|
||||
// return IdReasonOfEnd_BlockPositionDeviates;
|
||||
//
|
||||
// return IdReasonOfEnd_NotDetected;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
//
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcDeltaMinutes(telemetry, begin, end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
@ -1,65 +1,65 @@
|
||||
using AsbCloudDb.Model;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
internal class DetectorTemplating : DetectorAbstract
|
||||
{
|
||||
public DetectorTemplating()
|
||||
: base(WellOperationCategory.IdTemplating) { }
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
if(previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime)
|
||||
return false;
|
||||
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta < 0.03d || delta > 30)
|
||||
return false;
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return false;
|
||||
|
||||
if (point0.BlockPosition > 2.5)
|
||||
return false;
|
||||
|
||||
if (point0.RotorSpeed > 10)
|
||||
return false;
|
||||
|
||||
if (!ContainsDeviationApprox(telemetry, d => d.BlockPosition, position, 60, 0.03))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if (delta < 0.03d || delta > 30)
|
||||
return IdReasonOfEnd_DeltaDepthOutOfRange;
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return IdReasonOfEnd_PressureIsLo;
|
||||
|
||||
if (point0.BlockPosition > 31)
|
||||
return IdReasonOfEnd_BlockPositionIsHi;
|
||||
|
||||
if (point0.RotorSpeed > 10)
|
||||
return IdReasonOfEnd_RotorSpeedIsHi;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using AsbCloudDb.Model;
|
||||
// using System.Collections.Generic;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
// internal class DetectorTemplating : DetectorAbstract
|
||||
// {
|
||||
// public DetectorTemplating()
|
||||
// : base(WellOperationCategory.IdTemplating) { }
|
||||
//
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcDeltaMinutes(telemetry, begin, end);
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// if(previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime)
|
||||
// return false;
|
||||
//
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta < 0.03d || delta > 30)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.BlockPosition > 2.5)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.RotorSpeed > 10)
|
||||
// return false;
|
||||
//
|
||||
// if (!ContainsDeviationApprox(telemetry, d => d.BlockPosition, position, 60, 0.03))
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if (delta < 0.03d || delta > 30)
|
||||
// return IdReasonOfEnd_DeltaDepthOutOfRange;
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return IdReasonOfEnd_PressureIsLo;
|
||||
//
|
||||
// if (point0.BlockPosition > 31)
|
||||
// return IdReasonOfEnd_BlockPositionIsHi;
|
||||
//
|
||||
// if (point0.RotorSpeed > 10)
|
||||
// return IdReasonOfEnd_RotorSpeedIsHi;
|
||||
//
|
||||
// return IdReasonOfEnd_NotDetected;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
@ -1,61 +1,61 @@
|
||||
using AsbCloudDb.Model;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Шаблонировка при бурении
|
||||
/// </summary>
|
||||
internal class DetectorTemplatingWhileDrilling : DetectorAbstract
|
||||
{
|
||||
public DetectorTemplatingWhileDrilling()
|
||||
: base(WellOperationCategory.IdTemplatingWhileDrilling) { }
|
||||
|
||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||
|
||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
if (previousOperation?.IdCategory != WellOperationCategory.IdFlashing)
|
||||
return false;
|
||||
|
||||
var point0 = telemetry[position];
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return false;
|
||||
|
||||
if (point0.RotorSpeed < 1)
|
||||
return false;
|
||||
|
||||
if (RisesFromBegin(telemetry, t => t.BlockPosition, position, 30, 0.5))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
{
|
||||
var point0 = telemetry[position];
|
||||
|
||||
if (point0.Pressure < 15)
|
||||
return IdReasonOfEnd_PressureIsLo;
|
||||
|
||||
if (RisesFromBegin(telemetry, t=>t.WellDepth, position, 10, 0.01))
|
||||
return IdReasonOfEnd_WellDepthDeviates;
|
||||
|
||||
var delta = point0.WellDepth - point0.BitDepth;
|
||||
if ( (delta > 0.03d )
|
||||
&& (point0.Pressure > 15)
|
||||
&& (!ContainsDeviationApprox(telemetry, t=>t.BlockPosition, position, 60, 0.03)))
|
||||
return IdReasonOfEnd_Custom1;
|
||||
|
||||
return IdReasonOfEnd_NotDetected;
|
||||
}
|
||||
|
||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// using AsbCloudDb.Model;
|
||||
//
|
||||
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
// {
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Шаблонировка при бурении
|
||||
// /// </summary>
|
||||
// internal class DetectorTemplatingWhileDrilling : DetectorAbstract
|
||||
// {
|
||||
// public DetectorTemplatingWhileDrilling()
|
||||
// : base(WellOperationCategory.IdTemplatingWhileDrilling) { }
|
||||
//
|
||||
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => CalcDeltaMinutes(telemetry, begin, end);
|
||||
//
|
||||
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// if (previousOperation?.IdCategory != WellOperationCategory.IdFlashing)
|
||||
// return false;
|
||||
//
|
||||
// var point0 = telemetry[position];
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return false;
|
||||
//
|
||||
// if (point0.RotorSpeed < 1)
|
||||
// return false;
|
||||
//
|
||||
// if (RisesFromBegin(telemetry, t => t.BlockPosition, position, 30, 0.5))
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||
// {
|
||||
// var point0 = telemetry[position];
|
||||
//
|
||||
// if (point0.Pressure < 15)
|
||||
// return IdReasonOfEnd_PressureIsLo;
|
||||
//
|
||||
// if (RisesFromBegin(telemetry, t=>t.WellDepth, position, 10, 0.01))
|
||||
// return IdReasonOfEnd_WellDepthDeviates;
|
||||
//
|
||||
// var delta = point0.WellDepth - point0.BitDepth;
|
||||
// if ( (delta > 0.03d )
|
||||
// && (point0.Pressure > 15)
|
||||
// && (!ContainsDeviationApprox(telemetry, t=>t.BlockPosition, position, 60, 0.03)))
|
||||
// return IdReasonOfEnd_Custom1;
|
||||
//
|
||||
// return IdReasonOfEnd_NotDetected;
|
||||
// }
|
||||
//
|
||||
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||
// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
@ -3,11 +3,10 @@
|
||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||
{
|
||||
|
||||
class OperationDetectorResult
|
||||
public class OperationDetectorResult
|
||||
{
|
||||
public int TelemetryBegin { get; set; }
|
||||
public int TelemetryEnd { get; set; }
|
||||
public DetectedOperation Operation { get; set; } = null!;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,22 +1,29 @@
|
||||
# Алгоритм определения бурения в роторе
|
||||
## Описание
|
||||
|
||||
## Метод определения бурения в роторе
|
||||
Метод определения бурения
|
||||
|
||||
Признак начала операции =
|
||||
( расстояние от долота до забоя < 0.03м ) И
|
||||
( давление > 25атм ) И
|
||||
( глубина забоя за следующую секунду больше текущей на 0.003м ) И
|
||||
( обороты ротора > 5 об/м );
|
||||
|
||||
расстояние от долота до забоя < 0.03м И
|
||||
|
||||
давление > 25атм
|
||||
|
||||
Признак окончания операции =
|
||||
( расстояние от долота до забоя > 0.03м ) ИЛИ
|
||||
( давление < 25атм ) ИЛИ
|
||||
( среднее арифметическое оборотов ротора за 60 сек < 10 об/м ) ИЛИ
|
||||
( глубина забоя в течении следующих 150 сек не изменяется больше чем на 0.003 );
|
||||
|
||||
## Метод определения бурения в слайде
|
||||
Повторяет метод определения бурения в роторе, за исключением условия с оборотами ротора. Это уловие нужно инвертировать.
|
||||
расстояние от долота до забоя > 0.03м ИЛИ
|
||||
|
||||
## Ключевой параметр
|
||||
МСП = разность глубины забоя на конец и начало операции / продолжительность операции.
|
||||
давление < 25атм
|
||||
|
||||
Находим границы
|
||||
|
||||
После того когда мы нашли границы, мы должны определить операцию, тогда мы смотрим на забой точки окончания операций сравниваем с забоем точками начала операций:
|
||||
|
||||
Если они равны друг другу, то мы эту операцию дальше не обрабатываем, а выбрасываем.
|
||||
|
||||
Если они не равны, то у нас произошло увеличение забоя, значит эта операция бурения.
|
||||
|
||||
Дальше мы определяем как мы бурили в роторе или слайде, для этого нам необходимо рассчитать среднюю скорость(среднее арифметическое) за всю операцию бурения . Если среднее арифметическое больше константы (10 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде.
|
||||
|
||||
Если бурение в роторе, то мы считаем только дисперсию нормированных оборотов ротора(по среднему значению). (Так как это может быть бурение в слайде с осцилляцией и выглядеть как бурение в роторе):
|
||||
|
||||
Если полученное значение меньше константы(0,2), то мы подтвердили что бурение в роторе.
|
||||
|
||||
Если полученное значение больше константы, то это бурение в слайде с осцилляцией.
|
@ -16,8 +16,8 @@ public class WorkOperationDetection: Work
|
||||
{
|
||||
private static readonly DetectorAbstract[] detectors = new DetectorAbstract[]
|
||||
{
|
||||
new DetectorRotor(),
|
||||
new DetectorSlide(),
|
||||
// new DetectorRotor(),
|
||||
// new DetectorSlide(),
|
||||
//new DetectorDevelopment(),
|
||||
//new DetectorTemplating(),
|
||||
new DetectorSlipsTime(),
|
||||
|
@ -23,6 +23,10 @@
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="DetectedOperations\Files\Operations.xlsx" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Connected Services" />
|
||||
|
227
ConsoleApp1/DetectedOperations/DetectedOperationExportService.cs
Normal file
227
ConsoleApp1/DetectedOperations/DetectedOperationExportService.cs
Normal file
@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure;
|
||||
using AsbCloudInfrastructure.Services.DetectOperations;
|
||||
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||
using ClosedXML.Excel;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ConsoleApp1.DetectedOperations;
|
||||
|
||||
public class DetectedOperationExportService
|
||||
{
|
||||
private static readonly DetectorAbstract[] detectors = new DetectorAbstract[]
|
||||
{
|
||||
new DetectorDrilling(),
|
||||
new DetectorSlipsTime(),
|
||||
};
|
||||
|
||||
private const int headerRowsCount = 1;
|
||||
|
||||
private const string cellDepositName = "B1";
|
||||
private const string cellClusterName = "B2";
|
||||
private const string cellWellName = "B3";
|
||||
private const string cellDeltaDate = "H2";
|
||||
|
||||
private const int columnOperationName = 1;
|
||||
private const int columnDateStart = 2;
|
||||
private const int columnDateEnd = 3;
|
||||
private const int columnDuration = 4;
|
||||
private const int columnDepthStart = 5;
|
||||
private const int columnDepthEnd = 6;
|
||||
private const int columnDeltaDepth = 7;
|
||||
private const int columnDepth = 8;
|
||||
private const int columnIdReasonOfEnd = 9;
|
||||
|
||||
private readonly IAsbCloudDbContext dbContext;
|
||||
|
||||
public DetectedOperationExportService(IAsbCloudDbContext dbContext)
|
||||
{
|
||||
this.dbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task Export(int idWell, CancellationToken cancellationToken)
|
||||
{
|
||||
var well = await dbContext.Wells
|
||||
.Include(w => w.Cluster)
|
||||
.ThenInclude(c => c.Deposit)
|
||||
.SingleOrDefaultAsync(w => w.Id == idWell, cancellationToken);
|
||||
|
||||
if (well is null)
|
||||
throw new ArgumentNullException(nameof(well));
|
||||
|
||||
if (!well.IdTelemetry.HasValue)
|
||||
throw new ArgumentNullException(nameof(well));
|
||||
|
||||
var operations = await DetectOperationsAsync(well.IdTelemetry.Value, new DateTime(2023, 10,14)
|
||||
.ToUtcDateTimeOffset(well.Timezone.Hours), cancellationToken);
|
||||
|
||||
var stream = await GenerateExcelFileStreamAsync(well, operations, cancellationToken);
|
||||
|
||||
using var fileStream = File.Create("DetectedOperations.xlsx");
|
||||
|
||||
stream.CopyTo(fileStream);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<DetectedOperation>> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin, CancellationToken token)
|
||||
{
|
||||
var query = dbContext.TelemetryDataSaub
|
||||
.AsNoTracking()
|
||||
.Where(d => d.IdTelemetry == idTelemetry)
|
||||
.Where(d => d.BlockPosition >= 0)
|
||||
.Select(d => new DetectableTelemetry
|
||||
{
|
||||
DateTime = d.DateTime,
|
||||
IdUser = d.IdUser,
|
||||
WellDepth = d.WellDepth ?? float.NaN,
|
||||
Pressure = d.Pressure ?? float.NaN,
|
||||
HookWeight = d.HookWeight ?? float.NaN,
|
||||
BlockPosition = d.BlockPosition ?? float.NaN,
|
||||
BitDepth = d.BitDepth ?? float.NaN,
|
||||
RotorSpeed = d.RotorSpeed ?? float.NaN,
|
||||
})
|
||||
.OrderBy(d => d.DateTime);
|
||||
|
||||
int take = 4 * 86_400; // 4 дня
|
||||
var startDate = begin;
|
||||
var detectedOperations = new List<DetectedOperation>(8);
|
||||
DetectedOperation? lastDetectedOperation = null;
|
||||
const int minOperationLength = 5;
|
||||
const int maxDetectorsInterpolationFrameLength = 30;
|
||||
const int gap = maxDetectorsInterpolationFrameLength + minOperationLength;
|
||||
|
||||
while (true)
|
||||
{
|
||||
var data = await query
|
||||
.Where(d => d.DateTime > startDate)
|
||||
.Take(take)
|
||||
.ToArrayAsync(token);
|
||||
|
||||
if (data.Length < gap)
|
||||
break;
|
||||
|
||||
bool isDetected = false;
|
||||
int positionBegin = 0;
|
||||
int positionEnd = data.Length - gap;
|
||||
int step = 10;
|
||||
while (positionEnd > positionBegin)
|
||||
{
|
||||
step++;
|
||||
for (int i = 0; i < detectors.Length; i++)
|
||||
{
|
||||
if (detectors[i].TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result))
|
||||
{
|
||||
detectedOperations.Add(result!.Operation);
|
||||
lastDetectedOperation = result.Operation;
|
||||
isDetected = true;
|
||||
step = 1;
|
||||
positionBegin = result.TelemetryEnd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (step > 20)
|
||||
step = 10;
|
||||
positionBegin += step;
|
||||
}
|
||||
|
||||
if (isDetected)
|
||||
startDate = lastDetectedOperation!.DateEnd;
|
||||
else
|
||||
startDate = data[positionEnd].DateTime;
|
||||
}
|
||||
|
||||
return detectedOperations;
|
||||
}
|
||||
|
||||
private async Task<Stream> GenerateExcelFileStreamAsync(Well well, IEnumerable<DetectedOperation> detectedOperations,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
||||
|
||||
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
|
||||
|
||||
await AddToWorkbookAsync(workbook, well, detectedOperations, cancellationToken);
|
||||
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
return memoryStream;
|
||||
}
|
||||
|
||||
private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, IEnumerable<DetectedOperation> detectedOperations,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
const string sheetName = "Операции";
|
||||
|
||||
if (!detectedOperations.Any())
|
||||
return;
|
||||
|
||||
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
|
||||
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
|
||||
|
||||
await AddToSheetAsync(sheet, well, detectedOperations.OrderBy(x => x.DateStart).ThenBy(x => x.DepthStart).ToArray(), cancellationToken);
|
||||
}
|
||||
|
||||
private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, IList<DetectedOperation> detectedOperations,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var wellOperationCategories = await dbContext.WellOperationCategories.ToListAsync(cancellationToken);
|
||||
|
||||
sheet.Cell(cellDepositName).Value = well.Cluster.Deposit.Caption;
|
||||
sheet.Cell(cellClusterName).Value = well.Cluster.Caption;
|
||||
sheet.Cell(cellWellName).Value = well.Caption;
|
||||
sheet.Cell(cellDeltaDate).Value = detectedOperations.Max(o => o.DateEnd) - detectedOperations.Min(o => o.DateStart);
|
||||
|
||||
var timeZoneWell = TimeSpan.FromHours(well.Timezone.Hours);
|
||||
|
||||
for (int i = 0; i < detectedOperations.Count; i++)
|
||||
{
|
||||
var dateStart = detectedOperations[i].DateStart.ToOffset(timeZoneWell);
|
||||
var dateEnd = detectedOperations[i].DateEnd.ToOffset(timeZoneWell);
|
||||
|
||||
var row = sheet.Row(5 + i + headerRowsCount);
|
||||
|
||||
row.Cell(columnOperationName).Value = detectedOperations[i].IdCategory == 12000 ? "Бурение в слайде с осцилляцией" :
|
||||
wellOperationCategories.Single(o => o.Id == detectedOperations[i].IdCategory).Name;
|
||||
row.Cell(columnDateEnd).Value = dateEnd;
|
||||
row.Cell(columnDuration).Value = (dateEnd - dateStart).TotalMinutes;
|
||||
row.Cell(columnDepthStart).Value = detectedOperations[i].DepthStart;
|
||||
row.Cell(columnDepthEnd).Value = detectedOperations[i].DepthEnd;
|
||||
row.Cell(columnDepth).Value = detectedOperations[i].DepthEnd - detectedOperations[i].DepthStart;
|
||||
row.Cell(columnIdReasonOfEnd).Value = detectedOperations[i].IdReasonOfEnd;
|
||||
|
||||
var link =
|
||||
$"https://cloud.digitaldrilling.ru/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(3544).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=3600";
|
||||
row.Cell(columnDateStart).Value = dateStart;
|
||||
row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link));
|
||||
|
||||
row.Cell(columnDeltaDepth).Value = i > 0 && i + 1 < detectedOperations.Count
|
||||
? detectedOperations[i].DepthStart - detectedOperations[i - 1].DepthEnd
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task<Stream> GetExcelTemplateStreamAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
string resourceName = Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceNames()
|
||||
.FirstOrDefault(n => n.EndsWith("Operations.xlsx"))!;
|
||||
|
||||
using var stream = Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceStream(resourceName)!;
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
await stream.CopyToAsync(memoryStream, cancellationToken);
|
||||
memoryStream.Position = 0;
|
||||
|
||||
return memoryStream;
|
||||
}
|
||||
}
|
BIN
ConsoleApp1/DetectedOperations/Files/Operations.xlsx
Normal file
BIN
ConsoleApp1/DetectedOperations/Files/Operations.xlsx
Normal file
Binary file not shown.
@ -1,23 +1,23 @@
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure;
|
||||
using CliWrap;
|
||||
using Mapster;
|
||||
using ConsoleApp1.DetectedOperations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ConsoleApp1
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(/*string[] args*/)
|
||||
private static DbContextOptions<AsbCloudDbContext> options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||
.UseNpgsql("Host=localhost;Database=postgres;Port=5433;Username=postgres;Password=root;Persist Security Info=True")
|
||||
.Options;
|
||||
|
||||
static async Task Main(/*string[] args*/)
|
||||
{
|
||||
using var db = new AsbCloudDbContext(options);
|
||||
|
||||
await new DetectedOperationExportService(db).Export(483, CancellationToken.None);
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user