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

184 lines
8.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Background.PeriodicWorks
{
/// <summary>
/// задача по добавлению данных в таблицу DataSaubStat, которая используется дл построения РТК-отчета
/// </summary>
internal class WorkDataSaubStat : Work
{
private int MechanicalDrillingCategoryId = 4001;
public WorkDataSaubStat() : base("Generate DataSaubStat entries and save them into Db")
{
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>();
var dateEnd = db.Set<DataSaubStat>()
.OrderByDescending(c => c.DateEnd)
.FirstOrDefault()?.DateEnd
?? DateTimeOffset.MinValue;
var detectedOperations = db.Set<DetectedOperation>()
.Where(o => o.DateStart > dateEnd)
.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.Set<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)
{
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, db);
}
}
return Task.CompletedTask;
}
private int CalcStats(DetectedOperation operation, Span<TelemetryDataSaub> telemetryDataSaub, IAsbCloudDbContext db)
{
var indexStart = 0;
for (var i = 1; i < telemetryDataSaub.Length; i++)
{
var previous = telemetryDataSaub[i - 1];
var current = telemetryDataSaub[i];
if (IsNewCacheItem(previous, current) || i == telemetryDataSaub.Length - 1)
{
var length = i - indexStart;
var span = telemetryDataSaub.Slice(indexStart, length);
indexStart = i;
var dataSaubStatItem = CalcStat(operation, span);
db.Set<DataSaubStat>().Add(dataSaubStatItem);
}
}
return db.SaveChanges();
}
private DataSaubStat CalcStat(DetectedOperation operation, Span<TelemetryDataSaub> span)
{
var hasOscillation = operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyHasOscillation, out object? hasOscillationObject)
&& hasOscillationObject is true;
var wavg = CalcWavg(span);
var processMapDrillingCacheItem = new DataSaubStat
{
DateStart = operation.DateStart,
DateEnd = operation.DateEnd,
DepthStart = operation.DepthStart,
DepthEnd = operation.DepthEnd,
Speed = (operation.DepthEnd - operation.DepthStart) / ((operation.DateEnd - operation.DateStart).TotalHours),
BlockSpeedSp = span[0].BlockSpeedSp,
Pressure = wavg.Pressure,
PressureIdle = span[0].PressureIdle,
PressureSp = span[0].PressureSp,
AxialLoad = wavg.AxialLoad,
AxialLoadSp = span[0].AxialLoadSp,
AxialLoadLimitMax = span[0].AxialLoadLimitMax,
RotorTorque = wavg.RotorTorque,
RotorTorqueSp = span[0].RotorTorqueSp,
RotorTorqueLimitMax = span[0].RotorTorqueLimitMax,
IdFeedRegulator = span[0].IdFeedRegulator,
RotorSpeed = wavg.RotorSpeed,
DetectedOperationCategoryId = operation.IdCategory,
EnabledSubsystems = operation.EnabledSubsystems,
HasOscillation = hasOscillation,
IdTelemetry = operation.IdTelemetry,
Flow = wavg.Flow
};
return processMapDrillingCacheItem;
}
private (
double Pressure,
double AxialLoad,
double RotorTorque,
double RotorSpeed,
double Flow
) CalcWavg(Span<TelemetryDataSaub> 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 weigth = span[i + 1].WellDepth - span[i].WellDepth;
sumPressure += weigth * span[i].Pressure;
sumAxialLoad += weigth * span[i].AxialLoad;
sumRotorTorque += weigth * span[i].RotorTorque;
sumRotorSpeed += weigth * 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 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);
}
}
}