DD.WellWorkover.Cloud/AsbCloudInfrastructure/Background/PeriodicWorks/WorkProcessMapDrillingCache.cs

189 lines
9.1 KiB
C#
Raw Normal View History

using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Background.PeriodicWorks
{
internal class WorkProcessMapDrillingCache : Work
{
private int MechanicalDrillingCategoryId = 4001;
public WorkProcessMapDrillingCache() : base("Generate process map drilling cache table")
{
Timeout = TimeSpan.FromMinutes(10);
}
protected override Task Action(string id, IServiceProvider services, Action<string, double?> onProgressCallback, CancellationToken token)
{
//1 найти последнюю запись в кеш-таблице (по полям "Дата до")
//2 определяем дату с которой начинаем анализ
//3 находим автоопределнные операции по скважине, начиная с начальной даты из пункта 2
// 3.1 только те, которые связанные с бурением (idParent = 4001)
// 3.2 выбираем 500 операций
// 3.3. выбираем минимальную дату начала и максимальную дату окончания
//4 по полученным в пункте выше данным выбираем записи из telemetry_data_saub
// 4.1.выбираем те у которых (bit_depth == well_depth)
//5. для каждой операции из 3.2 находим соответствующий ей кусок телеметрии (по дате начала и окончания)
// и храним индексы этого куска в виде span
//6. кусок телеметрии, полученный в пункте 5 (span) и соответствующая ей операция направляется на разбивку диапазонов
//7/ разбивка диапазонов:
// параметры метода: массив из
using var db = services.GetRequiredService<IAsbCloudDbContext>();
2024-01-30 17:28:41 +05:00
var dateFrom = db.ProcessMapDrillingCache
.OrderByDescending(c => c.DateTo)
.FirstOrDefault()?.DateTo
?? DateTimeOffset.MinValue;
//а остальные операции, которые не вошли в 500 первых?
var detectedOperations = db.DetectedOperations
.Where(o => o.DateStart > dateFrom)
.Where(o => o.OperationCategory.IdParent == MechanicalDrillingCategoryId)
.OrderBy(o => o.DateStart)
.Take(500)
.ToArray();
var minDate = detectedOperations.FirstOrDefault()?.DateStart;
var maxDate = detectedOperations.OrderByDescending(d =>d.DateEnd).FirstOrDefault()?.DateEnd;
var telemetryDataSaub = db.TelemetryDataSaub
.Where(t => t.DateTime >= minDate)
.Where(t => t.DateTime <= maxDate)
.Where(t => Math.Abs(t.BitDepth - t.WellDepth) < 0.0001)
.OrderBy(t => t.DateTime)
.ToArray();
var indexStart = 0;
var indexEnd = 0;
foreach (var operation in detectedOperations)
{
2024-01-30 17:28:41 +05:00
indexStart = Array.FindIndex(telemetryDataSaub, indexEnd, t => t.DateTime >= operation.DateStart );
indexEnd = Array.FindIndex(telemetryDataSaub, indexStart, t => t.DateTime > operation.DateEnd) - 1;
if(indexStart >= 0 && indexEnd >= indexStart)
{
var length = indexEnd - indexStart;
var subset = telemetryDataSaub.AsSpan(indexStart, length + 1);
var result = CalcStats(operation, subset);
2024-01-30 17:28:41 +05:00
}
}
return Task.CompletedTask;
}
private object CalcStats(DetectedOperation operation, Span<TelemetryDataSaub> telemetryDataSaub)
{
var indexStart = 0;
for (var i = 1; i < telemetryDataSaub.Length; i++)
{
var previous = telemetryDataSaub[i - 1];
var current = telemetryDataSaub[i];
2024-01-30 17:28:41 +05:00
if(IsNewCacheItem(previous, current) || i == telemetryDataSaub.Length)
{
2024-01-30 17:28:41 +05:00
var length = i - indexStart;
var span = telemetryDataSaub.Slice(indexStart, length);
indexStart = i;
var processMapDrillingCacheItem = CalcStat(operation, span);
2024-01-30 17:28:41 +05:00
}
}
return null;
}
private ProcessMapDrillingCache CalcStat(DetectedOperation operation, Span<TelemetryDataSaub> span)
{
var depthStart = span[0].WellDepth;
2024-01-30 17:28:41 +05:00
var depthEnd = span[^1].WellDepth;
var hasOscillation = false;
if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyHasOscillation, out object? HasOscillation))
hasOscillation = Convert.ToBoolean(HasOscillation);
var processMapDrillingCacheItem = new ProcessMapDrillingCache
{
DateDrillingStart = operation.DateStart,
DateDrillingEnd = operation.DateEnd,
DepthStart = depthStart,
DepthEnd = depthEnd,
Speed = (depthEnd - depthStart) / ((operation.DateEnd - operation.DateStart).TotalHours),
BlockSpeedSp = span[0].BlockSpeedSp,
Pressure = CalcValue(span, depthEnd - depthStart).Pressure,
PressureIdle = span[0].PressureIdle,
PressureSp = span[0].PressureSp,
AxialLoad = CalcValue(span, depthEnd - depthStart).AxialLoad,
AxialLoadSp = span[0].AxialLoadSp,
AxialLoadLimitMax = span[0].AxialLoadLimitMax,
RotorTorque = CalcValue(span, depthEnd - depthStart).RotorTorque,
RotorTorqueSp = span[0].RotorTorqueSp,
RotorTorqueLimitMax = span[0].RotorTorqueLimitMax,
//Значение столбца id_feed_regulator из таблицы “Фильтрованная телеметрия”
//в границах временного интервала (диапазоне).
IdFeedRegulator = span[0].IdFeedRegulator,
RotorSpeed = CalcValue(span, depthEnd - depthStart).RotorSpeed,
//?
DetectedOperationCategoryId = operation.IdCategory,
EnabledSubsystems = operation.EnabledSubsystems,
HasOscillation = hasOscillation
};
return processMapDrillingCacheItem;
}
private (
double Pressure,
double AxialLoad,
double RotorTorque,
double RotorSpeed
2024-01-30 17:28:41 +05:00
) CalcValue(Span<TelemetryDataSaub> span)
{
var sumPressure = 0.0;
var sumAxialLoad = 0.0;
var sumRotorTorque = 0.0;
var sumRotorSpeed = 0.0;
2024-01-30 17:28:41 +05:00
var diffDepthTotal = span[^1].WellDepth - span[0].WellDepth;
for (var i = 0; i < span.Length - 1; i++)
{
2024-01-30 17:28:41 +05:00
var weigth = span[i + 1].WellDepth - span[i].WellDepth;
sumPressure += () * span[i].Pressure;
sumAxialLoad += (span[i + 1].WellDepth - span[i].WellDepth) * span[i].AxialLoad;
sumRotorTorque += (span[i + 1].WellDepth - span[i].WellDepth) * span[i].RotorTorque;
sumRotorSpeed += (span[i + 1].WellDepth - span[i].WellDepth) * span[i].RotorSpeed;
}
return (
Pressure: sumPressure / diffDepthTotal,
AxialLoad: sumAxialLoad / diffDepthTotal,
RotorTorque: sumRotorTorque / diffDepthTotal,
RotorSpeed: sumRotorSpeed / diffDepthTotal
);
}
private bool IsNewCacheItem(TelemetryDataSaub previous, TelemetryDataSaub current)
{
return !(current.Mode == previous.Mode)
|| !(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);
}
}
}