diff --git a/AsbCloudDb/Model/DetectedOperation.cs b/AsbCloudDb/Model/DetectedOperation.cs index 27f4f928..7300eb59 100644 --- a/AsbCloudDb/Model/DetectedOperation.cs +++ b/AsbCloudDb/Model/DetectedOperation.cs @@ -41,6 +41,9 @@ namespace AsbCloudDb.Model [Column("value"), Comment("Ключевой показатель операции")] public double Value { get; set; } + [Column("enabled_subsystems"), Comment("флаги аключенных подсистем")] + public int EnabledSubsystems { get; set; } + [Column("extra_data", TypeName = "jsonb"), Comment("доп. инфо по операции")] public IDictionary ExtraData { get; set; } = null!; @@ -54,5 +57,57 @@ namespace AsbCloudDb.Model public override string ToString() => $"{IdCategory}\t{DateStart:G}\t{DateEnd:G}\t{DurationMinutes:#0.#}\t{DepthStart:#0.#}\t{DepthEnd:#0.#}"; + + /// + /// Флаги аключенных подсистем + /// + [Flags] + public enum EnabledSubsystemsFlags + { + /// + /// Автоподача долота + /// + AutoRotor = 1 << 0, + /// + /// БУРЕНИЕ В СЛАЙДЕ + /// + AutoSlide = 1 << 1, + /// + /// ПРОРАБОТКА + /// + AutoConditionig = 1 << 2, + /// + /// СПУСК СПО + /// + AutoSinking = 1 << 3, + /// + /// ПОДЪЕМ СПО + /// + AutoLifting = 1 << 4, + /// + /// ПОДЪЕМ С ПРОРАБОТКОЙ + /// + AutoLiftingWithConditionig = 1 << 5, + /// + /// блокировка + /// + AutoBlocknig = 1 << 6, + } + + /// + /// Есть ли флаг подсистемы у операции + /// + /// + /// + public bool HasSubsystemFlag(EnabledSubsystemsFlags flag) + => HasSubsystemFlag((int)flag); + + /// + /// Есть ли флаг/флаги подсистемы у операции + /// + /// + /// + public bool HasSubsystemFlag(int flags) + => (EnabledSubsystems & flags) > 0; } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs index 0d882c58..bb5f2663 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs @@ -193,7 +193,7 @@ public class DetectedOperationExportService return memoryStream; } - private string? CreateComment(OperationDetectorResult operationDetectorResult) + private static string CreateComment(OperationDetectorResult operationDetectorResult) { var operation = operationDetectorResult.Operation; switch (operation.IdCategory) @@ -214,7 +214,7 @@ public class DetectedOperationExportService return comment; } default: - return null; + return string.Empty; } } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs index a3cf05c4..a164cb4e 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs @@ -201,7 +201,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations if (well?.IdTelemetry is null || well.Timezone is null) return 0; - var query = BuildQuery(well, request); + var query = BuildQueryBase(well, request); if (query is null) return 0; @@ -232,13 +232,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations }; } - private IQueryable? BuildQuery(WellDto well, DetectedOperationRequest request) - { - if (well?.IdTelemetry is null || well.Timezone is null) - return null; + private IQueryable BuildQueryBase(WellDto well, DetectedOperationRequest request) + { var query = db.Set() - .Include(o => o.OperationCategory) .Where(o => o.IdTelemetry == well.IdTelemetry); if (request is not null) @@ -262,6 +259,14 @@ namespace AsbCloudInfrastructure.Services.DetectOperations query = query.Where(o => o.IdUsersAtStart == request.EqIdTelemetryUser); } + return query; + } + + private IQueryable BuildQuery(WellDto well, DetectedOperationRequest request) + { + IQueryable query = BuildQueryBase(well, request) + .Include(o => o.OperationCategory); + if (request?.SortFields?.Any() == true) { query = query.SortBy(request.SortFields); diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs index 8a85b86f..6da769bf 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs @@ -96,7 +96,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors int end, int idReasonOfEnd) { - var operation = MakeOperation(idTelemetry, telemetry, begin, end); + var operation = MakeDetectedOperation(idTelemetry, telemetry, begin, end); operation.ExtraData["IdReasonOfEnd"] = idReasonOfEnd; @@ -110,57 +110,83 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors return result; } - protected abstract DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end); - - protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end); - - protected DetectedOperation MakeDetectedOperationBlank(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) + private DetectedOperation MakeDetectedOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) { var pBegin = telemetry[begin]; var pEnd = telemetry[end]; - + var (IdCategory, ExtraData) = GetSpecificInformation(telemetry, begin, end); var operation = new DetectedOperation { + IdCategory = IdCategory, IdTelemetry = idTelemetry, IdUsersAtStart = pBegin.IdUser ?? -1, DateStart = pBegin.DateTime, DateEnd = pEnd.DateTime, DepthStart = (double)pBegin.WellDepth, DepthEnd = (double)pEnd.WellDepth, - ExtraData = new Dictionary(), + ExtraData = ExtraData, Value = CalcValue(telemetry, begin, end), + EnabledSubsystems = DetectEnabledSubsystems(telemetry, begin, end) }; return operation; } /// - /// Среднее арифметическое + /// Получение информации специфичной для конкретного детектора + /// IdCategory - одна из констант WellOperationCategory + /// ExtraData - дополнительная информация для отладки алгоритмов авто определения + /// + /// + protected abstract (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end); + + /// + /// Расчет ключевого параметра операции /// - /// /// /// - /// + /// /// - protected static double CalcAvgAppr( - Func yGetter, - DetectableTelemetry[] telemetry, - int begin, - int fragmentLength) + protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end); + + /// + /// Определение включенных подсистем во время выполнения операции + /// + /// + /// + /// + /// + private static int DetectEnabledSubsystems(DetectableTelemetry[] telemetry, int begin, int end) { - var end = begin + fragmentLength; - end = end < telemetry.Length - ? end - : telemetry.Length; - var subData = telemetry[begin..end].Select(yGetter); - if (end - begin > 10) + var enabledSubsystems = 0; + + for (var i = begin; i < end; i += 2) { - var ratio = (end - begin) / 5; - subData = subData.Where((_, i) => i % ratio > 0); + var mode = telemetry[i].Mode; + + if(mode == 1) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoRotor; + + if (mode == 3) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoSlide; + + if (mode == 2) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoConditionig; + + if (mode == 4) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoSinking; + + if (mode == 5) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoLifting; + + if (mode == 6) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoLiftingWithConditionig; + + if (mode == 10) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoBlocknig; } - var avg = subData.Average(); - return avg; + return enabledSubsystems; } /// diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs index 2120b271..3806e380 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Drawing; using System.Linq; using AsbCloudDb.Model; @@ -55,25 +57,23 @@ public class DetectorDrilling : DetectorAbstract return (begin, i); } - protected override DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) + protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end) { - var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed, isAfbEnabled) = CalcCriteries(telemetry, begin, end); - var operation = MakeDetectedOperationBlank(idTelemetry, telemetry, begin, end); - operation.IdCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed); - operation.ExtraData[ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed; - operation.ExtraData[ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed; - operation.ExtraData[ExtraDataKeyHasOscillation] = dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold; - operation.ExtraData[ExtraDataKeyIsAfbEnabled] = isAfbEnabled; - return operation; + var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed) = CalcCriteries(telemetry, begin, end); + var idCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed); + var extraData = new Dictionary(); + extraData[ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed; + extraData[ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed; + extraData[ExtraDataKeyHasOscillation] = dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold; + return (idCategory, extraData); } - private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed, bool isAfbEnabled) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end) + 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)); - var isAfbEnabled = telemetryRange.Any(t => t.Mode > 0); - return (avgRotorSpeed, dispersion, isAfbEnabled); + return (avgRotorSpeed, dispersion); } private static int GetIdOperation(double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) @@ -88,4 +88,5 @@ public class DetectorDrilling : DetectorAbstract else return idSlideWithOscillation; } + } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs index 509970c4..58bdba27 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using AsbCloudDb.Model; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; @@ -27,14 +28,12 @@ public class DetectorSlipsTime : DetectorAbstract return true; } + protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end) + { + return (WellOperationCategory.IdSlipsTime, new Dictionary()); + } + protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; - - protected override DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) - { - var operation = MakeDetectedOperationBlank(idTelemetry, telemetry, begin, end); - operation.IdCategory = WellOperationCategory.IdSlipsTime; - return operation; - } } diff --git a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs index 33255f21..3c6d5b64 100644 --- a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs @@ -60,7 +60,7 @@ namespace AsbCloudWebApi.Controllers.SAUB [FromQuery] DetectedOperationRequest request, CancellationToken token) { - if (!await UserHasAccesToWellAsync(request.IdWell, token)) + if (!await UserHasAccessToWellAsync(request.IdWell, token)) return Forbid(); var result = await detectedOperationService.GetAsync(request, token); @@ -79,7 +79,7 @@ namespace AsbCloudWebApi.Controllers.SAUB [FromQuery] DetectedOperationRequest request, CancellationToken token) { - if (!await UserHasAccesToWellAsync(request.IdWell, token)) + if (!await UserHasAccessToWellAsync(request.IdWell, token)) return Forbid(); var result = await detectedOperationService.GetOperationsStatAsync(request, token); @@ -101,14 +101,14 @@ namespace AsbCloudWebApi.Controllers.SAUB [FromQuery] DetectedOperationRequest request, CancellationToken token) { - if (!await UserHasAccesToWellAsync(request.IdWell, token)) + if (!await UserHasAccessToWellAsync(request.IdWell, token)) return Forbid(); var result = await detectedOperationService.DeleteAsync(request, token); return Ok(result); } - protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) + protected async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) { var idCompany = User.GetCompanyId(); if (idCompany is not null && diff --git a/AsbCloudWebApi/Program.cs b/AsbCloudWebApi/Program.cs index 18825902..864b9600 100644 --- a/AsbCloudWebApi/Program.cs +++ b/AsbCloudWebApi/Program.cs @@ -7,6 +7,7 @@ namespace AsbCloudWebApi { // Uncomment next line to find wired exceptions by tracing. //static TraceListenerView trace4debug = new TraceListenerView(); + enum A { a = 1 << 2 } public static void Main(string[] args) {