diff --git a/AsbCloudApp/Services/IDataSaubStatService.cs b/AsbCloudApp/Services/IDataSaubStatService.cs
new file mode 100644
index 00000000..f72d4480
--- /dev/null
+++ b/AsbCloudApp/Services/IDataSaubStatService.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Services
+{
+ ///
+ /// Сервис записи данных в таблицу DataSaubStat, которая используется для построения РТК-отчета
+ ///
+ public interface IDataSaubStatService
+ {
+ ///
+ /// Расчет статистики DataSaubStat
+ ///
+ ///
+ /// Количество дней за которые должны были приходить данные, чтобы телеметрия попала в обработку.
+ ///
+ ///
+ ///
+ ///
+ Task CreateStatAsync(int lastDaysFilter, Action onProgressCallback, CancellationToken token);
+
+ }
+}
diff --git a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs
index c7ea36ff..6a2f92de 100644
--- a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs
+++ b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs
@@ -16,7 +16,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Background.PeriodicWorks
{
///
- /// задача по добавлению данных в таблицу DataSaubStat, которая используется дл построения РТК-отчета
+ /// задача по добавлению данных в таблицу DataSaubStat, которая используется для построения РТК-отчета
///
internal class WorkDataSaubStat : Work
{
@@ -29,209 +29,11 @@ namespace AsbCloudInfrastructure.Background.PeriodicWorks
protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token)
{
+ var dataSaubStatService = services.GetRequiredService();
- var telemetryDataCache = services.GetRequiredService>();
+ if (dataSaubStatService != null )
+ await dataSaubStatService.CreateStatAsync(Gap, onProgressCallback, token);
- var cacheRequest = new TelemetryDataRequest()
- {
- GeDate = DateTime.UtcNow.AddDays(-Gap)
- };
- var idTelemetries = telemetryDataCache.GetIds(cacheRequest).ToArray();
-
- if (!idTelemetries.Any())
- return;
-
- var dataSaubStatRepo = services.GetRequiredService();
- var dataSaubService = services.GetRequiredService();
- var detectedOperationRepository = services.GetRequiredService();
- var stats = await dataSaubStatRepo.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, dataSaubService, dataSaubStatRepo, detectedOperationRepository, token);
- onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 100*i / idTelemetries.Length);
- }
- }
-
- private static async Task CreateStatForTelemetryFromDate(
- int idTelemetry,
- DateTimeOffset begin,
- ITelemetryDataSaubService dataSaubService,
- IDataSaubStatRepository dataSaubStatRepo,
- IDetectedOperationRepository detectedOperationRepository,
- CancellationToken token)
- {
- var detectedOperationRequest = new DetectedOperationByTelemetryRequest {
- GeDateStart = begin,
- IdTelemetry = idTelemetry,
- IdsCategories = WellOperationCategory.MechanicalDrillingSubIds,
- SortFields = new[] {nameof(DetectedOperation.DateStart) },
- Take = 250,
- };
-
- var detectedOperations = await detectedOperationRepository.Get(detectedOperationRequest, token);
-
- if (!detectedOperations.Any())
- return 0;
-
- var geDate = detectedOperations.First().DateStart;
- var leDate = detectedOperations.OrderByDescending(d => d.DateEnd).First().DateEnd;
-
- 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(detectedOperations, dataSaubArray);
-
- return await dataSaubStatRepo.InsertRangeAsync(dataSaubStats, token);
- }
-
- private static IEnumerable CreateDataSaubStat(IEnumerable detectedOperations, TelemetryDataSaubDto[] dataSaub)
- {
- var indexStart = 0;
- var indexEnd = 0;
- var result = new List();
-
- if (!dataSaub.Any())
- return result;
-
- foreach (var operation in detectedOperations)
- {
- indexStart = Array.FindIndex(dataSaub, indexEnd, t => t.DateTime >= operation.DateStart);
- if (indexStart < 0)
- break;
-
- indexEnd = Array.FindIndex(dataSaub, indexStart, t => t.DateTime > operation.DateEnd);
-
- if (indexEnd < 0)
- indexEnd = dataSaub.Length - 1;
-
- if (indexEnd == indexStart)
- continue;
-
- var length = indexEnd - indexStart;
-
- var subset = dataSaub.AsSpan(indexStart, length);
- var stats = CalcStats(operation, subset);
- result.AddRange(stats);
- }
- return result;
- }
-
- private static IEnumerable CalcStats(DetectedOperationDto operation, Span dataSaub)
- {
- var result = new List();
-
- var indexStart = 0;
- for (var i = 1; i < dataSaub.Length; i++)
- {
- var previous = dataSaub[i - 1];
- var current = dataSaub[i];
-
- if (IsNewCacheItem(previous, current) || i == dataSaub.Length - 1)
- {
- var length = i - indexStart;
- var span = dataSaub.Slice(indexStart, length);
- indexStart = i;
- if (length <= 2 || (span[^1].WellDepth - span[0].WellDepth) < 0.001)
- continue; // мелкие выборки не учитываем.
- var stat = CalcStat(operation, span);
- result.Add(stat);
- }
- }
-
- 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/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index 9fbe1721..5ce1ada0 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -316,6 +316,7 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient<
IChangeLogRepository,
diff --git a/AsbCloudInfrastructure/Services/DataSaubStatService.cs b/AsbCloudInfrastructure/Services/DataSaubStatService.cs
new file mode 100644
index 00000000..e54a380d
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/DataSaubStatService.cs
@@ -0,0 +1,237 @@
+using AsbCloudApp.Data;
+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 DataSaubStatService : IDataSaubStatService
+ {
+ private IDataSaubStatRepository dataSaubStatRepository;
+ private ITelemetryDataCache telemetryDataCache;
+ private ITelemetryDataSaubService dataSaubService;
+ private IDetectedOperationRepository detectedOperationRepository;
+
+ public DataSaubStatService(
+ 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)
+ {
+ var cacheRequest = new TelemetryDataRequest()
+ {
+ GeDate = DateTime.UtcNow.AddDays(-lastDaysFilter)
+ };
+ var idTelemetries = telemetryDataCache.GetIds(cacheRequest).ToArray();
+
+ if (!idTelemetries.Any())
+ return;
+
+ var stats = 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 begin,
+ CancellationToken token)
+ {
+ var detectedOperationRequest = new DetectedOperationByTelemetryRequest
+ {
+ GeDateStart = begin,
+ IdTelemetry = idTelemetry,
+ IdsCategories = WellOperationCategory.MechanicalDrillingSubIds,
+ SortFields = new[] { nameof(DetectedOperation.DateStart) },
+ Take = 250,
+ };
+
+ var detectedOperations = await detectedOperationRepository.Get(detectedOperationRequest, token);
+
+ if (!detectedOperations.Any())
+ return 0;
+
+ var geDate = detectedOperations.First().DateStart;
+ var leDate = detectedOperations.OrderByDescending(d => d.DateEnd).First().DateEnd;
+
+ 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(detectedOperations, dataSaubArray);
+
+ return await dataSaubStatRepository.InsertRangeAsync(dataSaubStats, token);
+ }
+
+ private static IEnumerable CreateDataSaubStat(IEnumerable detectedOperations, TelemetryDataSaubDto[] dataSaub)
+ {
+ var indexStart = 0;
+ var indexEnd = 0;
+ var result = new List();
+
+ if (!dataSaub.Any())
+ return result;
+
+ foreach (var operation in detectedOperations)
+ {
+ indexStart = Array.FindIndex(dataSaub, indexEnd, t => t.DateTime >= operation.DateStart);
+ if (indexStart < 0)
+ break;
+
+ indexEnd = Array.FindIndex(dataSaub, indexStart, t => t.DateTime > operation.DateEnd);
+
+ if (indexEnd < 0)
+ indexEnd = dataSaub.Length - 1;
+
+ if (indexEnd == indexStart)
+ continue;
+
+ var length = indexEnd - indexStart + 1;
+
+ var subset = dataSaub.AsSpan(indexStart, length);
+ var stats = CalcStats(operation, subset);
+ result.AddRange(stats);
+ }
+ return result;
+ }
+
+ private static IEnumerable CalcStats(DetectedOperationDto operation, Span dataSaub)
+ {
+ var result = new List();
+
+ var indexStart = 0;
+ for (var i = 1; i < dataSaub.Length; i++)
+ {
+ var previous = dataSaub[i - 1];
+ var current = dataSaub[i];
+
+ if (IsNewCacheItem(previous, current) || i == dataSaub.Length - 1)
+ {
+ var length = i - indexStart + 1;
+ var span = dataSaub.Slice(indexStart, length);
+ indexStart = i;
+ if (length <= 2 || (span[^1].WellDepth - span[0].WellDepth) < 0.001)
+ continue; // мелкие выборки не учитываем.
+ var stat = CalcStat(operation, span);
+ result.Add(stat);
+ }
+ }
+
+ 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/AsbCloudWebApi.Tests/Services/DataSaubStatServiceTest.cs b/AsbCloudWebApi.Tests/Services/DataSaubStatServiceTest.cs
new file mode 100644
index 00000000..6d65a1f2
--- /dev/null
+++ b/AsbCloudWebApi.Tests/Services/DataSaubStatServiceTest.cs
@@ -0,0 +1,323 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.DetectedOperation;
+using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using AsbCloudInfrastructure.Services;
+using Mapster;
+using NSubstitute;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace AsbCloudWebApi.Tests.Services;
+
+public class DataSaubStatServiceTest
+{
+ private readonly int Gap = 5;
+ private readonly IDataSaubStatRepository dataSaubStatRepositoryMock = Substitute.For();
+ private readonly ITelemetryDataCache telemetryDataCacheMock = Substitute.For>();
+ private readonly IDetectedOperationRepository detectedOperationRepositoryMock = Substitute.For();
+ private readonly ITelemetryDataSaubService dataSaubServiceMock = Substitute.For();
+
+ private DataSaubStatService dataSaubStatService;
+
+ private int[] idTelemetries = [1];
+ private IEnumerable dataSaubStatDtos = new List()
+ {
+ new DataSaubStatDto {
+ Id = 1,
+ AxialLoad = 1,
+ AxialLoadLimitMax = 1,
+ AxialLoadSp = 1,
+ BlockSpeedSp = 1,
+ DateEnd = DateTime.UtcNow,
+ DateStart = DateTime.UtcNow.AddHours(-1),
+ DepthEnd = 2,
+ DepthStart = 1,
+ EnabledSubsystems = 1,
+ Flow = 1,
+ HasOscillation = true,
+ IdCategory = 1,
+ IdFeedRegulator = 1,
+ IdTelemetry = 1,
+ Pressure = 1,
+ PressureIdle = 1,
+ PressureSp = 1,
+ RotorSpeed = 1,
+ RotorTorque = 1,
+ RotorTorqueLimitMax = 1,
+ RotorTorqueSp = 1,
+ Speed = 1
+ },
+ new DataSaubStatDto {
+ Id = 2,
+ AxialLoad = 2,
+ AxialLoadLimitMax = 2,
+ AxialLoadSp = 2,
+ BlockSpeedSp = 2,
+ DateEnd = DateTime.UtcNow,
+ DateStart = DateTime.UtcNow.AddHours(-1),
+ DepthEnd = 3,
+ DepthStart = 2,
+ EnabledSubsystems = 2,
+ Flow = 2,
+ HasOscillation = true,
+ IdCategory = 2,
+ IdFeedRegulator = 2,
+ IdTelemetry = 2,
+ Pressure = 2,
+ PressureIdle = 2,
+ PressureSp = 2,
+ RotorSpeed = 2,
+ RotorTorque = 2,
+ RotorTorqueLimitMax = 2,
+ RotorTorqueSp = 2,
+ Speed = 2
+ },
+ new DataSaubStatDto {
+ Id = 3,
+ AxialLoad = 3,
+ AxialLoadLimitMax = 3,
+ AxialLoadSp = 3,
+ BlockSpeedSp = 3,
+ DateEnd = DateTime.UtcNow,
+ DateStart = DateTime.UtcNow.AddHours(-1),
+ DepthEnd = 4,
+ DepthStart = 3,
+ EnabledSubsystems = 3,
+ Flow = 3,
+ HasOscillation = true,
+ IdCategory = 3,
+ IdFeedRegulator = 3,
+ IdTelemetry = 3,
+ Pressure = 3,
+ PressureIdle = 3,
+ PressureSp = 3,
+ RotorSpeed = 3,
+ RotorTorque = 3,
+ RotorTorqueLimitMax = 3,
+ RotorTorqueSp = 3,
+ Speed = 3
+ },
+ };
+
+ private List detectedOperationDtos = new List() {
+ new DetectedOperationDto {
+ Id = 1,
+ DateEnd = DateTimeOffset.UtcNow,
+ DateStart = DateTimeOffset.UtcNow.AddHours(-1),
+ DepthStart = 1,
+ DepthEnd = 2,
+ IdCategory = 5002,
+ IdTelemetry = 1,
+ Value = 1,
+ IdEditor = 1,
+ IdUserAtStart = 1
+ }
+ };
+
+ private List telemetryDataSaubDtos = new List {
+ new TelemetryDataSaubDto()
+ {
+ IdTelemetry = 1,
+ DateTime = DateTime.UtcNow.AddMinutes(-30),
+ AxialLoad = 1,
+ AxialLoadLimitMax = 1,
+ AxialLoadSp = 1,
+ BitDepth = 1,
+ BlockPosition = 1,
+ BlockPositionMax = 1,
+ BlockPositionMin = 1,
+ BlockSpeed = 1,
+ BlockSpeedSp = 1,
+ BlockSpeedSpDevelop = 1,
+ BlockSpeedSpRotor = 1,
+ BlockSpeedSpSlide = 1,
+ Flow = 1,
+ FlowDeltaLimitMax = 1,
+ FlowIdle = 1,
+ HookWeight = 1,
+ HookWeightIdle = 1,
+ HookWeightLimitMax = 1,
+ HookWeightLimitMin = 1,
+ IdFeedRegulator = 1,
+ IdUser = 1,
+ Mode = 1,
+ Mse = 1,
+ MseState = 1,
+ Pressure = 1,
+ PressureDeltaLimitMax = 1,
+ PressureIdle = 1,
+ PressureSp = 1,
+ PressureSpDevelop = 1,
+ PressureSpRotor = 1,
+ PressureSpSlide = 1,
+ Pump0Flow = 1,
+ Pump1Flow = 1,
+ Pump2Flow = 1,
+ RotorSpeed = 1,
+ RotorTorque = 1,
+ RotorTorqueIdle = 1,
+ RotorTorqueSp = 1,
+ RotorTorqueLimitMax = 1,
+ WellDepth = 10,
+ }
+ };
+
+ public DataSaubStatServiceTest()
+ {
+ telemetryDataCacheMock
+ .GetIds(Arg.Any())
+ .Returns(idTelemetries);
+
+ dataSaubStatRepositoryMock
+ .GetLastsAsync(Arg.Any(), Arg.Any())
+ .Returns(dataSaubStatDtos);
+
+ var telemetrySaubDto = telemetryDataSaubDtos.FirstOrDefault();
+ if (telemetrySaubDto != null)
+ {
+ //заполнение списка телеметрий следующим образом:
+ // - всего в списке 6 элементов:
+ // - все они попадают в диапазон, определенный датами DateStart и DateEnd соответствующей записи detectedOperation
+ // - из этих 6-х записей у 2-х записей меняется параметр,
+ // являющийся признаком начала нового интервала (новой записи dataSaubStat)
+ // таким образом, в базе данных должно создаться 1 новая запись dataSaubStat (insertedDataSaubStatCount = 1)
+ var telemetrySaubDto1 = telemetrySaubDto.Adapt();
+ telemetrySaubDto1.DateTime = DateTime.UtcNow.AddMinutes(-20);
+ telemetryDataSaubDtos.Add(telemetrySaubDto1);
+
+ var telemetrySaubDto2 = telemetrySaubDto.Adapt();
+ telemetrySaubDto2.DateTime = DateTime.UtcNow.AddMinutes(-10);
+ telemetrySaubDto2.RotorTorqueLimitMax = 2;
+ telemetryDataSaubDtos.Add(telemetrySaubDto2);
+
+ var telemetrySaubDto3 = telemetrySaubDto.Adapt();
+ telemetrySaubDto3.DateTime = DateTime.UtcNow.AddMinutes(-8);
+ telemetrySaubDto3.RotorTorqueLimitMax = 2;
+ telemetryDataSaubDtos.Add(telemetrySaubDto3);
+
+ var telemetrySaubDto4 = telemetrySaubDto.Adapt();
+ telemetrySaubDto4.DateTime = DateTime.UtcNow.AddMinutes(-6);
+ telemetrySaubDto4.RotorTorqueLimitMax = 2;
+ telemetryDataSaubDtos.Add(telemetrySaubDto4);
+
+ var telemetrySaubDto5 = telemetrySaubDto.Adapt();
+ telemetrySaubDto5.DateTime = DateTime.UtcNow.AddMinutes(-4);
+ telemetrySaubDto5.RotorTorqueLimitMax = 2;
+ telemetryDataSaubDtos.Add(telemetrySaubDto5);
+
+ var telemetrySaubDto6 = telemetrySaubDto.Adapt();
+ telemetrySaubDto6.DateTime = DateTime.UtcNow.AddMinutes(-2);
+ telemetrySaubDto6.RotorTorqueLimitMax = 3;
+ telemetrySaubDto6.WellDepth = 11;
+ telemetryDataSaubDtos.Add(telemetrySaubDto6);
+ }
+
+ dataSaubServiceMock
+ .Get(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
+ .Returns(telemetryDataSaubDtos);
+
+ dataSaubStatService = new DataSaubStatService(
+ dataSaubStatRepositoryMock,
+ telemetryDataCacheMock,
+ dataSaubServiceMock,
+ detectedOperationRepositoryMock);
+ }
+
+ [Fact]
+ public async Task Create_1DataSaubStatItems_ShouldReturn__Success()
+ {
+ var insertedDataSaubStatCount = 1;
+
+ detectedOperationRepositoryMock
+ .Get(Arg.Any(), Arg.Any())
+ .Returns(detectedOperationDtos);
+
+
+ dataSaubStatRepositoryMock
+ .InsertRangeAsync(Arg.Any>(), Arg.Any())
+ .Returns(insertedDataSaubStatCount);
+
+ Action action = (message, percent) =>
+ {
+ //assert
+ Assert.NotNull(percent);
+ Assert.InRange(percent.Value, 0.0, 1.0);
+ };
+
+ //act
+ await dataSaubStatService.CreateStatAsync(Gap, action, CancellationToken.None);
+
+ //assert
+ await dataSaubStatRepositoryMock.Received().InsertRangeAsync(
+ Arg.Is>(l => l.Count() == insertedDataSaubStatCount),
+ Arg.Any());
+ }
+
+
+
+ [Fact]
+ public async Task Create_2DataSaubStatItems_ShouldReturn__Success()
+ {
+ var insertedDataSaubStatCount = 2;
+
+ var detectedOperationDto = detectedOperationDtos.FirstOrDefault();
+ if (detectedOperationDto != null)
+ {
+ var detectedOperationDto1 = detectedOperationDto.Adapt();
+ detectedOperationDto1.DateStart = DateTimeOffset.UtcNow.AddMinutes(1);
+ detectedOperationDto1.DateEnd = DateTimeOffset.UtcNow.AddHours(1);
+
+ detectedOperationDtos.Add(detectedOperationDto1);
+ }
+
+ var telemetryDataSaubDto = telemetryDataSaubDtos.LastOrDefault();
+ if (telemetryDataSaubDto != null)
+ {
+ var telemetryDataSaubDto1 = telemetryDataSaubDto.Adapt();
+ telemetryDataSaubDto1.DateTime = DateTime.UtcNow.AddMinutes(10);
+ telemetryDataSaubDto1.WellDepth = telemetryDataSaubDto.WellDepth + 1;
+
+ var telemetryDataSaubDto2 = telemetryDataSaubDto.Adapt();
+ telemetryDataSaubDto2.DateTime = DateTime.UtcNow.AddMinutes(20);
+ telemetryDataSaubDto2.WellDepth = telemetryDataSaubDto1.WellDepth + 1;
+
+ var telemetryDataSaubDto3 = telemetryDataSaubDto.Adapt();
+ telemetryDataSaubDto3.DateTime = DateTime.UtcNow.AddMinutes(30);
+ telemetryDataSaubDto3.WellDepth = telemetryDataSaubDto2.WellDepth + 1;
+
+ telemetryDataSaubDtos.Add(telemetryDataSaubDto1);
+ telemetryDataSaubDtos.Add(telemetryDataSaubDto2);
+ telemetryDataSaubDtos.Add(telemetryDataSaubDto3);
+ }
+
+ detectedOperationRepositoryMock
+ .Get(Arg.Any(), Arg.Any())
+ .Returns(detectedOperationDtos);
+
+ dataSaubStatRepositoryMock
+ .InsertRangeAsync(Arg.Any>(), Arg.Any())
+ .Returns(insertedDataSaubStatCount);
+
+ Action action = (message, percent) =>
+ {
+ //assert
+ Assert.NotNull(percent);
+ Assert.InRange(percent.Value, 0.0, 1.0);
+ };
+
+ //act
+ await dataSaubStatService.CreateStatAsync(Gap, action, CancellationToken.None);
+
+ //assert
+ await dataSaubStatRepositoryMock.Received().InsertRangeAsync(
+ Arg.Is>(l => l.Count() == insertedDataSaubStatCount),
+ Arg.Any());
+ }
+}
\ No newline at end of file