using AsbCloudDb.Model; using AsbCloudDb.Model.Subsystems; using AsbCloudInfrastructure.Services.Subsystems; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Background.PeriodicWorks; public class WorkSubsystemAbfOperationTimeCalc : WorkSubsystemOperationTimeCalcAbstract { public WorkSubsystemAbfOperationTimeCalc() : base("Subsystem automated bit feeding operation time calc") { Timeout = TimeSpan.FromMinutes(30); } protected override async Task> OperationTimeAsync(int idTelemetry, DateTimeOffset geDate, IAsbCloudDbContext db, CancellationToken token) { static bool isSubsytemAkbRotor(short? mode) => mode == 1; static bool isSubsytemAkbSlide(short? mode) => mode == 3; static bool IsSubsystemMse(short? state) => (state & 1) > 0; var query = $"select tt.date, tt.mode, tt.well_depth, tt.mse_state " + $"from ( " + $" select " + $" date, " + $" mode, " + $" mse_state, " + $" well_depth, " + $" lag(mode,1) over (order by date) as mode_lag, " + $" lead(mode,1) over (order by date) as mode_lead " + $" from t_telemetry_data_saub " + $" where id_telemetry = {idTelemetry} and well_depth is not null and well_depth > 0 " + $" order by date ) as tt " + $"where (tt.mode_lag is null or (tt.mode != tt.mode_lag and tt.mode_lead != tt.mode_lag)) and tt.date >= '{geDate:u}' " + $"order by tt.date;"; using var result = await ExecuteReaderAsync(db, query, token); var subsystemsOperationTimes = new List(); var detectorRotor = new SubsystemDetector(idTelemetry, idSubsystemAPDRotor, isSubsytemAkbRotor, IsValid); var detectorSlide = new SubsystemDetector(idTelemetry, idSubsystemAPDSlide, isSubsytemAkbSlide, IsValid); var detectorMse = new SubsystemDetector(idTelemetry, idSubsystemMse, IsSubsystemMse, IsValid); while (result.Read()) { var mode = result.GetFieldValue(1); var state = result.GetFieldValue(3); var isAkbRotorEnable = isSubsytemAkbRotor(mode); var isAkbSlideEnable = isSubsytemAkbSlide(mode); var isMseEnable = IsSubsystemMse(state); var date = result.GetFieldValue(0); var depth = result.GetFieldValue(2); if (detectorRotor.TryDetect(mode, date, depth, out var detectedRotor)) subsystemsOperationTimes.Add(detectedRotor!); if (detectorSlide.TryDetect(mode, date, depth, out var detectedSlide)) subsystemsOperationTimes.Add(detectedSlide!); if (detectorMse.TryDetect(mode, date, depth, out var detectedMse)) subsystemsOperationTimes.Add(detectedMse!); } return subsystemsOperationTimes; } private static async Task ExecuteReaderAsync(IAsbCloudDbContext db, string query, CancellationToken token) { var connection = db.Database.GetDbConnection(); if ( connection?.State is null || connection.State == ConnectionState.Broken || connection.State == ConnectionState.Closed) { await db.Database.OpenConnectionAsync(token); connection = db.Database.GetDbConnection(); } using var command = connection.CreateCommand(); command.CommandText = query; var result = await command.ExecuteReaderAsync(token); return result; } private static bool IsValid(SubsystemOperationTime item) { var validateCode = GetValidateErrorCode(item); if (validateCode != 0) { var str = System.Text.Json.JsonSerializer.Serialize(item); Trace.TraceWarning($"Wrong({validateCode}) SubsystemOperationTime: {str}"); } return validateCode == 0; } private static int GetValidateErrorCode(SubsystemOperationTime item) { if (item.DateStart > item.DateEnd) return -1; if ((item.DateEnd - item.DateStart).TotalHours > 48) return -2; if (item.DepthEnd < item.DepthStart) return -3; if (item.DepthEnd - item.DepthStart > 2000d) return -4; if (item.DepthEnd < 0d) return -5; if (item.DepthStart < 0d) return -6; if (item.DepthEnd > 24_0000d) return -7; if (item.DepthStart > 24_0000d) return -8; return 0; } }