forked from ddrilling/AsbCloudServer
Merge branch 'dev' into feature/import
This commit is contained in:
commit
9d6fa75a01
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace AsbCloudApp.Data
|
namespace AsbCloudApp.Data
|
||||||
{
|
{
|
||||||
public class DataSaubStatDto
|
public class DataSaubStatDto:IId
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -8,6 +8,30 @@ namespace AsbCloudApp.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LimitingParameterDto
|
public class LimitingParameterDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Нет ограничения
|
||||||
|
/// </summary>
|
||||||
|
public const int NoLimit = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// МСП
|
||||||
|
/// </summary>
|
||||||
|
public const int RopPlan = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Давление
|
||||||
|
/// </summary>
|
||||||
|
public const int Pressure = 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Осевая нагрузка
|
||||||
|
/// </summary>
|
||||||
|
public const int AxialLoad = 3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Момент
|
||||||
|
/// </summary>
|
||||||
|
public const int RotorTorque = 4;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Идентификатор скважины
|
/// Идентификатор скважины
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Data.ProcessMaps.Report;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Модель РТК
|
||||||
|
/// </summary>
|
||||||
|
public class ProcessMapReportDataSaubStatDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Время, затраченное на бурение интервала, в часах
|
||||||
|
/// </summary>
|
||||||
|
public double DrilledTime { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <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 TopDriveSpeed { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Расход, л/с
|
||||||
|
/// </summary>
|
||||||
|
public ProcessMapReportDataSaubStatParamsDto Flow { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Механическая скорость, м/ч
|
||||||
|
/// </summary>
|
||||||
|
public PlanFactDto<double?> Rop { get; set; } = new();
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
namespace AsbCloudApp.Data.ProcessMaps.Report;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Параметры РТК
|
||||||
|
/// </summary>
|
||||||
|
public class ProcessMapReportDataSaubStatParamsDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Уставка план
|
||||||
|
/// </summary>
|
||||||
|
public double? SetpointPlan { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Уставка факт
|
||||||
|
/// </summary>
|
||||||
|
public double? SetpointFact { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Факт (средневзвешенное)
|
||||||
|
/// </summary>
|
||||||
|
public double? FactWavg { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Факт (максимум)
|
||||||
|
/// </summary>
|
||||||
|
public double? FactMax { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ограничение
|
||||||
|
/// </summary>
|
||||||
|
public double? Limit { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Процент бурения по уставке, %
|
||||||
|
/// </summary>
|
||||||
|
public double? SetpointUsage { get; set; }
|
||||||
|
}
|
@ -39,7 +39,8 @@ namespace AsbCloudApp.Data.SAUB
|
|||||||
/// время в секундах актуальности этого запроса
|
/// время в секундах актуальности этого запроса
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
[Required]
|
||||||
public int ObsolescenceSec { get; set; }
|
[Range(10 * 60, 4 * 60 * 60)]
|
||||||
|
public int ObsolescenceSec { get; set; } = 10 * 60;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// набор уставок: {"название переменной панели"; "рекомендуемое значение"}
|
/// набор уставок: {"название переменной панели"; "рекомендуемое значение"}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -10,6 +11,16 @@ namespace AsbCloudApp.Repositories
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDataSaubStatRepository
|
public interface IDataSaubStatRepository
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Получение записей по ключу телеметрии
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idTelemetry">ключ телеметрии</param>
|
||||||
|
/// <param name="geDate">начальная дата</param>
|
||||||
|
/// <param name="leDate">конечная дата</param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<DataSaubStatDto>> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение последних по дате окончания бурения записей в разрезе телеметрий
|
/// Получение последних по дате окончания бурения записей в разрезе телеметрий
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
41
AsbCloudApp/Requests/DataSaubStatRequest.cs
Normal file
41
AsbCloudApp/Requests/DataSaubStatRequest.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Requests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Параметры запроса для построения отчёта
|
||||||
|
/// </summary>
|
||||||
|
public class DataSaubStatRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Изменение уставки факт перепада давления от первого значения в начале интервала
|
||||||
|
/// Не менее 5 атм и не более 15(50) атм;
|
||||||
|
/// </summary>
|
||||||
|
[Range(5, 15, ErrorMessage = "Изменение уставки факт перепада давления не может быть меньше 5 и больше 15 атм")]
|
||||||
|
public double DeltaPressure { get; set; } = 5d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Изменение уставки факт осевой нагрузки от первого значения в начале интервала
|
||||||
|
/// Не менее 1 т и не более 5(20) т;
|
||||||
|
/// </summary>
|
||||||
|
[Range(1, 5, ErrorMessage = "Изменение уставки факт осевой нагрузки не может быть меньше 1 и больше 5 т")]
|
||||||
|
public double DeltaAxialLoad { get; set; } = 1d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Изменение уставки момента от первого значения в начале интервала
|
||||||
|
/// Не менее 5 кН*м и не более 10(20) кН*м.
|
||||||
|
/// </summary>
|
||||||
|
[Range(5, 10, ErrorMessage = "Изменение уставки момента не может быть меньше 5 и больше 10 кН*м")]
|
||||||
|
public double DeltaRotorTorque { get; set; } = 5d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Изменение ограничения нагрузки от первого значения в начале интервала
|
||||||
|
/// </summary>
|
||||||
|
public double DeltaAxialLoadSp => 1.0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Изменение ограничения момента от первого значения в начале интервала
|
||||||
|
/// </summary>
|
||||||
|
public double DeltaRotorTorqueSp => 5.0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
using AsbCloudApp.Data.ProcessMaps.Report;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Services.ProcessMaps.WellDrilling
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Получить РТК-отчет по бурению
|
||||||
|
/// </summary>
|
||||||
|
public interface IProcessMapReportDataSaubStatService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Получения строк РТК-отчёта
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">ключ скважины</param>
|
||||||
|
/// <param name="request">параметры запроса</param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<ProcessMapReportDataSaubStatDto>> GetAsync(int idWell, DataSaubStatRequest request, CancellationToken token);
|
||||||
|
}
|
||||||
|
}
|
@ -229,6 +229,8 @@ namespace AsbCloudInfrastructure
|
|||||||
IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell>,
|
IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell>,
|
||||||
ProcessMapPlanBaseRepository<ProcessMapPlanDrillingDto, ProcessMapPlanDrilling>>();
|
ProcessMapPlanBaseRepository<ProcessMapPlanDrillingDto, ProcessMapPlanDrilling>>();
|
||||||
|
|
||||||
|
services.AddTransient<IProcessMapReportDataSaubStatService, ProcessMapReportDataSaubStatService>();
|
||||||
|
|
||||||
services.AddTransient<TrajectoryService>();
|
services.AddTransient<TrajectoryService>();
|
||||||
|
|
||||||
services.AddTransient<IGtrRepository, GtrWitsRepository>();
|
services.AddTransient<IGtrRepository, GtrWitsRepository>();
|
||||||
|
@ -40,6 +40,23 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<DataSaubStatDto>> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token)
|
||||||
|
{
|
||||||
|
var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours);
|
||||||
|
var geDateUtc = geDate.ToUniversalTime();
|
||||||
|
var leDateUtc = leDate.ToUniversalTime();
|
||||||
|
|
||||||
|
var stats = await db.Set<DataSaubStat>()
|
||||||
|
.Where(s => s.IdTelemetry == idTelemetry)
|
||||||
|
.Where(s => s.DateStart >= geDateUtc)
|
||||||
|
.Where(s => s.DateEnd <= leDateUtc)
|
||||||
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
|
var result = stats.Select(s => ConvertToDto(s, timeSpan));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<int> InsertRangeAsync(IEnumerable<DataSaubStatDto> dataSaubStats, CancellationToken token)
|
public async Task<int> InsertRangeAsync(IEnumerable<DataSaubStatDto> dataSaubStats, CancellationToken token)
|
||||||
{
|
{
|
||||||
var entities = dataSaubStats.Select(data => ConvertToEntity(data));
|
var entities = dataSaubStats.Select(data => ConvertToEntity(data));
|
||||||
|
@ -17,11 +17,11 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
private readonly Dictionary<int, string> feedRegulatorData = new ()
|
private readonly Dictionary<int, string> feedRegulatorData = new ()
|
||||||
{
|
{
|
||||||
{ 0, "Нет ограничения" },
|
{ LimitingParameterDto.NoLimit, "Нет ограничения" },
|
||||||
{ 1, "МСП" },
|
{ LimitingParameterDto.RopPlan, "МСП" },
|
||||||
{ 2, "Давление" },
|
{ LimitingParameterDto.Pressure, "Давление" },
|
||||||
{ 3, "Осевая нагрузка" },
|
{ LimitingParameterDto.AxialLoad, "Осевая нагрузка" },
|
||||||
{ 4, "Момент" }
|
{ LimitingParameterDto.RotorTorque, "Момент" }
|
||||||
};
|
};
|
||||||
|
|
||||||
public LimitingParameterService(ILimitingParameterRepository limitingParameterRepository,
|
public LimitingParameterService(ILimitingParameterRepository limitingParameterRepository,
|
||||||
|
@ -0,0 +1,344 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps.Report;
|
||||||
|
using AsbCloudApp.Exceptions;
|
||||||
|
using AsbCloudApp.Extensions;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.ProcessMaps.Report;
|
||||||
|
|
||||||
|
public class ProcessMapReportDataSaubStatService : IProcessMapReportDataSaubStatService
|
||||||
|
{
|
||||||
|
private readonly IWellService wellService;
|
||||||
|
private readonly IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell> processMapPlanBaseRepository;
|
||||||
|
private readonly IDataSaubStatRepository dataSaubStatRepository;
|
||||||
|
private readonly IWellOperationRepository wellOperationRepository;
|
||||||
|
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
|
||||||
|
|
||||||
|
public ProcessMapReportDataSaubStatService(IWellService wellService,
|
||||||
|
IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell> processMapPlanBaseRepository,
|
||||||
|
IDataSaubStatRepository dataSaubStatRepository,
|
||||||
|
IWellOperationRepository wellOperationRepository,
|
||||||
|
IWellOperationCategoryRepository wellOperationCategoryRepository
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.wellService = wellService;
|
||||||
|
this.processMapPlanBaseRepository = processMapPlanBaseRepository;
|
||||||
|
this.dataSaubStatRepository = dataSaubStatRepository;
|
||||||
|
this.wellOperationRepository = wellOperationRepository;
|
||||||
|
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<ProcessMapReportDataSaubStatDto>> GetAsync(int idWell, DataSaubStatRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var well = await wellService.GetOrDefaultAsync(idWell, token)
|
||||||
|
?? throw new ArgumentInvalidException(nameof(idWell), $"Скважина с Id: {idWell} не найдена");
|
||||||
|
|
||||||
|
if (!well.IdTelemetry.HasValue)
|
||||||
|
return Enumerable.Empty<ProcessMapReportDataSaubStatDto>();
|
||||||
|
|
||||||
|
var requestProcessMapPlan = new ProcessMapPlanBaseRequestWithWell(idWell);
|
||||||
|
var processMapPlanWellDrillings = await processMapPlanBaseRepository.Get(requestProcessMapPlan, token);
|
||||||
|
|
||||||
|
if (!processMapPlanWellDrillings.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,
|
||||||
|
GeDepth = geDepth,
|
||||||
|
LeDepth = leDepth
|
||||||
|
};
|
||||||
|
var wellOperations = await wellOperationRepository
|
||||||
|
.GetAsync(requestWellOperationFact, token);
|
||||||
|
if (!wellOperations.Any())
|
||||||
|
return Enumerable.Empty<ProcessMapReportDataSaubStatDto>();
|
||||||
|
|
||||||
|
var geDate = wellOperations.Min(p => p.DateStart);
|
||||||
|
var leDate = wellOperations.Max(p => (p.DateStart.AddHours(p.DurationHours)));
|
||||||
|
var dataSaubStats =
|
||||||
|
(await dataSaubStatRepository.GetAsync(well.IdTelemetry.Value, geDate, leDate, token)).ToArray();
|
||||||
|
|
||||||
|
if (!dataSaubStats.Any())
|
||||||
|
return Enumerable.Empty<ProcessMapReportDataSaubStatDto>();
|
||||||
|
|
||||||
|
var wellOperationCategories = wellOperationCategoryRepository.Get(false);
|
||||||
|
var wellSectionTypes = wellOperationRepository.GetSectionTypes();
|
||||||
|
|
||||||
|
var result = CalcByIntervals(
|
||||||
|
request,
|
||||||
|
processMapPlanWellDrillings,
|
||||||
|
dataSaubStats,
|
||||||
|
wellOperations,
|
||||||
|
wellOperationCategories,
|
||||||
|
wellSectionTypes);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<ProcessMapReportDataSaubStatDto> CalcByIntervals(
|
||||||
|
DataSaubStatRequest request,
|
||||||
|
IEnumerable<ProcessMapPlanDrillingDto> processMapPlanWellDrillings,
|
||||||
|
Span<DataSaubStatDto> dataSaubStats,
|
||||||
|
IEnumerable<WellOperationDto> wellOperations,
|
||||||
|
IEnumerable<WellOperationCategoryDto> wellOperationCategories,
|
||||||
|
IEnumerable<WellSectionTypeDto> wellSectionTypes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var list = new List<ProcessMapReportDataSaubStatDto>();
|
||||||
|
var firstElemInInterval = dataSaubStats[0];
|
||||||
|
|
||||||
|
int GetSection(DataSaubStatDto data)
|
||||||
|
=> wellOperations.MinBy(o => data.DateStart - o.DateStart)!.IdWellSectionType;
|
||||||
|
|
||||||
|
ProcessMapPlanDrillingDto? GetProcessMapPlan(int idWellSectionType, DataSaubStatDto data)
|
||||||
|
=> processMapPlanWellDrillings
|
||||||
|
.Where(p => p.IdWellSectionType == idWellSectionType)
|
||||||
|
.Where(p => p.DepthStart <= data.DepthStart)
|
||||||
|
.Where(p => p.DepthEnd >= data.DepthStart)
|
||||||
|
.Where(p => IsModeMatchOperationCategory(p.IdMode, data.IdCategory))
|
||||||
|
.WhereActualAtMoment(data.DateStart)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
var idWellSectionType = GetSection(firstElemInInterval);
|
||||||
|
var prevProcessMapPlan = GetProcessMapPlan(idWellSectionType, firstElemInInterval);
|
||||||
|
var indexStart = 0;
|
||||||
|
|
||||||
|
for (var i = 1; i < dataSaubStats.Length; i++)
|
||||||
|
{
|
||||||
|
var currentElem = dataSaubStats[i];
|
||||||
|
idWellSectionType = GetSection(currentElem);
|
||||||
|
var processMapPlan = GetProcessMapPlan(idWellSectionType, currentElem);
|
||||||
|
|
||||||
|
if (IsNewInterval(currentElem, firstElemInInterval, request) || i == dataSaubStats.Length - 1 || processMapPlan != prevProcessMapPlan)
|
||||||
|
{
|
||||||
|
prevProcessMapPlan = processMapPlan;
|
||||||
|
var length = i - indexStart;
|
||||||
|
|
||||||
|
var span = dataSaubStats.Slice(indexStart, length);
|
||||||
|
|
||||||
|
indexStart = i;
|
||||||
|
firstElemInInterval = currentElem;
|
||||||
|
|
||||||
|
var firstElemInSpan = span[0];
|
||||||
|
var lastElemInISpan = span[^1];
|
||||||
|
|
||||||
|
var wellOperationCategoryName = wellOperationCategories
|
||||||
|
.Where(c => c.Id == firstElemInSpan.IdCategory)
|
||||||
|
.FirstOrDefault()?.Name ?? string.Empty;
|
||||||
|
|
||||||
|
var wellSectionType = wellSectionTypes
|
||||||
|
.Where(c => c.Id == idWellSectionType)
|
||||||
|
.First();
|
||||||
|
|
||||||
|
var elem = CalcStat(processMapPlan, span, wellOperationCategoryName, wellSectionType);
|
||||||
|
if (elem is not null)
|
||||||
|
list.Add(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsModeMatchOperationCategory(int idMode, int idCategory)
|
||||||
|
{
|
||||||
|
return (idMode == 1 && idCategory == 5003) || (idMode == 2 && idCategory == 5002);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProcessMapReportDataSaubStatDto? CalcStat(
|
||||||
|
ProcessMapPlanDrillingDto? processMapPlanFilteredByDepth,
|
||||||
|
Span<DataSaubStatDto> span,
|
||||||
|
string wellOperationCategoryName,
|
||||||
|
WellSectionTypeDto wellSectionType
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var firstElemInInterval = span[0];
|
||||||
|
var lastElemInInterval = span[^1];
|
||||||
|
|
||||||
|
var deltaDepth = lastElemInInterval.DepthEnd - firstElemInInterval.DepthStart;
|
||||||
|
|
||||||
|
var aggregatedValues = CalcAggregate(span);
|
||||||
|
|
||||||
|
var result = new ProcessMapReportDataSaubStatDto()
|
||||||
|
{
|
||||||
|
IdWellSectionType = wellSectionType.Id,
|
||||||
|
DateStart = firstElemInInterval.DateStart.DateTime,
|
||||||
|
WellSectionTypeName = wellSectionType.Caption,
|
||||||
|
DepthStart = firstElemInInterval.DepthStart,
|
||||||
|
DepthEnd = lastElemInInterval.DepthEnd,
|
||||||
|
DeltaDepth = deltaDepth,
|
||||||
|
DrilledTime = aggregatedValues.DrilledTime,
|
||||||
|
DrillingMode = wellOperationCategoryName,
|
||||||
|
PressureDiff = new ProcessMapReportDataSaubStatParamsDto()
|
||||||
|
{
|
||||||
|
SetpointPlan = processMapPlanFilteredByDepth?.DeltaPressurePlan,
|
||||||
|
SetpointFact = firstElemInInterval.PressureSp - firstElemInInterval.PressureIdle,
|
||||||
|
FactWavg = aggregatedValues.Pressure,
|
||||||
|
Limit = processMapPlanFilteredByDepth?.DeltaPressureLimitMax,
|
||||||
|
SetpointUsage = aggregatedValues.SetpointUsagePressure
|
||||||
|
},
|
||||||
|
AxialLoad = new ProcessMapReportDataSaubStatParamsDto()
|
||||||
|
{
|
||||||
|
SetpointPlan = processMapPlanFilteredByDepth?.AxialLoadPlan,
|
||||||
|
SetpointFact = aggregatedValues.AxialLoadSp,
|
||||||
|
FactWavg = aggregatedValues.AxialLoad,
|
||||||
|
Limit = processMapPlanFilteredByDepth?.AxialLoadLimitMax,
|
||||||
|
SetpointUsage = aggregatedValues.SetpointUsageAxialLoad
|
||||||
|
},
|
||||||
|
TopDriveTorque = new ProcessMapReportDataSaubStatParamsDto()
|
||||||
|
{
|
||||||
|
SetpointPlan = processMapPlanFilteredByDepth?.TopDriveTorquePlan,
|
||||||
|
SetpointFact = aggregatedValues.RotorTorqueSp,
|
||||||
|
FactWavg = aggregatedValues.RotorTorque,
|
||||||
|
FactMax = aggregatedValues.RotorTorqueMax,
|
||||||
|
Limit = processMapPlanFilteredByDepth?.TopDriveTorqueLimitMax,
|
||||||
|
SetpointUsage = aggregatedValues.SetpointUsageRotorTorque
|
||||||
|
},
|
||||||
|
SpeedLimit = new ProcessMapReportDataSaubStatParamsDto
|
||||||
|
{
|
||||||
|
SetpointPlan = processMapPlanFilteredByDepth?.RopPlan,
|
||||||
|
SetpointFact = aggregatedValues.BlockSpeedSp,
|
||||||
|
FactWavg = deltaDepth / aggregatedValues.DrilledTime,
|
||||||
|
SetpointUsage = aggregatedValues.SetpointUsageRopPlan
|
||||||
|
},
|
||||||
|
TopDriveSpeed = new ProcessMapReportDataSaubStatParamsDto
|
||||||
|
{
|
||||||
|
SetpointPlan = processMapPlanFilteredByDepth?.TopDriveSpeedPlan,
|
||||||
|
FactWavg = aggregatedValues.RotorSpeed,
|
||||||
|
FactMax = aggregatedValues.RotorSpeedMax
|
||||||
|
},
|
||||||
|
Flow = new ProcessMapReportDataSaubStatParamsDto
|
||||||
|
{
|
||||||
|
SetpointPlan = processMapPlanFilteredByDepth?.FlowPlan,
|
||||||
|
FactWavg = aggregatedValues.MaxFlow,
|
||||||
|
Limit = processMapPlanFilteredByDepth?.FlowLimitMax,
|
||||||
|
},
|
||||||
|
Rop = new PlanFactDto<double?>
|
||||||
|
{
|
||||||
|
Plan = processMapPlanFilteredByDepth?.RopPlan,
|
||||||
|
Fact = deltaDepth / aggregatedValues.DrilledTime
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (
|
||||||
|
double Pressure,
|
||||||
|
double AxialLoadSp,
|
||||||
|
double AxialLoad,
|
||||||
|
double RotorTorqueSp,
|
||||||
|
double RotorTorque,
|
||||||
|
double RotorTorqueMax,
|
||||||
|
double BlockSpeedSp,
|
||||||
|
double RotorSpeed,
|
||||||
|
double RotorSpeedMax,
|
||||||
|
double MaxFlow,
|
||||||
|
double SetpointUsagePressure,
|
||||||
|
double SetpointUsageAxialLoad,
|
||||||
|
double SetpointUsageRotorTorque,
|
||||||
|
double SetpointUsageRopPlan,
|
||||||
|
double DrilledTime
|
||||||
|
) CalcAggregate(Span<DataSaubStatDto> span)
|
||||||
|
{
|
||||||
|
var sumPressure = 0.0;
|
||||||
|
var sumAxialLoadSp = 0.0;
|
||||||
|
var sumAxialLoad = 0.0;
|
||||||
|
var sumRotorTorqueSp = 0.0;
|
||||||
|
var sumRotorTorque = 0.0;
|
||||||
|
var sumBlockSpeedSp = 0.0;
|
||||||
|
var sumRotorSpeed = 0.0;
|
||||||
|
var maxFlow = 0.0;
|
||||||
|
var maxRotorTorque = 0.0;
|
||||||
|
var maxRotorSpeed = 0.0;
|
||||||
|
var sumDiffDepthByPressure = 0.0;
|
||||||
|
var sumDiffDepthByAxialLoad = 0.0;
|
||||||
|
var sumDiffDepthByRotorTorque = 0.0;
|
||||||
|
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 - (span[i].PressureIdle ?? 0.0));
|
||||||
|
sumAxialLoadSp += diffDepth * (span[i].AxialLoadSp ?? 0);
|
||||||
|
sumAxialLoad += diffDepth * span[i].AxialLoad;
|
||||||
|
sumRotorTorqueSp += diffDepth * (span[i].RotorTorqueSp ?? 0);
|
||||||
|
sumRotorTorque += diffDepth * span[i].RotorTorque;
|
||||||
|
sumBlockSpeedSp += diffDepth * (span[i].BlockSpeedSp ?? 0);
|
||||||
|
sumRotorSpeed += diffDepth * span[i].RotorSpeed;
|
||||||
|
maxFlow = span[i].Flow > maxFlow ? span[i].Flow : maxFlow;
|
||||||
|
maxRotorTorque = span[i].RotorTorque > maxRotorTorque ? span[i].RotorTorque : maxRotorTorque;
|
||||||
|
maxRotorSpeed = span[i].RotorSpeed > maxRotorSpeed ? span[i].RotorSpeed : maxRotorSpeed;
|
||||||
|
|
||||||
|
if (span[i].IdFeedRegulator == LimitingParameterDto.Pressure)
|
||||||
|
sumDiffDepthByPressure += diffDepth;
|
||||||
|
if (span[i].IdFeedRegulator == LimitingParameterDto.AxialLoad)
|
||||||
|
sumDiffDepthByAxialLoad += diffDepth;
|
||||||
|
if (span[i].IdFeedRegulator == LimitingParameterDto.RotorTorque)
|
||||||
|
sumDiffDepthByRotorTorque += diffDepth;
|
||||||
|
if (span[i].IdFeedRegulator == LimitingParameterDto.RopPlan)
|
||||||
|
sumDiffDepthByRopPlan += diffDepth;
|
||||||
|
|
||||||
|
diffDepthTotal += diffDepth;
|
||||||
|
drilledTime += (span[i].DateEnd - span[i].DateStart).TotalHours;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
Pressure: sumPressure / diffDepthTotal,
|
||||||
|
AxialLoadSp: sumAxialLoadSp / diffDepthTotal,
|
||||||
|
AxialLoad: sumAxialLoad / diffDepthTotal,
|
||||||
|
RotorTorqueSp: sumRotorTorqueSp / diffDepthTotal,
|
||||||
|
RotorTorque: sumRotorTorque / diffDepthTotal,
|
||||||
|
RotorTorqueMax: maxRotorTorque,
|
||||||
|
BlockSpeedSp: sumBlockSpeedSp / diffDepthTotal,
|
||||||
|
RotorSpeed: sumRotorSpeed / diffDepthTotal,
|
||||||
|
RotorSpeedMax: maxRotorSpeed,
|
||||||
|
MaxFlow: maxFlow,
|
||||||
|
SetpointUsagePressure: sumDiffDepthByPressure / diffDepthTotal,
|
||||||
|
SetpointUsageAxialLoad: sumDiffDepthByAxialLoad / diffDepthTotal,
|
||||||
|
SetpointUsageRotorTorque: sumDiffDepthByRotorTorque / diffDepthTotal,
|
||||||
|
SetpointUsageRopPlan: sumDiffDepthByRopPlan / diffDepthTotal,
|
||||||
|
DrilledTime: drilledTime
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsNewInterval(DataSaubStatDto currentElem, DataSaubStatDto firstElem, DataSaubStatRequest request)
|
||||||
|
{
|
||||||
|
static bool IsNewElemBySpeed(double currentSpeed, double firstSpeed)
|
||||||
|
{
|
||||||
|
//2. Изменение уставки скорости подачи от первого значения в начале интервала при условии:
|
||||||
|
//скорость > 80 м/ч => изменение уставки на ± 20 м/ч;
|
||||||
|
//скорость > 30 м/ч => изменение уставки на ± 15 м/ч;
|
||||||
|
//скорость <= 30 м/ч => изменение уставки на ± 5 м/ч;
|
||||||
|
if (firstSpeed > 80)
|
||||||
|
return Math.Abs(currentSpeed - firstSpeed) >= 20;
|
||||||
|
else if (firstSpeed > 30)
|
||||||
|
return Math.Abs(currentSpeed - firstSpeed) >= 15;
|
||||||
|
else
|
||||||
|
return Math.Abs(currentSpeed - firstSpeed) >= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isNewElem = (currentElem.IdCategory != firstElem.IdCategory)
|
||||||
|
|| (Math.Abs(currentElem.Pressure - firstElem.Pressure) >= request.DeltaPressure)
|
||||||
|
|| (Math.Abs(currentElem.AxialLoad - firstElem.AxialLoad) >= request.DeltaAxialLoad)
|
||||||
|
|| (Math.Abs(currentElem.RotorTorque - firstElem.RotorTorque) >= request.DeltaRotorTorque)
|
||||||
|
|| (Math.Abs((currentElem.AxialLoadSp ?? 0) - (firstElem.AxialLoadSp ?? 0)) >= request.DeltaAxialLoadSp)
|
||||||
|
|| (Math.Abs((currentElem.RotorTorqueSp ?? 0) - (firstElem.RotorTorqueSp ?? 0)) >= request.DeltaRotorTorqueSp)
|
||||||
|
|| (IsNewElemBySpeed(currentElem.Speed, firstElem.Speed));
|
||||||
|
return isNewElem;
|
||||||
|
}
|
||||||
|
}
|
@ -275,7 +275,7 @@ public class DailyReportServiceTest
|
|||||||
wellOperationRepositoryMock.GetSectionTypes()
|
wellOperationRepositoryMock.GetSectionTypes()
|
||||||
.ReturnsForAnyArgs(new[] { fakeSectionType });
|
.ReturnsForAnyArgs(new[] { fakeSectionType });
|
||||||
|
|
||||||
detectedOperationServiceMock.GetAsync(Arg.Any<DetectedOperationRequest>(), Arg.Any<CancellationToken>())
|
detectedOperationServiceMock.GetAsync(Arg.Any<DetectedOperationByWellRequest>(), Arg.Any<CancellationToken>())
|
||||||
.ReturnsForAnyArgs(fakeWellOperationSlipsTime);
|
.ReturnsForAnyArgs(fakeWellOperationSlipsTime);
|
||||||
|
|
||||||
subsystemServiceMock.GetStatAsync(Arg.Any<SubsystemRequest>(), Arg.Any<CancellationToken>())
|
subsystemServiceMock.GetStatAsync(Arg.Any<SubsystemRequest>(), Arg.Any<CancellationToken>())
|
||||||
|
@ -0,0 +1,292 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudInfrastructure.Repository;
|
||||||
|
using AsbCloudInfrastructure.Services.ProcessMaps;
|
||||||
|
using AsbCloudInfrastructure.Services.ProcessMaps.Report;
|
||||||
|
using DocumentFormat.OpenXml.Bibliography;
|
||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Tests.Services.ProcessMaps;
|
||||||
|
|
||||||
|
public class ProcessMapReportDataSaubStatServiceTest
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
private IWellService wellService
|
||||||
|
= Substitute.For<IWellService>();
|
||||||
|
|
||||||
|
private IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell> processMapPlanBaseRepository
|
||||||
|
= Substitute.For<IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell>>();
|
||||||
|
|
||||||
|
private IWellOperationRepository wellOperationRepository
|
||||||
|
= Substitute.For<IWellOperationRepository>();
|
||||||
|
|
||||||
|
private IWellOperationCategoryRepository wellOperationCategoryRepository
|
||||||
|
= Substitute.For<IWellOperationCategoryRepository>();
|
||||||
|
|
||||||
|
private IDataSaubStatRepository dataSaubStatRepository
|
||||||
|
= Substitute.For<IDataSaubStatRepository>();
|
||||||
|
|
||||||
|
private ProcessMapReportDataSaubStatService service;
|
||||||
|
|
||||||
|
private readonly static SimpleTimezoneDto timezone = new() { Hours = 2 };
|
||||||
|
private static readonly DateTimeOffset dateStart = new (2024, 01, 01, 00, 11, 11, timezone.Offset);
|
||||||
|
private readonly static WellDto well = new()
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
IdTelemetry = 1,
|
||||||
|
Timezone = timezone
|
||||||
|
};
|
||||||
|
private readonly static IEnumerable<ProcessMapPlanDrillingDto> processMapPlan = new List<ProcessMapPlanDrillingDto>()
|
||||||
|
{
|
||||||
|
new() {
|
||||||
|
DepthStart = 0,
|
||||||
|
DepthEnd = 100,
|
||||||
|
IdMode = 1,
|
||||||
|
IdWell = well.Id,
|
||||||
|
IdWellSectionType = 1,
|
||||||
|
AxialLoadPlan = 0.2,
|
||||||
|
AxialLoadLimitMax = 0.3,
|
||||||
|
DeltaPressurePlan = 0.4,
|
||||||
|
DeltaPressureLimitMax = 0.5,
|
||||||
|
TopDriveTorquePlan = 0.6,
|
||||||
|
TopDriveTorqueLimitMax = 0.7,
|
||||||
|
TopDriveSpeedPlan = 0.8,
|
||||||
|
TopDriveSpeedLimitMax = 0.9,
|
||||||
|
FlowPlan = 0.10,
|
||||||
|
FlowLimitMax = 0.11,
|
||||||
|
RopPlan = 0.12,
|
||||||
|
UsageSaub = 0.12,
|
||||||
|
UsageSpin = 0.14,
|
||||||
|
Comment = "r",
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
DepthStart = 0,
|
||||||
|
DepthEnd = 100,
|
||||||
|
IdMode = 2,
|
||||||
|
IdWell = well.Id,
|
||||||
|
IdWellSectionType = 1,
|
||||||
|
AxialLoadPlan = 0.12,
|
||||||
|
AxialLoadLimitMax = 0.13,
|
||||||
|
DeltaPressurePlan = 0.14,
|
||||||
|
DeltaPressureLimitMax = 0.15,
|
||||||
|
TopDriveTorquePlan = 0.16,
|
||||||
|
TopDriveTorqueLimitMax = 0.17,
|
||||||
|
TopDriveSpeedPlan = 0.18,
|
||||||
|
TopDriveSpeedLimitMax = 0.19,
|
||||||
|
FlowPlan = 0.110,
|
||||||
|
FlowLimitMax = 0.111,
|
||||||
|
RopPlan = 0.112,
|
||||||
|
UsageSaub = 0.112,
|
||||||
|
UsageSpin = 0.114,
|
||||||
|
Comment = "s",
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
DepthStart = 100,
|
||||||
|
DepthEnd = 200,
|
||||||
|
IdMode = 1,
|
||||||
|
IdWell = well.Id,
|
||||||
|
IdWellSectionType = 1,
|
||||||
|
AxialLoadPlan = 0.22,
|
||||||
|
AxialLoadLimitMax = 0.23,
|
||||||
|
DeltaPressurePlan = 0.24,
|
||||||
|
DeltaPressureLimitMax = 0.25,
|
||||||
|
TopDriveTorquePlan = 0.26,
|
||||||
|
TopDriveTorqueLimitMax = 0.27,
|
||||||
|
TopDriveSpeedPlan = 0.28,
|
||||||
|
TopDriveSpeedLimitMax = 0.29,
|
||||||
|
FlowPlan = 0.210,
|
||||||
|
FlowLimitMax = 0.211,
|
||||||
|
RopPlan = 0.212,
|
||||||
|
UsageSaub = 0.212,
|
||||||
|
UsageSpin = 0.214,
|
||||||
|
Comment = "r",
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
DepthStart = 100,
|
||||||
|
DepthEnd = 200,
|
||||||
|
IdMode = 2,
|
||||||
|
IdWell = well.Id,
|
||||||
|
IdWellSectionType = 1,
|
||||||
|
AxialLoadPlan = 0.32,
|
||||||
|
AxialLoadLimitMax = 0.33,
|
||||||
|
DeltaPressurePlan = 0.34,
|
||||||
|
DeltaPressureLimitMax = 0.35,
|
||||||
|
TopDriveTorquePlan = 0.36,
|
||||||
|
TopDriveTorqueLimitMax = 0.37,
|
||||||
|
TopDriveSpeedPlan = 0.38,
|
||||||
|
TopDriveSpeedLimitMax = 0.39,
|
||||||
|
FlowPlan = 0.310,
|
||||||
|
FlowLimitMax = 0.311,
|
||||||
|
RopPlan = 0.312,
|
||||||
|
UsageSaub = 0.312,
|
||||||
|
UsageSpin = 0.314,
|
||||||
|
Comment = "s",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
private readonly static IEnumerable<WellOperationDto> operations = new List<WellOperationDto>()
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
IdWell = well.Id,
|
||||||
|
IdWellSectionType = 1,
|
||||||
|
IdCategory = WellOperationCategory.IdRotor,
|
||||||
|
IdParentCategory = WellOperationCategory.IdMechanicalDrilling,
|
||||||
|
IdType = WellOperation.IdOperationTypeFact,
|
||||||
|
DepthStart = 0,
|
||||||
|
DepthEnd = 10,
|
||||||
|
DateStart = dateStart,
|
||||||
|
DurationHours = 1,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
IdWell = well.Id,
|
||||||
|
IdWellSectionType = 2,
|
||||||
|
IdCategory = WellOperationCategory.IdRotor,
|
||||||
|
IdParentCategory = WellOperationCategory.IdMechanicalDrilling,
|
||||||
|
IdType = WellOperation.IdOperationTypeFact,
|
||||||
|
DepthStart = 50,
|
||||||
|
DepthEnd = 100,
|
||||||
|
DateStart = dateStart,
|
||||||
|
DurationHours = 1,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private readonly static IEnumerable<WellOperationCategoryDto> operationCategories = new List<WellOperationCategoryDto>()
|
||||||
|
{
|
||||||
|
new(){Id = WellOperationCategory.IdRotor, IdParent = WellOperationCategory.IdMechanicalDrilling, Name = "РОТОР"},
|
||||||
|
new(){Id = WellOperationCategory.IdSlide, IdParent = WellOperationCategory.IdMechanicalDrilling, Name = "СЛАЙД"},
|
||||||
|
};
|
||||||
|
private readonly static IEnumerable<WellSectionTypeDto> sectionTypes = new List<WellSectionTypeDto>() {
|
||||||
|
new(){ Id = 1, Caption = "Секция 1"},
|
||||||
|
new(){ Id = 2, Caption = "Секция 2"},
|
||||||
|
new(){ Id = 3, Caption = "Секция 3"},
|
||||||
|
new(){ Id = 4, Caption = "Секция 4"},
|
||||||
|
};
|
||||||
|
private readonly static IEnumerable<DataSaubStatDto> dataSaubStat = new List<DataSaubStatDto>() {
|
||||||
|
new(){
|
||||||
|
Id = 1,
|
||||||
|
IdTelemetry = 1,
|
||||||
|
IdCategory = WellOperationCategory.IdRotor,
|
||||||
|
DateStart = dateStart,
|
||||||
|
DateEnd = dateStart.AddHours(3.25),
|
||||||
|
DepthStart = 0,
|
||||||
|
DepthEnd = 20,
|
||||||
|
Speed = 0.1,
|
||||||
|
BlockSpeedSp = 0.2,
|
||||||
|
Pressure = 0.3,
|
||||||
|
PressureIdle = 0.4,
|
||||||
|
PressureSp = 0.5,
|
||||||
|
AxialLoad = 0.6,
|
||||||
|
AxialLoadSp = 0.7,
|
||||||
|
AxialLoadLimitMax = 0.8,
|
||||||
|
RotorTorque = 0.9,
|
||||||
|
RotorTorqueSp = 0.11,
|
||||||
|
RotorTorqueLimitMax = 0.12,
|
||||||
|
RotorSpeed = 0.14,
|
||||||
|
Flow = 0.17,
|
||||||
|
IdFeedRegulator = LimitingParameterDto.AxialLoad,
|
||||||
|
EnabledSubsystems = 15,
|
||||||
|
HasOscillation = false,
|
||||||
|
},
|
||||||
|
new(){
|
||||||
|
Id = 1,
|
||||||
|
IdTelemetry = 1,
|
||||||
|
IdCategory = WellOperationCategory.IdRotor,
|
||||||
|
DateStart = dateStart.AddHours(3.25),
|
||||||
|
DateEnd = dateStart.AddHours(4.25),
|
||||||
|
DepthStart = 20,
|
||||||
|
DepthEnd = 190,
|
||||||
|
Speed = 0.21,
|
||||||
|
BlockSpeedSp = 0.22,
|
||||||
|
Pressure = 0.23,
|
||||||
|
PressureIdle = 0.24,
|
||||||
|
PressureSp = 0.25,
|
||||||
|
AxialLoad = 0.26,
|
||||||
|
AxialLoadSp = 0.27,
|
||||||
|
AxialLoadLimitMax = 0.28,
|
||||||
|
RotorTorque = 0.29,
|
||||||
|
RotorTorqueSp = 0.211,
|
||||||
|
RotorTorqueLimitMax = 0.212,
|
||||||
|
RotorSpeed = 0.214,
|
||||||
|
Flow = 0.217,
|
||||||
|
IdFeedRegulator = LimitingParameterDto.AxialLoad,
|
||||||
|
EnabledSubsystems = 15,
|
||||||
|
HasOscillation = false,
|
||||||
|
},
|
||||||
|
new(){
|
||||||
|
Id = 1,
|
||||||
|
IdTelemetry = 1,
|
||||||
|
IdCategory = WellOperationCategory.IdRotor,
|
||||||
|
DateStart = dateStart.AddHours(4.25),
|
||||||
|
DateEnd = dateStart.AddHours(16),
|
||||||
|
DepthStart = 190,
|
||||||
|
DepthEnd = 290,
|
||||||
|
Speed = 0.31,
|
||||||
|
BlockSpeedSp = 0.32,
|
||||||
|
Pressure = 0.33,
|
||||||
|
PressureIdle = 0.34,
|
||||||
|
PressureSp = 0.35,
|
||||||
|
AxialLoad = 0.36,
|
||||||
|
AxialLoadSp = 0.37,
|
||||||
|
AxialLoadLimitMax = 0.38,
|
||||||
|
RotorTorque = 0.39,
|
||||||
|
RotorTorqueSp = 0.231,
|
||||||
|
RotorTorqueLimitMax = 0.232,
|
||||||
|
RotorSpeed = 0.234,
|
||||||
|
Flow = 0.237,
|
||||||
|
IdFeedRegulator = LimitingParameterDto.AxialLoad,
|
||||||
|
EnabledSubsystems = 15,
|
||||||
|
HasOscillation = false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public ProcessMapReportDataSaubStatServiceTest()
|
||||||
|
{
|
||||||
|
wellService.GetOrDefaultAsync(Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(well);
|
||||||
|
|
||||||
|
processMapPlanBaseRepository.Get(Arg.Any<ProcessMapPlanBaseRequestWithWell>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(processMapPlan);
|
||||||
|
|
||||||
|
wellOperationRepository.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(operations);
|
||||||
|
|
||||||
|
wellOperationRepository.GetSectionTypes()
|
||||||
|
.Returns(sectionTypes);
|
||||||
|
|
||||||
|
wellOperationCategoryRepository.Get(Arg.Any<bool>())
|
||||||
|
.Returns(operationCategories);
|
||||||
|
|
||||||
|
dataSaubStatRepository.GetAsync(Arg.Any<int>(), Arg.Any<DateTimeOffset>(), Arg.Any<DateTimeOffset>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(dataSaubStat);
|
||||||
|
|
||||||
|
service = new ProcessMapReportDataSaubStatService(wellService, processMapPlanBaseRepository, dataSaubStatRepository, wellOperationRepository, wellOperationCategoryRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAsync_return_data()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
DataSaubStatRequest request = new() { };
|
||||||
|
|
||||||
|
// act
|
||||||
|
var result = await service.GetAsync(well.Id, request, CancellationToken.None);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.NotEmpty(result);
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using AsbCloudApp.Data;
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using AsbCloudApp.Data;
|
|
||||||
using AsbCloudApp.Data.ProcessMaps;
|
using AsbCloudApp.Data.ProcessMaps;
|
||||||
|
using AsbCloudApp.Data.ProcessMaps.Report;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudApp.Services.ProcessMaps;
|
using AsbCloudApp.Services.ProcessMaps;
|
||||||
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
||||||
@ -14,6 +11,11 @@ using AsbCloudWebApi.SignalR.Clients;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers.ProcessMaps;
|
namespace AsbCloudWebApi.Controllers.ProcessMaps;
|
||||||
|
|
||||||
@ -23,6 +25,7 @@ namespace AsbCloudWebApi.Controllers.ProcessMaps;
|
|||||||
public class ProcessMapWellDrillingController : ProcessMapBaseController<ProcessMapPlanWellDrillingDto>
|
public class ProcessMapWellDrillingController : ProcessMapBaseController<ProcessMapPlanWellDrillingDto>
|
||||||
{
|
{
|
||||||
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingService;
|
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingService;
|
||||||
|
private readonly IProcessMapReportDataSaubStatService processMapReportDataSaubStatService;
|
||||||
private readonly IProcessMapReportWellDrillingExportService processMapReportWellDrillingExportService;
|
private readonly IProcessMapReportWellDrillingExportService processMapReportWellDrillingExportService;
|
||||||
private readonly IProcessMapPlanImportService processMapPlanImportService;
|
private readonly IProcessMapPlanImportService processMapPlanImportService;
|
||||||
|
|
||||||
@ -33,7 +36,8 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController<Process
|
|||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
IProcessMapReportWellDrillingExportService processMapReportWellDrillingExportService,
|
IProcessMapReportWellDrillingExportService processMapReportWellDrillingExportService,
|
||||||
IProcessMapPlanImportService processMapPlanImportService,
|
IProcessMapPlanImportService processMapPlanImportService,
|
||||||
IProcessMapReportWellDrillingService processMapReportWellDrillingService,
|
IProcessMapReportWellDrillingService processMapReportWellDrillingService,
|
||||||
|
IProcessMapReportDataSaubStatService processMapReportDataSaubStatService,
|
||||||
ICrudRepository<WellSectionTypeDto> wellSectionRepository,
|
ICrudRepository<WellSectionTypeDto> wellSectionRepository,
|
||||||
IHubContext<TelemetryHub, ITelemetryHubClient> telemetryHubContext,
|
IHubContext<TelemetryHub, ITelemetryHubClient> telemetryHubContext,
|
||||||
ITelemetryService telemetryService,
|
ITelemetryService telemetryService,
|
||||||
@ -42,6 +46,7 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController<Process
|
|||||||
{
|
{
|
||||||
this.processMapReportWellDrillingExportService = processMapReportWellDrillingExportService;
|
this.processMapReportWellDrillingExportService = processMapReportWellDrillingExportService;
|
||||||
this.processMapPlanImportService = processMapPlanImportService;
|
this.processMapPlanImportService = processMapPlanImportService;
|
||||||
|
this.processMapReportDataSaubStatService = processMapReportDataSaubStatService;
|
||||||
this.processMapReportWellDrillingService = processMapReportWellDrillingService;
|
this.processMapReportWellDrillingService = processMapReportWellDrillingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,13 +54,14 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController<Process
|
|||||||
/// Получение данных для отчета РТК бурение
|
/// Получение данных для отчета РТК бурение
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell">Id</param>
|
/// <param name="idWell">Id</param>
|
||||||
|
/// <param name="request">параметры запроса</param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet("report")]
|
[HttpPost("report")]
|
||||||
[ProducesResponseType(typeof(IEnumerable<ProcessMapPlanWellDrillingDto>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(IEnumerable<ProcessMapReportDataSaubStatDto>), StatusCodes.Status200OK)]
|
||||||
public async Task<IActionResult> GetReportAsync(int idWell, CancellationToken cancellationToken)
|
public async Task<IActionResult> GetReportAsync(int idWell, DataSaubStatRequest request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var report = await processMapReportWellDrillingService.GetAsync(idWell, cancellationToken);
|
var report = await processMapReportDataSaubStatService.GetAsync(idWell, request, cancellationToken);
|
||||||
|
|
||||||
return Ok(report);
|
return Ok(report);
|
||||||
}
|
}
|
||||||
@ -89,9 +95,9 @@ public class ProcessMapWellDrillingController : ProcessMapBaseController<Process
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost("import/{options}")]
|
[HttpPost("import/{options}")]
|
||||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||||
public async Task<IActionResult> ImportAsync(int idWell,
|
public async Task<IActionResult> ImportAsync(int idWell,
|
||||||
int options,
|
int options,
|
||||||
[Required] IFormFile file,
|
[Required] IFormFile file,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await AssertUserHasAccessToEditProcessMapAsync(idWell, cancellationToken);
|
await AssertUserHasAccessToEditProcessMapAsync(idWell, cancellationToken);
|
||||||
|
@ -18,8 +18,6 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
{
|
{
|
||||||
private readonly ISetpointsService setpointsService;
|
private readonly ISetpointsService setpointsService;
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
private const int ObsolescenceSecMin = 30;
|
|
||||||
private const int ObsolescenceSecMax = 6 * 60 * 60;
|
|
||||||
|
|
||||||
public SetpointsController(ISetpointsService setpointsService, IWellService wellService)
|
public SetpointsController(ISetpointsService setpointsService, IWellService wellService)
|
||||||
{
|
{
|
||||||
@ -68,11 +66,6 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
setpoints.IdWell = idWell;
|
setpoints.IdWell = idWell;
|
||||||
setpoints.IdState = 1;
|
setpoints.IdState = 1;
|
||||||
|
|
||||||
if (setpoints is null
|
|
||||||
|| setpoints.ObsolescenceSec > ObsolescenceSecMax
|
|
||||||
|| setpoints.ObsolescenceSec < ObsolescenceSecMin)
|
|
||||||
return this.ValidationBadRequest(nameof(setpoints.ObsolescenceSec), "Wrong ObsolescenceSec");
|
|
||||||
|
|
||||||
if (!setpoints.Setpoints.Any())
|
if (!setpoints.Setpoints.Any())
|
||||||
return this.ValidationBadRequest(nameof(setpoints.Setpoints), "Wrong setpoints count");
|
return this.ValidationBadRequest(nameof(setpoints.Setpoints), "Wrong setpoints count");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user