forked from ddrilling/AsbCloudServer
правки после ревью
This commit is contained in:
parent
4f2bc9244e
commit
0fdb1ede72
@ -11,27 +11,27 @@ namespace AsbCloudApp.Data
|
||||
/// <summary>
|
||||
/// Нет ограничения
|
||||
/// </summary>
|
||||
public static int NoLimit = 0;
|
||||
public const int NoLimit = 0;
|
||||
|
||||
/// <summary>
|
||||
/// МСП
|
||||
/// </summary>
|
||||
public static int RopPlan = 1;
|
||||
public const int RopPlan = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Давление
|
||||
/// </summary>
|
||||
public static int Pressure = 2;
|
||||
public const int Pressure = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Осевая нагрузка
|
||||
/// </summary>
|
||||
public static int AxialLoad = 3;
|
||||
public const int AxialLoad = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Момент
|
||||
/// </summary>
|
||||
public static int RotorTorque = 4;
|
||||
public const int RotorTorque = 4;
|
||||
/// <summary>
|
||||
/// Идентификатор скважины
|
||||
/// </summary>
|
||||
|
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudApp.Data.ProcessMaps.Report;
|
||||
|
||||
/// <summary>
|
||||
/// Модель РТК
|
||||
/// </summary>
|
||||
public class ProcessMapReportDataSaubStatDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Время, затраченное на бурение интервала, в часах
|
||||
/// </summary>
|
||||
public double DrilledTime { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор скважины
|
||||
/// </summary>
|
||||
public int IdWell { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id секции скважины
|
||||
/// </summary>
|
||||
public int IdWellSectionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Название секции скважины
|
||||
/// </summary>
|
||||
public string WellSectionTypeName { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Глубина по стволу от, м
|
||||
/// <para>
|
||||
/// на начало интервала
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public double DepthStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Глубина по стволу до, м
|
||||
/// <para>
|
||||
/// на конец интервала
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public double DepthEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата/ время
|
||||
/// <para>
|
||||
/// на начало интервала
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public DateTime DateStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Режим бурения (Ротор/слайд/ручной)
|
||||
/// </summary>
|
||||
public string DrillingMode { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Проходка, м
|
||||
/// </summary>
|
||||
public double? DeltaDepth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Перепад давления, атм
|
||||
/// </summary>
|
||||
public ProcessMapReportDataSaubStatParamsDto PressureDiff { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Нагрузка, т
|
||||
/// </summary>
|
||||
public ProcessMapReportDataSaubStatParamsDto AxialLoad { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Момент на ВСП, кНхМ
|
||||
/// </summary>
|
||||
public ProcessMapReportDataSaubStatParamsDto TopDriveTorque { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Ограничение скорости, м/ч
|
||||
/// </summary>
|
||||
public ProcessMapReportDataSaubStatParamsDto SpeedLimit { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Обороты ВСП, об/мин
|
||||
/// </summary>
|
||||
public ProcessMapReportDataSaubStatParamsDto Turnover { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Расход, л/с
|
||||
/// </summary>
|
||||
public ProcessMapReportDataSaubStatParamsDto Flow { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Механическая скорость, м/ч
|
||||
/// </summary>
|
||||
public PlanFactDto<double?> Rop { get; set; } = new();
|
||||
}
|
32
AsbCloudApp/Extensions/ChangeLogExtensions.cs
Normal file
32
AsbCloudApp/Extensions/ChangeLogExtensions.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using AsbCloudApp.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Расширения для поиска в истории
|
||||
/// </summary>
|
||||
public static class ChangeLogExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Действительные на момент времени значения
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="moment"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> WhereActualAtMoment<T>(this IEnumerable<T> items, DateTimeOffset moment)
|
||||
where T : ChangeLogAbstract
|
||||
{
|
||||
var actualItems = items
|
||||
.Where(item => item.Creation >= moment)
|
||||
.Where(item => item.Obsolete is null || item.Obsolete <= moment);
|
||||
|
||||
return actualItems;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,9 +14,11 @@ namespace AsbCloudApp.Repositories
|
||||
/// Получение записей по ключу телеметрии
|
||||
/// </summary>
|
||||
/// <param name="idTelemetry">ключ телеметрии</param>
|
||||
/// <param name="geDepth">начальная глубина</param>
|
||||
/// <param name="leDepth">конечная глубина</param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<DataSaubStatDto>> GetAsync(int idTelemetry, CancellationToken token);
|
||||
Task<IEnumerable<DataSaubStatDto>> GetAsync(int idTelemetry, double geDepth, double leDepth, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получение последних по дате окончания бурения записей в разрезе телеметрий
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace AsbCloudApp.Requests
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Requests
|
||||
{
|
||||
/// <summary>
|
||||
/// Параметры запроса для построения отчёта
|
||||
@ -7,18 +9,24 @@
|
||||
{
|
||||
/// <summary>
|
||||
/// Изменение уставки факт перепада давления от первого значения в начале интервала
|
||||
/// Не менее 5 атм и не более 15(50) атм;
|
||||
/// </summary>
|
||||
public double DeltaPressure { get; set; }
|
||||
[Range(5, 15, ErrorMessage = "Изменение уставки факт перепада давления не может быть меньше 5 и больше 15 атм")]
|
||||
public double DeltaPressure { get; set; } = 5d;
|
||||
|
||||
/// <summary>
|
||||
/// Изменение уставки факт осевой нагрузки от первого значения в начале интервала
|
||||
/// Изменение уставки факт осевой нагрузки от первого значения в начале интервала
|
||||
/// Не менее 1 т и не более 5(20) т;
|
||||
/// </summary>
|
||||
public double DeltaAxialLoad { get; set; }
|
||||
[Range(1, 5, ErrorMessage = "Изменение уставки факт осевой нагрузки не может быть меньше 1 и больше 5 т")]
|
||||
public double DeltaAxialLoad { get; set; } = 1d;
|
||||
|
||||
/// <summary>
|
||||
/// Изменение уставки момента от первого значения в начале интервала
|
||||
/// Изменение уставки момента от первого значения в начале интервала
|
||||
/// Не менее 5 кН*м и не более 10(20) кН*м.
|
||||
/// </summary>
|
||||
public double DeltaRotorTorque { get; set; }
|
||||
[Range(5, 10, ErrorMessage = "Изменение уставки момента не может быть меньше 5 и больше 10 кН*м")]
|
||||
public double DeltaRotorTorque { get; set; } = 5d;
|
||||
|
||||
/// <summary>
|
||||
/// Изменение ограничения нагрузки от первого значения в начале интервала
|
||||
|
@ -40,12 +40,14 @@ namespace AsbCloudInfrastructure.Repository
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<DataSaubStatDto>> GetAsync(int idTelemetry, CancellationToken token)
|
||||
public async Task<IEnumerable<DataSaubStatDto>> GetAsync(int idTelemetry, double geDepth, double leDepth, CancellationToken token)
|
||||
{
|
||||
var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours);
|
||||
|
||||
var stats = await db.Set<DataSaubStat>()
|
||||
.Where(s => s.IdTelemetry == idTelemetry)
|
||||
.Where(s => s.DepthStart >= geDepth)
|
||||
.Where(s => s.DepthEnd <= leDepth)
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var result = stats.Select(s => ConvertToDto(s, timeSpan));
|
||||
|
@ -2,6 +2,7 @@
|
||||
using AsbCloudApp.Data.ProcessMapPlan;
|
||||
using AsbCloudApp.Data.ProcessMaps.Report;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Extensions;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services;
|
||||
@ -48,24 +49,30 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
if (!processMapPlanWellDrillings.Any())
|
||||
return Enumerable.Empty<ProcessMapReportDataSaubStatDto>();
|
||||
|
||||
var dataSaubStats =
|
||||
(await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, token)).ToArray();
|
||||
|
||||
if (!dataSaubStats.Any())
|
||||
return Enumerable.Empty<ProcessMapReportDataSaubStatDto>();
|
||||
var geDepth = processMapPlanWellDrillings.Min(p => p.DepthStart);
|
||||
var leDepth = processMapPlanWellDrillings.Max(p => p.DepthEnd);
|
||||
|
||||
var requestWellOperationFact = new WellOperationRequest()
|
||||
{
|
||||
IdWell = idWell,
|
||||
OperationType = WellOperation.IdOperationTypeFact
|
||||
OperationType = WellOperation.IdOperationTypeFact,
|
||||
GeDepth = geDepth,
|
||||
LeDepth = leDepth
|
||||
};
|
||||
var wellOperations = await wellOperationRepository
|
||||
.GetAsync(requestWellOperationFact, token);
|
||||
if (!wellOperations.Any())
|
||||
return Enumerable.Empty<ProcessMapReportDataSaubStatDto>();
|
||||
|
||||
var timeZone = TimeSpan.FromHours(wellService.GetTimezone(idWell).Hours);
|
||||
var result = CalcByIntervals(request, processMapPlanWellDrillings, dataSaubStats, wellOperations, timeZone);
|
||||
var dataSaubStats =
|
||||
(await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, geDepth, leDepth, token)).ToArray();
|
||||
|
||||
if (!dataSaubStats.Any())
|
||||
return Enumerable.Empty<ProcessMapReportDataSaubStatDto>();
|
||||
|
||||
var wellOperationCategories = wellOperationRepository.GetCategories(false);
|
||||
|
||||
var result = CalcByIntervals(request, processMapPlanWellDrillings, dataSaubStats, wellOperations, wellOperationCategories);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -75,7 +82,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
IEnumerable<ProcessMapPlanDrillingDto> processMapPlanWellDrillings,
|
||||
Span<DataSaubStatDto> dataSaubStats,
|
||||
IEnumerable<WellOperationDto> wellOperations,
|
||||
TimeSpan timeZone
|
||||
IEnumerable<WellOperationCategoryDto> wellOperationCategories
|
||||
)
|
||||
{
|
||||
var list = new List<ProcessMapReportDataSaubStatDto>();
|
||||
@ -88,56 +95,66 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
if (IsNewInterval(currentElem, firstElemInInterval, request) || i == dataSaubStats.Length - 1)
|
||||
{
|
||||
var length = i - indexStart;
|
||||
var elem = CalcStat(processMapPlanWellDrillings, dataSaubStats, indexStart, length, wellOperations, timeZone);
|
||||
if (elem != null)
|
||||
list.Add(elem);
|
||||
|
||||
var span = dataSaubStats.Slice(indexStart, length);
|
||||
|
||||
indexStart = i;
|
||||
firstElemInInterval = currentElem;
|
||||
|
||||
var firstElemInSpan = span[0];
|
||||
var lastElemInISpan = span[^1];
|
||||
|
||||
var nearestOperation = wellOperations.MinBy(o => firstElemInSpan.DateStart - o.DateStart);
|
||||
if (nearestOperation is null)
|
||||
continue;
|
||||
|
||||
var processMapPlanFilteredByDepth = processMapPlanWellDrillings
|
||||
.Where(x => x.IdWellSectionType == nearestOperation.IdWellSectionType)
|
||||
.Where(x => x.DepthStart >= firstElemInSpan.DepthStart)
|
||||
.Where(x => x.DepthEnd <= lastElemInISpan.DepthEnd)
|
||||
.WhereActualAtMoment(DateTimeOffset.Now)
|
||||
.ToArray();
|
||||
|
||||
if (!processMapPlanFilteredByDepth.Any())
|
||||
continue;
|
||||
|
||||
var wellOperationCategoryName = wellOperationCategories.
|
||||
Where(c => c.Id == currentElem.IdCategory)
|
||||
.FirstOrDefault()
|
||||
?.Name ?? string.Empty;
|
||||
|
||||
var elem = CalcStat(processMapPlanFilteredByDepth, span, nearestOperation, wellOperationCategoryName);
|
||||
if (elem is not null)
|
||||
list.Add(elem);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private ProcessMapReportDataSaubStatDto? CalcStat(
|
||||
IEnumerable<ProcessMapPlanDrillingDto> processMapPlanDrillingDtos,
|
||||
Span<DataSaubStatDto> dataSaubStats,
|
||||
int indexStart,
|
||||
int length,
|
||||
IEnumerable<WellOperationDto> wellOperations,
|
||||
TimeSpan timeZone
|
||||
ProcessMapPlanDrillingDto[] processMapPlanFilteredByDepth,
|
||||
Span<DataSaubStatDto> span,
|
||||
WellOperationDto nearestOperation,
|
||||
string wellOperationCategoryName
|
||||
)
|
||||
{
|
||||
var span = dataSaubStats.Slice(indexStart, length);
|
||||
var firstElemInInterval = span[0];
|
||||
var lastElemInInterval = span[^1];
|
||||
|
||||
var nearestOperation = wellOperations?.MinBy(o => firstElemInInterval.DateStart - o.DateStart);
|
||||
if (nearestOperation is null)
|
||||
return null;
|
||||
|
||||
var processMapPlanFilteredByDepth = processMapPlanDrillingDtos
|
||||
.Where(x => x.IdWellSectionType == nearestOperation.IdWellSectionType)
|
||||
.Where(x => x.DepthStart >= firstElemInInterval.DepthStart)
|
||||
.Where(x => x.DepthEnd <= lastElemInInterval.DepthEnd)
|
||||
.ToArray();
|
||||
if (!processMapPlanFilteredByDepth.Any())
|
||||
return null;
|
||||
|
||||
var deltaDepth = lastElemInInterval.DepthEnd - firstElemInInterval.DepthStart;
|
||||
var drilledTime = (lastElemInInterval.DateEnd - firstElemInInterval.DateStart).TotalHours;
|
||||
|
||||
|
||||
var aggregatedValues = CalcAggregate(span);
|
||||
|
||||
return new ProcessMapReportDataSaubStatDto()
|
||||
{
|
||||
DateStart = firstElemInInterval.DateStart.ToOffset(timeZone).DateTime,
|
||||
DateStart = firstElemInInterval.DateStart.DateTime,
|
||||
WellSectionTypeName = nearestOperation.WellSectionTypeName ?? string.Empty,
|
||||
DepthStart = firstElemInInterval.DepthStart,
|
||||
DepthEnd = lastElemInInterval.DepthEnd,
|
||||
DeltaDepth = deltaDepth,
|
||||
DrilledTime = drilledTime,
|
||||
DrillingMode = nearestOperation.CategoryName ?? string.Empty,
|
||||
DrilledTime = aggregatedValues.DrilledTime,
|
||||
DrillingMode = wellOperationCategoryName,
|
||||
PressureDiff = new ProcessMapReportDataSaubStatParamsDto()
|
||||
{
|
||||
SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.DeltaPressurePlan),
|
||||
@ -171,7 +188,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
SetpointPlanMax = processMapPlanFilteredByDepth.Max(p => p.RopPlan),
|
||||
SetpointPlanMin = processMapPlanFilteredByDepth.Min(p => p.RopPlan),
|
||||
SetpointFact = aggregatedValues.BlockSpeedSp,
|
||||
FactWavg = deltaDepth / drilledTime,
|
||||
FactWavg = deltaDepth / aggregatedValues.DrilledTime,
|
||||
SetpointUsage = aggregatedValues.SetpointUsageRopPlan
|
||||
},
|
||||
Turnover = new ProcessMapReportDataSaubStatParamsDto
|
||||
@ -191,7 +208,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
Rop = new PlanFactDto<double?>
|
||||
{
|
||||
Plan = CalcRopPlan(processMapPlanFilteredByDepth),
|
||||
Fact = deltaDepth / drilledTime
|
||||
Fact = deltaDepth / aggregatedValues.DrilledTime
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -210,7 +227,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
double SetpointUsagePressure,
|
||||
double SetpointUsageAxialLoad,
|
||||
double SetpointUsageRotorTorque,
|
||||
double SetpointUsageRopPlan
|
||||
double SetpointUsageRopPlan,
|
||||
double DrilledTime
|
||||
) CalcAggregate(Span<DataSaubStatDto> span)
|
||||
{
|
||||
var sumPressure = 0.0;
|
||||
@ -229,11 +247,13 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
var sumDiffDepthByRopPlan = 0.0;
|
||||
|
||||
var diffDepthTotal = 0.0;
|
||||
var drilledTime = 0.0;
|
||||
|
||||
for (var i = 0; i < span.Length; i++)
|
||||
{
|
||||
var diffDepth = span[i].DepthEnd - span[i].DepthStart;
|
||||
|
||||
sumPressure += diffDepth * span[i].Pressure;
|
||||
sumPressure += diffDepth * ((span[i].PressureIdle ?? 0) - span[i].Pressure);
|
||||
sumAxialLoadSp += diffDepth * (span[i].AxialLoadSp ?? 0);
|
||||
sumAxialLoad += diffDepth * span[i].AxialLoad;
|
||||
sumRotorTorqueSp += diffDepth * (span[i].RotorTorqueSp ?? 0);
|
||||
@ -254,8 +274,7 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
sumDiffDepthByRopPlan += span[i].DepthEnd - span[i].DepthStart;
|
||||
|
||||
diffDepthTotal += diffDepth;
|
||||
|
||||
|
||||
drilledTime += (span[i].DateEnd - span[i].DateStart).TotalHours;
|
||||
}
|
||||
return (
|
||||
Pressure: sumPressure / diffDepthTotal,
|
||||
@ -271,7 +290,8 @@ namespace AsbCloudInfrastructure.Services.ProcessMaps.Report
|
||||
SetpointUsagePressure: sumDiffDepthByPressure / diffDepthTotal,
|
||||
SetpointUsageAxialLoad: sumDiffDepthByAxialLoad / diffDepthTotal,
|
||||
SetpointUsageRotorTorque: sumDiffDepthByRotorTorque / diffDepthTotal,
|
||||
SetpointUsageRopPlan: sumDiffDepthByRopPlan / diffDepthTotal
|
||||
SetpointUsageRopPlan: sumDiffDepthByRopPlan / diffDepthTotal,
|
||||
DrilledTime: drilledTime
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user