diff --git a/AsbCloudApp/Data/DataSaubStatDto.cs b/AsbCloudApp/Data/DataSaubStatDto.cs
deleted file mode 100644
index 3bb46d6d..00000000
--- a/AsbCloudApp/Data/DataSaubStatDto.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-using System;
-using AsbCloudApp.Data.WellOperation;
-
-namespace AsbCloudApp.Data;
-
-///
-/// dto для хранения данных статистики сауб
-///
-public class DataSaubStatDto:IId
-{
- ///
- ///
- ///
- public int Id { get; set; }
-
- ///
- /// Дата и время начала
- ///
- public DateTimeOffset DateStart { get; set; }
-
- ///
- /// Дата и время окончания
- ///
- public DateTimeOffset DateEnd { get; set; }
-
- ///
- /// Глубина забоя по стволу начальная
- ///
- public double DepthStart { get; set; }
-
- ///
- /// Глубина забоя по стволу конечная
- ///
- public double DepthEnd { get; set; }
-
- ///
- /// Скорость бурения
- ///
- public double Speed { get; set; }
-
- ///
- /// Ограничение скорости блока
- ///
- public double? BlockSpeedSp { get; set; }
-
- ///
- /// Давление
- ///
- public double Pressure { get; set; }
-
- ///
- /// Давление холостого хода
- ///
- public double? PressureIdle { get; set; }
-
- ///
- /// Ограничение фактического давления
- ///
- public double? PressureSp { get; set; }
-
- ///
- /// Фактическая нагрузка
- ///
- public double AxialLoad { get; set; }
-
- ///
- /// Ограничение факт. нагрузки
- ///
- public double? AxialLoadSp { get; set; }
-
- ///
- /// Максимально допустимая нагрузка
- ///
- public double? AxialLoadLimitMax { get; set; }
-
- ///
- /// Фактический момент
- ///
- public double RotorTorque { get; set; }
-
- ///
- /// Ограничение факт. момента
- ///
- public double? RotorTorqueSp { get; set; }
-
- ///
- /// Максимально допустимый момент
- ///
- public double? RotorTorqueLimitMax { get; set; }
-
- ///
- /// Работа при достижении ограничения
- ///
- public short? IdFeedRegulator { get; set; }
-
- ///
- /// Фактическая скорость оборотов ВСП
- ///
- public double RotorSpeed { get; set; }
-
- ///
- /// Название автоопределённой операции
- ///
- public int IdCategory { get; set; }
-
- ///
- /// Флаги подсистем
- ///
- public int EnabledSubsystems { get; set; }
-
- ///
- /// Наличие или отсутствие осцилляции
- ///
- public bool HasOscillation { get; set; }
-
- ///
- /// Фактический расход
- ///
- public double Flow { get; set; }
-
- ///
- /// Ключ телеметрии
- ///
- public int IdTelemetry { get; set; }
-
- ///
- /// Телеметрия
- ///
- public TelemetryDto Telemetry { get; set; } = null!;
-
- ///
- /// Категория автоопределенной операции
- ///
- public WellOperationCategoryDto OperationCategory { get; set; } = null!;
-}
diff --git a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs
index d419ad82..628276bc 100644
--- a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs
+++ b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs
@@ -1,4 +1,4 @@
-using AsbCloudApp.Data;
+using AsbCloudApp.Data.DataSaubStat;
using AsbCloudApp.Services;
using System;
using System.Collections.Generic;
diff --git a/AsbCloudApp/Services/ITelemetryDataSaubService.cs b/AsbCloudApp/Services/ITelemetryDataSaubService.cs
index 4a23ee87..fc4bbda8 100644
--- a/AsbCloudApp/Services/ITelemetryDataSaubService.cs
+++ b/AsbCloudApp/Services/ITelemetryDataSaubService.cs
@@ -21,8 +21,9 @@ public interface ITelemetryDataSaubService : ITelemetryDataService
///
///
+ ///
///
- Task> Get(IEnumerable idsTelemetries, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token);
+ Task> Get(IEnumerable idsTelemetries, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token, IEnumerable? idsFeedRegulators = null);
///
/// усредненная статистика по 1м за весь период
diff --git a/AsbCloudInfrastructure.Tests/Services/DataSaubStatServiceTest.cs b/AsbCloudInfrastructure.Tests/Services/DataSaubStatServiceTest.cs
index 80783c73..1e507f6f 100644
--- a/AsbCloudInfrastructure.Tests/Services/DataSaubStatServiceTest.cs
+++ b/AsbCloudInfrastructure.Tests/Services/DataSaubStatServiceTest.cs
@@ -1,4 +1,4 @@
-using AsbCloudApp.Data;
+using AsbCloudApp.Data.DataSaubStat;
using AsbCloudApp.Data.DetectedOperation;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index 859cfba5..86e4df64 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -319,7 +319,8 @@ public static class DependencyInjection
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddTransient();
+ //services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient<
diff --git a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs
index d8932b28..cb986215 100644
--- a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs
+++ b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs
@@ -1,4 +1,4 @@
-using AsbCloudApp.Data;
+using AsbCloudApp.Data.DataSaubStat;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
diff --git a/AsbCloudInfrastructure/Services/DataSaubStatDrillingQualityService.cs b/AsbCloudInfrastructure/Services/DataSaubStatDrillingQualityService.cs
new file mode 100644
index 00000000..1726af5c
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/DataSaubStatDrillingQualityService.cs
@@ -0,0 +1,239 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.DataSaubStat;
+using AsbCloudApp.Data.DetectedOperation;
+using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using AsbCloudDb.Model;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudInfrastructure.Services;
+
+
+public class DataSaubStatDrillingQualityService : IDataSaubStatService
+{
+ private IDataSaubStatRepository dataSaubStatRepository;
+ private ITelemetryDataCache telemetryDataCache;
+ private ITelemetryDataSaubService dataSaubService;
+ private IDetectedOperationRepository detectedOperationRepository;
+
+ public DataSaubStatDrillingQualityService(
+ IDataSaubStatRepository dataSaubStatRepository,
+ ITelemetryDataCache telemetryDataCache,
+ ITelemetryDataSaubService dataSaubService,
+ IDetectedOperationRepository detectedOperationRepository)
+ {
+ this.dataSaubStatRepository = dataSaubStatRepository;
+ this.telemetryDataCache = telemetryDataCache;
+ this.dataSaubService = dataSaubService;
+ this.detectedOperationRepository = detectedOperationRepository;
+ }
+
+ public async Task CreateStatAsync(int lastDaysFilter, Action onProgressCallback, CancellationToken token)
+ {
+ //to do
+ var cacheRequest = new TelemetryDataRequest()
+ {
+ GeDate = DateTime.UtcNow.AddDays(-5000)
+ };
+ var idTelemetries = telemetryDataCache.GetIds(cacheRequest).ToArray();
+
+ if (!idTelemetries.Any())
+ return;
+
+ var stats = new List();
+ //await dataSaubStatRepository.GetLastsAsync(idTelemetries, token);
+
+ //for (var i = 0; i < idTelemetries.Length; i++)
+ //{
+ // var idTelemetry = idTelemetries[i];
+ // var lastDate = stats.FirstOrDefault(s => s.IdTelemetry == idTelemetry)?.DateEnd.ToUniversalTime() ?? DateTimeOffset.UnixEpoch;
+ // var statsCount = await CreateStatForTelemetryFromDate(idTelemetry, lastDate, token);
+ // if(onProgressCallback != null)
+ // onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 1d * i / idTelemetries.Length);
+ //}
+ }
+
+ private async Task CreateStatForTelemetryFromDate(
+ int idTelemetry,
+ DateTimeOffset geDate,
+ CancellationToken token)
+ {
+ var leDate = DateTimeOffset.UtcNow;
+
+ var dataSaub = await dataSaubService.Get([idTelemetry], true, geDate, leDate, 100_000, token);
+
+ if (!dataSaub.Any())
+ return 0;
+
+ if (dataSaub is not TelemetryDataSaubDto[] dataSaubArray)
+ dataSaubArray = dataSaub.ToArray();
+
+ var dataSaubStats = CreateDataSaubStat(dataSaubArray);
+
+ return 0;
+
+ //return await dataSaubStatRepository.InsertRangeAsync(dataSaubStats, token);
+ }
+
+ private static IEnumerable CreateDataSaubStat2(int idFeedRegulator, TelemetryDataSaubDto[] dataSaub)
+ {
+ var result = new List();
+
+ var indexStart = 0;
+ var indexEnd = 0;
+
+ while (indexEnd < dataSaub.Count())
+ {
+ indexStart = Array.FindIndex(dataSaub, indexEnd, t => t.IdFeedRegulator == idFeedRegulator);
+ if (indexStart < 0)
+ break;
+
+ indexEnd = Array.FindIndex(dataSaub, indexStart, t => t.IdFeedRegulator != idFeedRegulator);
+
+ if (indexEnd < 0)
+ indexEnd = dataSaub.Length - 1;
+
+ if (indexEnd == indexStart)
+ {
+ continue;
+ }
+
+
+ var length = indexEnd - indexStart + 1;
+
+ var subset = dataSaub.AsSpan(indexStart, length);
+
+ if (length <= 2 || (subset[^1].WellDepth - subset[0].WellDepth) < 0.001)
+ continue; // мелкие выборки не учитываем.
+
+ var stats = CalcStats(subset);
+ result.Add(stats);
+
+ }
+ return result;
+ }
+
+ private static Dictionary> CreateDataSaubStat(TelemetryDataSaubDto[] dataSaub)
+ {
+
+ var dict = new Dictionary>() {
+ { 1, new List() },
+ { 2, new List() },
+ { 3, new List() },
+ { 4, new List() },
+ };
+
+ foreach (var item in dict)
+ {
+ var data = CreateDataSaubStat2(item.Key, dataSaub);
+ item.Value.AddRange(data);
+ }
+
+ return dict;
+ }
+
+ private static DataSaubStatDrillingQualityDto CalcStats(Span dataSaub)
+ {
+ var depthDrillingQuality = CalcAggregate(dataSaub);
+
+ var result = new DataSaubStatDrillingQualityDto();
+ result.DepthStart = dataSaub[0].WellDepth;
+ result.DepthEnd = dataSaub[^1].WellDepth;
+ result.DateStart = dataSaub[0].DateTime;
+ result.DateEnd = dataSaub[^1].DateTime;
+ result.DepthDrillingQuality = depthDrillingQuality;
+
+ return result;
+ }
+
+ private static DataSaubStatDto CalcStat(DetectedOperationDto operation, Span span)
+ {
+ var aggregatedValues = CalcAggregate(span);
+ var dateStart = span[0].DateTime;
+ var dateEnd = span[^1].DateTime;
+ var depthStart = span[0].WellDepth;
+ var depthEnd = span[^1].WellDepth;
+ var speed = ((depthEnd - depthStart) / (dateEnd - dateStart).TotalHours);
+
+ var processMapDrillingCacheItem = new DataSaubStatDto
+ {
+ DateStart = dateStart,
+ DateEnd = dateEnd,
+ DepthStart = depthStart,
+ DepthEnd = depthEnd,
+ Speed = speed,
+ BlockSpeedSp = span[0].BlockSpeedSp,
+ Pressure = aggregatedValues.Pressure,
+ PressureIdle = span[0].PressureIdle,
+ PressureSp = span[0].PressureSp,
+ AxialLoad = aggregatedValues.AxialLoad,
+ AxialLoadSp = span[0].AxialLoadSp,
+ AxialLoadLimitMax = span[0].AxialLoadLimitMax,
+ RotorTorque = aggregatedValues.RotorTorque,
+ RotorTorqueSp = span[0].RotorTorqueSp,
+ RotorTorqueLimitMax = span[0].RotorTorqueLimitMax,
+ IdFeedRegulator = span[0].IdFeedRegulator,
+ RotorSpeed = aggregatedValues.RotorSpeed,
+ IdCategory = operation.IdCategory,
+ EnabledSubsystems = operation.EnabledSubsystems,
+ HasOscillation = operation.EnabledSubsystems.IsAutoOscillation,
+ IdTelemetry = operation.IdTelemetry,
+ Flow = aggregatedValues.Flow
+ };
+ return processMapDrillingCacheItem;
+ }
+
+ private static (
+ double Pressure,
+ double AxialLoad,
+ double RotorTorque,
+ double RotorSpeed,
+ double Flow
+ ) CalcAggregate(Span span)
+ {
+ var sumPressure = 0.0;
+ var sumAxialLoad = 0.0;
+ var sumRotorTorque = 0.0;
+ var sumRotorSpeed = 0.0;
+ var flow = span[0].Flow ?? 0.0;
+ var diffDepthTotal = span[^1].WellDepth - span[0].WellDepth;
+ for (var i = 0; i < span.Length - 1; i++)
+ {
+ var diffDepth = span[i + 1].WellDepth - span[i].WellDepth;
+ sumPressure += diffDepth * span[i].Pressure;
+ sumAxialLoad += diffDepth * span[i].AxialLoad;
+ sumRotorTorque += diffDepth * span[i].RotorTorque;
+ sumRotorSpeed += diffDepth * span[i].RotorSpeed;
+ flow = span[i + 1].Flow > flow ? span[i + 1].Flow ?? 0.0 : flow;
+ }
+ return (
+ Pressure: sumPressure / diffDepthTotal,
+ AxialLoad: sumAxialLoad / diffDepthTotal,
+ RotorTorque: sumRotorTorque / diffDepthTotal,
+ RotorSpeed: sumRotorSpeed / diffDepthTotal,
+ Flow: flow
+ );
+ }
+
+ private static bool IsNewCacheItem(TelemetryDataSaubDto previous, TelemetryDataSaubDto current)
+ {
+ return !(current.Mode == previous.Mode)
+ || !(current.WellDepth >= previous.WellDepth)
+ || !(current.BlockSpeedSp == previous.BlockSpeedSp)
+ || !(current.PressureIdle == previous.PressureIdle)
+ || !(current.PressureSp == previous.PressureSp)
+ || !(current.AxialLoadSp == previous.AxialLoadSp)
+ || !(current.AxialLoadLimitMax == previous.AxialLoadLimitMax)
+ || !(current.HookWeightIdle == previous.HookWeightIdle)
+ || !(current.RotorTorqueIdle == previous.RotorTorqueIdle)
+ || !(current.RotorTorqueSp == previous.RotorTorqueSp)
+ || !(current.RotorTorqueLimitMax == previous.RotorTorqueLimitMax)
+ || !(current.IdFeedRegulator == previous.IdFeedRegulator);
+ }
+}
diff --git a/AsbCloudInfrastructure/Services/DataSaubStatService.cs b/AsbCloudInfrastructure/Services/DataSaubStatService.cs
index 82ee0416..f1722ba5 100644
--- a/AsbCloudInfrastructure/Services/DataSaubStatService.cs
+++ b/AsbCloudInfrastructure/Services/DataSaubStatService.cs
@@ -1,4 +1,4 @@
-using AsbCloudApp.Data;
+using AsbCloudApp.Data.DataSaubStat;
using AsbCloudApp.Data.DetectedOperation;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs
index cae5bdce..574a320e 100644
--- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs
+++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs
@@ -1,4 +1,5 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Data.DataSaubStat;
using AsbCloudApp.Data.ProcessMaps;
using AsbCloudApp.Data.ProcessMaps.Operations;
using AsbCloudApp.Data.ProcessMaps.Report;
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
index 0abd8fdf..c864eb7d 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
@@ -37,7 +37,14 @@ public class TelemetryDataSaubService : TelemetryDataBaseService> Get(IEnumerable idsTelemetries, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token)
+ public async Task> Get(
+ IEnumerable idsTelemetries,
+ bool isBitOnBottom,
+ DateTimeOffset geDate,
+ DateTimeOffset leDate,
+ int take,
+ CancellationToken token,
+ IEnumerable? idsFeedRegulators)
{
var offsetDict = new Dictionary();
foreach (var idTelemetry in idsTelemetries)
@@ -56,6 +63,11 @@ public class TelemetryDataSaubService : TelemetryDataBaseService Math.Abs(t.BitDepth - t.WellDepth) < 0.0001);
+ if (idsFeedRegulators != null && idsFeedRegulators.Any())
+ query = query
+ .Where(t => t.IdFeedRegulator.HasValue)
+ .Where(t => idsFeedRegulators.Contains(t.IdFeedRegulator!.Value));
+
query = query
.OrderBy(t => t.DateTime)
.Take(take);
diff --git a/AsbCloudWebApi.IntegrationTests/Repository/DataSaubStatRepositoryTest.cs b/AsbCloudWebApi.IntegrationTests/Repository/DataSaubStatRepositoryTest.cs
index e69cc692..7919a445 100644
--- a/AsbCloudWebApi.IntegrationTests/Repository/DataSaubStatRepositoryTest.cs
+++ b/AsbCloudWebApi.IntegrationTests/Repository/DataSaubStatRepositoryTest.cs
@@ -1,4 +1,4 @@
-using AsbCloudApp.Data;
+using AsbCloudApp.Data.DataSaubStat;
using AsbCloudApp.Repositories;
using AsbCloudDb.Model;
using Mapster;
diff --git a/AsbCloudWebApi/appsettings.json b/AsbCloudWebApi/appsettings.json
index 72d50f57..ae879099 100644
--- a/AsbCloudWebApi/appsettings.json
+++ b/AsbCloudWebApi/appsettings.json
@@ -7,10 +7,10 @@
}
},
"ConnectionStrings": {
- "DefaultConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True",
- "DebugConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True",
- "TestConnection": "Host=localhost;Database=test;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True",
- "LocalConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True"
+ "DefaultConnection": "Host=192.168.0.10;Database=postgres;Username=postgres;Password=q;Persist Security Info=True",
+ "DebugConnection": "Host=192.168.0.10;Database=postgres;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True",
+ "TestConnection": "Host=192.168.0.10;Database=test;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True",
+ "LocalConnection": "Host=192.168.0.10;Database=postgres;Username=postgres;Password=q;Persist Security Info=True"
},
"AllowedHosts": "*",
"ContentPath": "../data",
@@ -26,5 +26,5 @@
},
"DirectoryNameHelpPageFiles": "helpPages",
"DirectoryManualFiles": "manuals",
- "Urls": "http://0.0.0.0:5000"
+ "Urls": "http://0.0.0.0:5010"
}