using System; using System.Collections.Generic; using System.Linq; using AsbCloudApp.Data.DetectedOperation; using AsbCloudDb.Model; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; public class DetectorDrilling : DetectorAbstract { private const double dispersionOfNormalizedRotorSpeedThreshold = 0.2d; public const string ExtraDataKeyHasOscillation = "hasOscillation"; public const string ExtraDataKeyDispersionOfNormalizedRotorSpeed = "dispersionOfNormalizedRotorSpeed"; public const string ExtraDataKeyAvgRotorSpeed = "avgRotorSpeed"; protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation) { var point0 = telemetry[position]; var delta = point0.WellDepth - point0.BitDepth; if (delta > 0.03d) return false; if (point0.Pressure < 18) return false; return true; } protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation) { var point0 = telemetry[position]; var delta = point0.WellDepth - point0.BitDepth; if (delta > 0.03d) return IdReasonOfEnd_DeltaDepthIsHi; if (point0.Pressure < 18) return IdReasonOfEnd_PressureIsLo; return IdReasonOfEnd_NotDetected; } protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) => CalcRop(telemetry, begin, end); protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => base.IsValidOperationDetectorResult(operationDetectorResult) && (operationDetectorResult.Operation.DepthEnd - operationDetectorResult.Operation.DepthStart) > 0.01; protected override (int Begin, int End) RefineEdges(DetectableTelemetry[] telemetry, int begin, int end) { var i = end; for (; i > begin + 1; i--) if (telemetry[i].WellDepth - telemetry[i - 1].WellDepth > 0.001d) break; return (begin, i); } protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end) { var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed) = CalcCriteries(telemetry, begin, end); var idCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed); var extraData = new Dictionary { [ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed, [ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed, [ExtraDataKeyHasOscillation] = avgRotorSpeed > 1 && dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold }; return (idCategory, extraData); } private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end) { var telemetryRange = telemetry[begin..end]; var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed); var dispersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed / avgRotorSpeed - 1, 2)); return (avgRotorSpeed, dispersion); } private static int GetIdOperation(double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) { const int idSlideWithOscillation = WellOperationCategory.IdSlide; if (avgRotorSpeed < 5) return WellOperationCategory.IdSlide; if(dispersionOfNormalizedRotorSpeed < dispersionOfNormalizedRotorSpeedThreshold) return WellOperationCategory.IdRotor; return idSlideWithOscillation; } }