forked from ddrilling/AsbCloudServer
Новые расчеты наработки подсистем
This commit is contained in:
parent
f300974b1d
commit
5fb9375955
@ -1,30 +1,24 @@
|
|||||||
using System.Collections.Generic;
|
namespace AsbCloudApp.Data.Subsystems;
|
||||||
namespace AsbCloudApp.Data.Subsystems
|
|
||||||
|
/// <summary>
|
||||||
|
/// Статистика наработки подсистем по активным скважинам
|
||||||
|
/// </summary>
|
||||||
|
public class SubsystemActiveWellStatDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Статистика наработки подсистем по активным скважинам
|
/// Активная скважина
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubsystemActiveWellStatDto
|
public WellInfoDto Well { get; set; } = null!;
|
||||||
{
|
/// <summary>
|
||||||
/// <summary>
|
/// Наработки подсистемы АПД
|
||||||
/// Активная скважина
|
/// </summary>
|
||||||
/// </summary>
|
public SubsystemStatDto? SubsystemAPD { get; set; }
|
||||||
public WellInfoDto Well { get; set; } = null!;
|
/// <summary>
|
||||||
/// <summary>
|
/// Наработки подсистемы СПИН
|
||||||
/// Наработки подсистемы АКБ
|
/// </summary>
|
||||||
/// </summary>
|
public SubsystemStatDto? SubsystemSpinMaster { get; set; }
|
||||||
public SubsystemStatDto? SubsystemAKB { get; set; }
|
/// <summary>
|
||||||
/// <summary>
|
/// Наработки подсистемы ТОРК
|
||||||
/// Наработки подсистемы МСЕ
|
/// </summary>
|
||||||
/// </summary>
|
public SubsystemStatDto? SubsystemTorqueMaster { get; set; }
|
||||||
public SubsystemStatDto? SubsystemMSE { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Наработки подсистемы СПИН
|
|
||||||
/// </summary>
|
|
||||||
public SubsystemStatDto? SubsystemSpinMaster { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Наработки подсистемы ТОРК
|
|
||||||
/// </summary>
|
|
||||||
public SubsystemStatDto? SubsystemTorqueMaster { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
namespace AsbCloudApp.Data.Subsystems
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Модель информации о работе подсистемы
|
|
||||||
/// </summary>
|
|
||||||
public class SubsystemOperationTimeDto:IId
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Идентификатор
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// идентификатор подсистемы
|
|
||||||
/// </summary>
|
|
||||||
public int IdSubsystem { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Название подсистемы
|
|
||||||
/// </summary>
|
|
||||||
public string SubsystemName { get; set; } = null!;
|
|
||||||
/// <summary>
|
|
||||||
/// дата/время включения подсистемы
|
|
||||||
/// </summary>
|
|
||||||
public DateTime DateStart { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// дата/время выключения подсистемы
|
|
||||||
/// </summary>
|
|
||||||
public DateTime DateEnd { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// глубина забоя на момент включения подсистемы
|
|
||||||
/// </summary>
|
|
||||||
public double DepthStart { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// глубина забоя на момент выключения подсистемы
|
|
||||||
/// </summary>
|
|
||||||
public double DepthEnd { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ namespace AsbCloudApp.Requests
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// класс с фильтрами для запроса
|
/// класс с фильтрами для запроса
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubsystemOperationTimeRequest: RequestBase, IValidatableObject
|
public class SubsystemTimeRequest: RequestBase, IValidatableObject
|
||||||
{
|
{
|
||||||
private static readonly DateTime validationMinDate = new DateTime(2020,01,01,0,0,0,DateTimeKind.Utc);
|
private static readonly DateTime validationMinDate = new DateTime(2020,01,01,0,0,0,DateTimeKind.Utc);
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ namespace AsbCloudApp.Requests
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Больше или равно дате
|
/// Больше или равно дате
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? GtDate { get; set; }//TODO: its Ge*
|
public DateTime? GeDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Меньше или равно дате
|
/// Меньше или равно дате
|
||||||
@ -43,41 +43,20 @@ namespace AsbCloudApp.Requests
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double? LtDepth { get; set; }
|
public double? LtDepth { get; set; }
|
||||||
|
|
||||||
//TODO: Replace modes by DateTimeOffset LeDateStart, LeDateEnd
|
|
||||||
/// <summary>
|
|
||||||
/// информация попадает в выборку, если интервал выборки частично или полностью пересекается с запрашиваемым интервалом
|
|
||||||
/// </summary>
|
|
||||||
public const int SelectModeOuter = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// информация попадает в выборку, если интервал выборки строго полностью пересекается с запрашиваемым интервалом.
|
|
||||||
/// </summary>
|
|
||||||
public const int SelectModeInner = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// аналогично outer, но интервалы в частично пересекающиеся укорачиваются по границам интервала выборки.
|
|
||||||
/// </summary>
|
|
||||||
public const int SelectModeTrim = 2;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Режим выборки элементов
|
|
||||||
/// </summary>
|
|
||||||
public int SelectMode { get; set; } = SelectModeOuter;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||||
{
|
{
|
||||||
if (GtDate.HasValue && GtDate < validationMinDate)
|
if (GeDate.HasValue && GeDate < validationMinDate)
|
||||||
yield return new ValidationResult(
|
yield return new ValidationResult(
|
||||||
$"Должно быть больше {validationMinDate:O})",
|
$"Должно быть больше {validationMinDate:O})",
|
||||||
new[] { nameof(GtDate) });
|
new[] { nameof(GeDate) });
|
||||||
|
|
||||||
if (LtDate.HasValue && GtDate.HasValue)
|
if (LtDate.HasValue && GeDate.HasValue)
|
||||||
{
|
{
|
||||||
if (LtDate < GtDate)
|
if (LtDate < GeDate)
|
||||||
yield return new ValidationResult(
|
yield return new ValidationResult(
|
||||||
$"{nameof(LtDate)} должно быть больше {nameof(GtDate)}. ({LtDate:O} < {GtDate:O})",
|
$"{nameof(LtDate)} должно быть больше {nameof(GeDate)}. ({LtDate:O} < {GeDate:O})",
|
||||||
new[] { nameof(LtDate), nameof(GtDate) });
|
new[] { nameof(LtDate), nameof(GeDate) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LtDepth.HasValue && GtDepth.HasValue)
|
if (LtDepth.HasValue && GtDepth.HasValue)
|
40
AsbCloudApp/Services/ISubsystemService.cs
Normal file
40
AsbCloudApp/Services/ISubsystemService.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using AsbCloudApp.Data.Subsystems;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение инфо о наработке подсистем
|
||||||
|
/// </summary>
|
||||||
|
public interface ISubsystemService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Статистика о наработке подсистем
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<SubsystemStatDto>> GetStatAsync(SubsystemTimeRequest request, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение статистики по наработке подсистем по активным скважинам
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idCompany"></param>
|
||||||
|
/// <param name="gtDate"></param>
|
||||||
|
/// <param name="ltDate"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(int idCompany, DateTime? gtDate, DateTime? ltDate, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение статистики по наработке подсистем по активным скважинам
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wellIds"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(IEnumerable<int> wellIds, CancellationToken token);
|
||||||
|
}
|
@ -1,68 +0,0 @@
|
|||||||
using AsbCloudApp.Data;
|
|
||||||
using AsbCloudApp.Data.Subsystems;
|
|
||||||
using AsbCloudApp.Requests;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AsbCloudApp.Services.Subsystems
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Получение инфо о наработке подсистем
|
|
||||||
/// </summary>
|
|
||||||
public interface ISubsystemOperationTimeService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Статистика о наработке подсистем
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<IEnumerable<SubsystemStatDto>> GetStatAsync(SubsystemOperationTimeRequest request, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Удаление наработки по подсистемам.
|
|
||||||
/// Если удаляется конец, то фоновый сервис подсчета наработки восстановит эти данные.
|
|
||||||
/// Может потребоваться для запуска повторного расчета по новому алгоритму.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<int> DeleteAsync(SubsystemOperationTimeRequest request, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Интервалы работы подсистем
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<IEnumerable<SubsystemOperationTimeDto>> GetOperationTimeAsync(SubsystemOperationTimeRequest request, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Временной диапазон за который есть статистика работы подсистем
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<DatesRangeDto?> GetDateRangeOperationTimeAsync(SubsystemOperationTimeRequest request, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение статистики по наработке подсистем по активным скважинам
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="idCompany"></param>
|
|
||||||
/// <param name="gtDate"></param>
|
|
||||||
/// <param name="ltDate"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(int idCompany, DateTime? gtDate, DateTime? ltDate, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение статистики по наработке подсистем по активным скважинам
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="wellIds"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(IEnumerable<int> wellIds, CancellationToken token);
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,7 +24,7 @@ namespace AsbCloudDb.Model.DefaultData
|
|||||||
{ typeof(WellType), new EntityFillerWellType()},
|
{ typeof(WellType), new EntityFillerWellType()},
|
||||||
{ typeof(MeasureCategory), new EntityFillerMeasureCategory()},
|
{ typeof(MeasureCategory), new EntityFillerMeasureCategory()},
|
||||||
{ typeof(CompanyType), new EntityFillerCompanyType()},
|
{ typeof(CompanyType), new EntityFillerCompanyType()},
|
||||||
{ typeof(Subsystems.Subsystem), new EntityFillerSubsystem() },
|
{ typeof(Subsystem), new EntityFillerSubsystem() },
|
||||||
{ typeof(NotificationCategory), new EntityNotificationCategory()},
|
{ typeof(NotificationCategory), new EntityNotificationCategory()},
|
||||||
};
|
};
|
||||||
return fillers;
|
return fillers;
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
using AsbCloudDb.Model.Subsystems;
|
|
||||||
using AsbCloudInfrastructure.Services.Subsystems;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Data.Common;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Background.PeriodicWorks;
|
|
||||||
|
|
||||||
public class WorkSubsystemAbfOperationTimeCalc : WorkSubsystemOperationTimeCalcAbstract
|
|
||||||
{
|
|
||||||
public WorkSubsystemAbfOperationTimeCalc()
|
|
||||||
: base("Subsystem automated bit feeding operation time calc")
|
|
||||||
{
|
|
||||||
Timeout = TimeSpan.FromMinutes(30);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task<IEnumerable<SubsystemOperationTime>> OperationTimeAsync(int idTelemetry, DateTimeOffset geDate, IAsbCloudDbContext db, CancellationToken token)
|
|
||||||
{
|
|
||||||
static bool isSubsytemAkbRotor(short? mode) => mode == 1;
|
|
||||||
|
|
||||||
static bool isSubsytemAkbSlide(short? mode) => mode == 3;
|
|
||||||
|
|
||||||
static bool IsSubsystemMse(short? state) => (state & 1) > 0;
|
|
||||||
|
|
||||||
var query =
|
|
||||||
$"select tt.date, tt.mode, tt.well_depth, tt.mse_state " +
|
|
||||||
$"from ( " +
|
|
||||||
$" select " +
|
|
||||||
$" date, " +
|
|
||||||
$" mode, " +
|
|
||||||
$" mse_state, " +
|
|
||||||
$" well_depth, " +
|
|
||||||
$" lag(mode,1) over (order by date) as mode_lag, " +
|
|
||||||
$" lead(mode,1) over (order by date) as mode_lead " +
|
|
||||||
$" from t_telemetry_data_saub " +
|
|
||||||
$" where id_telemetry = {idTelemetry} and well_depth is not null and well_depth > 0 " +
|
|
||||||
$" order by date ) as tt " +
|
|
||||||
$"where (tt.mode_lag is null or (tt.mode != tt.mode_lag and tt.mode_lead != tt.mode_lag)) and tt.date >= '{geDate:u}' " +
|
|
||||||
$"order by tt.date;";
|
|
||||||
|
|
||||||
using var result = await ExecuteReaderAsync(db, query, token);
|
|
||||||
|
|
||||||
var subsystemsOperationTimes = new List<SubsystemOperationTime>();
|
|
||||||
var detectorRotor = new SubsystemDetector(idTelemetry, idSubsystemAPDRotor, isSubsytemAkbRotor, IsValid);
|
|
||||||
var detectorSlide = new SubsystemDetector(idTelemetry, idSubsystemAPDSlide, isSubsytemAkbSlide, IsValid);
|
|
||||||
var detectorMse = new SubsystemDetector(idTelemetry, idSubsystemMse, IsSubsystemMse, IsValid);
|
|
||||||
|
|
||||||
while (result.Read())
|
|
||||||
{
|
|
||||||
var mode = result.GetFieldValue<short?>(1);
|
|
||||||
var state = result.GetFieldValue<short?>(3);
|
|
||||||
|
|
||||||
var isAkbRotorEnable = isSubsytemAkbRotor(mode);
|
|
||||||
var isAkbSlideEnable = isSubsytemAkbSlide(mode);
|
|
||||||
var isMseEnable = IsSubsystemMse(state);
|
|
||||||
var date = result.GetFieldValue<DateTimeOffset>(0);
|
|
||||||
var depth = result.GetFieldValue<float>(2);
|
|
||||||
|
|
||||||
if (detectorRotor.TryDetect(mode, date, depth, out var detectedRotor))
|
|
||||||
subsystemsOperationTimes.Add(detectedRotor!);
|
|
||||||
|
|
||||||
if (detectorSlide.TryDetect(mode, date, depth, out var detectedSlide))
|
|
||||||
subsystemsOperationTimes.Add(detectedSlide!);
|
|
||||||
|
|
||||||
if (detectorMse.TryDetect(mode, date, depth, out var detectedMse))
|
|
||||||
subsystemsOperationTimes.Add(detectedMse!);
|
|
||||||
}
|
|
||||||
|
|
||||||
return subsystemsOperationTimes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<DbDataReader> ExecuteReaderAsync(IAsbCloudDbContext db, string query, CancellationToken token)
|
|
||||||
{
|
|
||||||
var connection = db.Database.GetDbConnection();
|
|
||||||
if (
|
|
||||||
connection?.State is null ||
|
|
||||||
connection.State == ConnectionState.Broken ||
|
|
||||||
connection.State == ConnectionState.Closed)
|
|
||||||
{
|
|
||||||
await db.Database.OpenConnectionAsync(token);
|
|
||||||
connection = db.Database.GetDbConnection();
|
|
||||||
}
|
|
||||||
using var command = connection.CreateCommand();
|
|
||||||
command.CommandText = query;
|
|
||||||
|
|
||||||
var result = await command.ExecuteReaderAsync(token);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsValid(SubsystemOperationTime item)
|
|
||||||
{
|
|
||||||
var validateCode = GetValidateErrorCode(item);
|
|
||||||
if (validateCode != 0)
|
|
||||||
{
|
|
||||||
var str = System.Text.Json.JsonSerializer.Serialize(item);
|
|
||||||
Trace.TraceWarning($"Wrong({validateCode}) SubsystemOperationTime: {str}");
|
|
||||||
}
|
|
||||||
return validateCode == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetValidateErrorCode(SubsystemOperationTime item)
|
|
||||||
{
|
|
||||||
if (item.DateStart > item.DateEnd)
|
|
||||||
return -1;
|
|
||||||
if ((item.DateEnd - item.DateStart).TotalHours > 48)
|
|
||||||
return -2;
|
|
||||||
if (item.DepthEnd < item.DepthStart)
|
|
||||||
return -3;
|
|
||||||
if (item.DepthEnd - item.DepthStart > 2000d)
|
|
||||||
return -4;
|
|
||||||
if (item.DepthEnd < 0d)
|
|
||||||
return -5;
|
|
||||||
if (item.DepthStart < 0d)
|
|
||||||
return -6;
|
|
||||||
if (item.DepthEnd > 24_0000d)
|
|
||||||
return -7;
|
|
||||||
if (item.DepthStart > 24_0000d)
|
|
||||||
return -8;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
using AsbCloudApp.Data.SAUB;
|
|
||||||
using AsbCloudApp.Repositories;
|
|
||||||
using AsbCloudDb.Model;
|
|
||||||
using AsbCloudDb.Model.Subsystems;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Background.PeriodicWorks;
|
|
||||||
|
|
||||||
public abstract class WorkSubsystemOperationTimeCalcAbstract : Work
|
|
||||||
{
|
|
||||||
protected const int idSubsystemTorqueMaster = 65537;
|
|
||||||
protected const int idSubsystemSpinMaster = 65536;
|
|
||||||
protected const int idSubsystemAPDRotor = 11;
|
|
||||||
protected const int idSubsystemAPDSlide = 12;
|
|
||||||
protected const int idSubsystemMse = 2;
|
|
||||||
|
|
||||||
private static TimeSpan obsoleteTime = TimeSpan.FromDays(365 * 100);
|
|
||||||
|
|
||||||
public WorkSubsystemOperationTimeCalcAbstract(string workId)
|
|
||||||
: base(workId)
|
|
||||||
{
|
|
||||||
Timeout = TimeSpan.FromMinutes(30);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task Action(string id, IServiceProvider services, Action<string, double?> onProgressCallback, CancellationToken token)
|
|
||||||
{
|
|
||||||
var db = services.GetRequiredService<IAsbCloudDbContext>();
|
|
||||||
db.Database.SetCommandTimeout(TimeSpan.FromMinutes(5));
|
|
||||||
|
|
||||||
var telemetryLastDetectedDates = await GetTelemetryLastDetectedDates(services, db, token);
|
|
||||||
|
|
||||||
var count = telemetryLastDetectedDates.Count();
|
|
||||||
var i = 0d;
|
|
||||||
|
|
||||||
foreach (var item in telemetryLastDetectedDates)
|
|
||||||
{
|
|
||||||
onProgressCallback($"Start handling telemetry: {item.IdTelemetry} from {item.DateDetectedLast}", i++ / count);
|
|
||||||
var newOperationsSaub = await OperationTimeAsync(item.IdTelemetry, item.DateDetectedLast, db, token);
|
|
||||||
if (newOperationsSaub.Any())
|
|
||||||
{
|
|
||||||
db.SubsystemOperationTimes.AddRange(newOperationsSaub);
|
|
||||||
await db.SaveChangesAsync(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
obsoleteTime = TimeSpan.FromDays(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Task<IEnumerable<SubsystemOperationTime>> OperationTimeAsync(int idTelemetry, DateTimeOffset geDate, IAsbCloudDbContext db, CancellationToken token);
|
|
||||||
|
|
||||||
private static async Task<IEnumerable<TelemetryDateLast>> GetTelemetryLastDetectedDates(IServiceProvider services, IAsbCloudDbContext db, CancellationToken token)
|
|
||||||
{
|
|
||||||
var telemetryDataCache = services.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
|
||||||
|
|
||||||
var updatingTelemetries = telemetryDataCache.GetStat()
|
|
||||||
.Where(tstat => (DateTimeOffset.Now - tstat.DateLast) < obsoleteTime);
|
|
||||||
|
|
||||||
var telemetryIds = updatingTelemetries
|
|
||||||
.Select(t => t.IdTelemetry)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
IEnumerable<TelemetryDateLast> lastDetectedDates = await GetLastSubsystemOperationTimeAsync(db, token);
|
|
||||||
lastDetectedDates = lastDetectedDates
|
|
||||||
.Where(s => telemetryIds.Contains(s.IdTelemetry));
|
|
||||||
|
|
||||||
var result = updatingTelemetries.Select(tstat => new TelemetryDateLast
|
|
||||||
{
|
|
||||||
IdTelemetry = tstat.IdTelemetry,
|
|
||||||
DateDetectedLast = lastDetectedDates.FirstOrDefault(ldd => ldd.IdTelemetry == tstat.IdTelemetry)?.DateDetectedLast
|
|
||||||
?? DateTimeOffset.UnixEpoch,
|
|
||||||
DateTelemetryLast = tstat.DateLast
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<IEnumerable<TelemetryDateLast>> GetLastSubsystemOperationTimeAsync(IAsbCloudDbContext db, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await db.SubsystemOperationTimes
|
|
||||||
.GroupBy(o => o.IdTelemetry)
|
|
||||||
.Select(g => new TelemetryDateLast
|
|
||||||
{
|
|
||||||
IdTelemetry = g.Key,
|
|
||||||
DateDetectedLast = g.Max(o => o.DateEnd)
|
|
||||||
})
|
|
||||||
.ToArrayAsync(token);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class TelemetryDateLast
|
|
||||||
{
|
|
||||||
public int IdTelemetry { get; set; }
|
|
||||||
public DateTimeOffset DateDetectedLast { get; set; }
|
|
||||||
public DateTimeOffset DateTelemetryLast { get; internal set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,186 +0,0 @@
|
|||||||
using AsbCloudDb.Model;
|
|
||||||
using AsbCloudDb.Model.Subsystems;
|
|
||||||
using AsbCloudInfrastructure.Background;
|
|
||||||
using AsbCloudInfrastructure.Services.Subsystems;
|
|
||||||
using AsbCloudInfrastructure.Services.Subsystems.Utils;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Data.Common;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Background.PeriodicWorks;
|
|
||||||
|
|
||||||
public class WorkSubsystemOscillationOperationTimeCalc : WorkSubsystemOperationTimeCalcAbstract
|
|
||||||
{
|
|
||||||
public WorkSubsystemOscillationOperationTimeCalc()
|
|
||||||
: base("Subsystem operation time calc")
|
|
||||||
{
|
|
||||||
Timeout = TimeSpan.FromMinutes(30);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task<IEnumerable<SubsystemOperationTime>> OperationTimeAsync(int idTelemetry, DateTimeOffset geDate, IAsbCloudDbContext db, CancellationToken token)
|
|
||||||
{
|
|
||||||
static int? GetSubsytemId(short? mode, int? state)
|
|
||||||
{
|
|
||||||
// При изменении следующего кода сообщи в Vladimir.Sobolev@nedra.digital
|
|
||||||
if (state == 7 && (mode & 2) > 0)
|
|
||||||
return idSubsystemTorqueMaster;// демпфер
|
|
||||||
|
|
||||||
if (state != 0 && state != 5 && state != 6 && state != 7)
|
|
||||||
return idSubsystemSpinMaster;// осцилляция
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var querySpin =
|
|
||||||
$"select " +
|
|
||||||
$" tspin.date, " +
|
|
||||||
$" tspin.mode, " +
|
|
||||||
$" tspin.state " +
|
|
||||||
$"from ( " +
|
|
||||||
$" select " +
|
|
||||||
$" date, " +
|
|
||||||
$" mode, " +
|
|
||||||
$" lag(mode, 1) over (order by date) as mode_lag, " +
|
|
||||||
$" lead(mode, 1) over (order by date) as mode_lead, " +
|
|
||||||
$" state, " +
|
|
||||||
$" lag(state, 1) over (order by date) as state_lag " +
|
|
||||||
$" from t_telemetry_data_spin " +
|
|
||||||
$" where id_telemetry = {idTelemetry} and date >= '{geDate:u}'" +
|
|
||||||
$" order by date ) as tspin " +
|
|
||||||
$"where mode_lag is null or state_lag is null or (mode != mode_lag and mode_lead != mode_lag) or state != state_lag " +
|
|
||||||
$"order by date;";
|
|
||||||
|
|
||||||
var rows = new List<(int? IdSubsystem, DateTimeOffset Date)>(32);
|
|
||||||
|
|
||||||
using var resultSpin = await ExecuteReaderAsync(db, querySpin, token);
|
|
||||||
int? idSubsystemLast = null;
|
|
||||||
while (resultSpin.Read())
|
|
||||||
{
|
|
||||||
var mode = resultSpin.GetFieldValue<short?>(1);
|
|
||||||
var state = resultSpin.GetFieldValue<short?>(2);
|
|
||||||
var idSubsystem = GetSubsytemId(mode, state);
|
|
||||||
if (idSubsystemLast != idSubsystem)
|
|
||||||
{
|
|
||||||
idSubsystemLast = idSubsystem;
|
|
||||||
var date = resultSpin.GetFieldValue<DateTimeOffset>(0);
|
|
||||||
rows.Add((idSubsystem, date));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await resultSpin.DisposeAsync();
|
|
||||||
|
|
||||||
if (rows.Count < 2)
|
|
||||||
return Enumerable.Empty<SubsystemOperationTime>();
|
|
||||||
|
|
||||||
var minSpinDate = rows.Min(i => i.Date);
|
|
||||||
var maxSpinDate = rows.Max(i => i.Date);
|
|
||||||
var depthInterpolation = await GetInterpolation(db, idTelemetry, minSpinDate, maxSpinDate, token);
|
|
||||||
|
|
||||||
if (depthInterpolation is null)
|
|
||||||
return Enumerable.Empty<SubsystemOperationTime>();
|
|
||||||
|
|
||||||
var subsystemsOperationTimes = new List<SubsystemOperationTime>(32);
|
|
||||||
|
|
||||||
for (int i = 1; i < rows.Count; i++)
|
|
||||||
{
|
|
||||||
var r0 = rows[i - 1];
|
|
||||||
var r1 = rows[i];
|
|
||||||
if (r0.IdSubsystem is not null && r0.IdSubsystem != r1.IdSubsystem)
|
|
||||||
{
|
|
||||||
var subsystemOperationTime = new SubsystemOperationTime()
|
|
||||||
{
|
|
||||||
IdTelemetry = idTelemetry,
|
|
||||||
IdSubsystem = r0.IdSubsystem.Value,
|
|
||||||
DateStart = r0.Date,
|
|
||||||
DateEnd = r1.Date,
|
|
||||||
DepthStart = depthInterpolation.GetDepth(r0.Date),
|
|
||||||
DepthEnd = depthInterpolation.GetDepth(r1.Date),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (IsValid(subsystemOperationTime))
|
|
||||||
subsystemsOperationTimes.Add(subsystemOperationTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return subsystemsOperationTimes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<DbDataReader> ExecuteReaderAsync(IAsbCloudDbContext db, string query, CancellationToken token)
|
|
||||||
{
|
|
||||||
var connection = db.Database.GetDbConnection();
|
|
||||||
if (
|
|
||||||
connection?.State is null ||
|
|
||||||
connection.State == ConnectionState.Broken ||
|
|
||||||
connection.State == ConnectionState.Closed)
|
|
||||||
{
|
|
||||||
await db.Database.OpenConnectionAsync(token);
|
|
||||||
connection = db.Database.GetDbConnection();
|
|
||||||
}
|
|
||||||
using var command = connection.CreateCommand();
|
|
||||||
command.CommandText = query;
|
|
||||||
|
|
||||||
var result = await command.ExecuteReaderAsync(token);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsValid(SubsystemOperationTime item)
|
|
||||||
{
|
|
||||||
var validateCode = GetValidateErrorCode(item);
|
|
||||||
if (validateCode != 0)
|
|
||||||
{
|
|
||||||
var str = System.Text.Json.JsonSerializer.Serialize(item);
|
|
||||||
Trace.TraceWarning($"Wrong({validateCode}) SubsystemOperationTime: {str}");
|
|
||||||
}
|
|
||||||
return validateCode == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetValidateErrorCode(SubsystemOperationTime item)
|
|
||||||
{
|
|
||||||
if (item.DateStart > item.DateEnd)
|
|
||||||
return -1;
|
|
||||||
if ((item.DateEnd - item.DateStart).TotalHours > 48)
|
|
||||||
return -2;
|
|
||||||
if (item.DepthEnd < item.DepthStart)
|
|
||||||
return -3;
|
|
||||||
if (item.DepthEnd - item.DepthStart > 2000d)
|
|
||||||
return -4;
|
|
||||||
if (item.DepthEnd < 0d)
|
|
||||||
return -5;
|
|
||||||
if (item.DepthStart < 0d)
|
|
||||||
return -6;
|
|
||||||
if (item.DepthEnd > 24_0000d)
|
|
||||||
return -7;
|
|
||||||
if (item.DepthStart > 24_0000d)
|
|
||||||
return -8;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<DepthInterpolation?> GetInterpolation(IAsbCloudDbContext db, int idTelemetry, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
|
|
||||||
{
|
|
||||||
var dataDepthFromSaub = await db.TelemetryDataSaub
|
|
||||||
.Where(d => d.IdTelemetry == idTelemetry)
|
|
||||||
.Where(d => d.DateTime >= dateBegin)
|
|
||||||
.Where(d => d.DateTime <= dateEnd)
|
|
||||||
.Where(d => d.WellDepth > 0)
|
|
||||||
.GroupBy(d => Math.Ceiling(d.WellDepth * 10))
|
|
||||||
.Select(g => new
|
|
||||||
{
|
|
||||||
DateMin = g.Min(d => d.DateTime),
|
|
||||||
DepthMin = g.Min(d => d.WellDepth),
|
|
||||||
})
|
|
||||||
.OrderBy(i => i.DateMin)
|
|
||||||
.ToArrayAsync(token);
|
|
||||||
|
|
||||||
if (!dataDepthFromSaub.Any())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var depthInterpolation = new DepthInterpolation(dataDepthFromSaub.Select(i => (i.DateMin, i.DepthMin)));
|
|
||||||
return depthInterpolation;
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,12 +12,10 @@ using AsbCloudApp.Services;
|
|||||||
using AsbCloudApp.Services.Notifications;
|
using AsbCloudApp.Services.Notifications;
|
||||||
using AsbCloudApp.Services.ProcessMaps;
|
using AsbCloudApp.Services.ProcessMaps;
|
||||||
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
||||||
using AsbCloudApp.Services.Subsystems;
|
|
||||||
using AsbCloudApp.Services.WellOperationImport;
|
using AsbCloudApp.Services.WellOperationImport;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using AsbCloudDb.Model.Manuals;
|
using AsbCloudDb.Model.Manuals;
|
||||||
using AsbCloudDb.Model.ProcessMaps;
|
using AsbCloudDb.Model.ProcessMaps;
|
||||||
using AsbCloudDb.Model.Subsystems;
|
|
||||||
using AsbCloudDb.Model.Trajectory;
|
using AsbCloudDb.Model.Trajectory;
|
||||||
using AsbCloudInfrastructure.Background;
|
using AsbCloudInfrastructure.Background;
|
||||||
using AsbCloudInfrastructure.Repository;
|
using AsbCloudInfrastructure.Repository;
|
||||||
@ -209,7 +207,7 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddTransient<IWellOperationRepository, WellOperationRepository>();
|
services.AddTransient<IWellOperationRepository, WellOperationRepository>();
|
||||||
services.AddTransient<IDailyReportService, DailyReportService>();
|
services.AddTransient<IDailyReportService, DailyReportService>();
|
||||||
services.AddTransient<IDetectedOperationService, DetectedOperationService>();
|
services.AddTransient<IDetectedOperationService, DetectedOperationService>();
|
||||||
services.AddTransient<ISubsystemOperationTimeService, SubsystemOperationTimeService>();
|
services.AddTransient<ISubsystemService, SubsystemService>();
|
||||||
services.AddTransient<IScheduleRepository, ScheduleRepository>();
|
services.AddTransient<IScheduleRepository, ScheduleRepository>();
|
||||||
services.AddTransient<IRepositoryWellRelated<OperationValueDto>, CrudWellRelatedRepositoryBase<OperationValueDto, OperationValue>>();
|
services.AddTransient<IRepositoryWellRelated<OperationValueDto>, CrudWellRelatedRepositoryBase<OperationValueDto, OperationValue>>();
|
||||||
services.AddTransient<IUserSettingsRepository, UserSettingsRepository>();
|
services.AddTransient<IUserSettingsRepository, UserSettingsRepository>();
|
||||||
|
@ -16,7 +16,6 @@ using AsbCloudApp.Data.DailyReport.Blocks.WellOperation;
|
|||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services.DailyReport;
|
using AsbCloudApp.Services.DailyReport;
|
||||||
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
||||||
using AsbCloudApp.Services.Subsystems;
|
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
|
|
||||||
@ -29,7 +28,7 @@ public class DailyReportService : IDailyReportService
|
|||||||
private readonly IDailyReportRepository dailyReportRepository;
|
private readonly IDailyReportRepository dailyReportRepository;
|
||||||
private readonly IScheduleRepository scheduleRepository;
|
private readonly IScheduleRepository scheduleRepository;
|
||||||
private readonly IWellOperationRepository wellOperationRepository;
|
private readonly IWellOperationRepository wellOperationRepository;
|
||||||
private readonly ISubsystemOperationTimeService subsystemOperationTimeService;
|
private readonly ISubsystemService subsystemService;
|
||||||
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingService;
|
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingService;
|
||||||
private readonly IDetectedOperationService detectedOperationService;
|
private readonly IDetectedOperationService detectedOperationService;
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ public class DailyReportService : IDailyReportService
|
|||||||
IDailyReportRepository dailyReportRepository,
|
IDailyReportRepository dailyReportRepository,
|
||||||
IScheduleRepository scheduleRepository,
|
IScheduleRepository scheduleRepository,
|
||||||
IWellOperationRepository wellOperationRepository,
|
IWellOperationRepository wellOperationRepository,
|
||||||
ISubsystemOperationTimeService subsystemOperationTimeService,
|
ISubsystemService subsystemService,
|
||||||
IProcessMapReportWellDrillingService processMapReportWellDrillingService,
|
IProcessMapReportWellDrillingService processMapReportWellDrillingService,
|
||||||
IDetectedOperationService detectedOperationService)
|
IDetectedOperationService detectedOperationService)
|
||||||
{
|
{
|
||||||
@ -47,7 +46,7 @@ public class DailyReportService : IDailyReportService
|
|||||||
this.dailyReportRepository = dailyReportRepository;
|
this.dailyReportRepository = dailyReportRepository;
|
||||||
this.scheduleRepository = scheduleRepository;
|
this.scheduleRepository = scheduleRepository;
|
||||||
this.wellOperationRepository = wellOperationRepository;
|
this.wellOperationRepository = wellOperationRepository;
|
||||||
this.subsystemOperationTimeService = subsystemOperationTimeService;
|
this.subsystemService = subsystemService;
|
||||||
this.processMapReportWellDrillingService = processMapReportWellDrillingService;
|
this.processMapReportWellDrillingService = processMapReportWellDrillingService;
|
||||||
this.detectedOperationService = detectedOperationService;
|
this.detectedOperationService = detectedOperationService;
|
||||||
}
|
}
|
||||||
@ -311,24 +310,24 @@ public class DailyReportService : IDailyReportService
|
|||||||
|
|
||||||
async Task<IEnumerable<SubsystemRecordDto>> GetSubsystemsAsync()
|
async Task<IEnumerable<SubsystemRecordDto>> GetSubsystemsAsync()
|
||||||
{
|
{
|
||||||
var subsystemOperationTimesPerWell = await subsystemOperationTimeService.GetStatAsync(new SubsystemOperationTimeRequest
|
var subsystemsStatPerWell = await subsystemService.GetStatAsync(new SubsystemTimeRequest
|
||||||
{
|
{
|
||||||
IdWell = dailyReport.IdWell
|
IdWell = dailyReport.IdWell
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
|
|
||||||
var subsystemOperationTimesPerDay = await subsystemOperationTimeService.GetStatAsync(new SubsystemOperationTimeRequest
|
var subsystemsStatPerDay = await subsystemService.GetStatAsync(new SubsystemTimeRequest
|
||||||
{
|
{
|
||||||
IdWell = dailyReport.IdWell,
|
IdWell = dailyReport.IdWell,
|
||||||
GtDate = dailyReport.Date,
|
GeDate = dailyReport.Date,
|
||||||
LtDate = dailyReport.Date.AddHours(24)
|
LtDate = dailyReport.Date.AddHours(24)
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
|
|
||||||
var subsystems = subsystemOperationTimesPerWell
|
var subsystems = subsystemsStatPerWell
|
||||||
.Select(subsystemOperationTime => new SubsystemRecordDto
|
.Select(subsystemStatPerWell => new SubsystemRecordDto
|
||||||
{
|
{
|
||||||
Name = subsystemOperationTime.SubsystemName,
|
Name = subsystemStatPerWell.SubsystemName,
|
||||||
UsagePerDay = subsystemOperationTimesPerDay.FirstOrDefault(s => s.IdSubsystem == subsystemOperationTime.IdSubsystem)?.Adapt<SubsystemParametersDto>(),
|
UsagePerDay = subsystemsStatPerDay.FirstOrDefault(s => s.IdSubsystem == subsystemStatPerWell.IdSubsystem)?.Adapt<SubsystemParametersDto>(),
|
||||||
UsagePerWell = subsystemOperationTime.Adapt<SubsystemParametersDto>()
|
UsagePerWell = subsystemStatPerWell.Adapt<SubsystemParametersDto>()
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
if (dailyReport.SubsystemBlock?.Subsystems != null && dailyReport.SubsystemBlock.Subsystems.Any())
|
if (dailyReport.SubsystemBlock?.Subsystems != null && dailyReport.SubsystemBlock.Subsystems.Any())
|
||||||
|
@ -1,397 +0,0 @@
|
|||||||
using AsbCloudApp.Data;
|
|
||||||
using AsbCloudApp.Data.DetectedOperation;
|
|
||||||
using AsbCloudApp.Data.Subsystems;
|
|
||||||
using AsbCloudApp.Exceptions;
|
|
||||||
using AsbCloudApp.Requests;
|
|
||||||
using AsbCloudApp.Services;
|
|
||||||
using AsbCloudApp.Services.Subsystems;
|
|
||||||
using AsbCloudDb;
|
|
||||||
using AsbCloudDb.Model;
|
|
||||||
using AsbCloudDb.Model.Subsystems;
|
|
||||||
using Mapster;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.Subsystems;
|
|
||||||
|
|
||||||
/// Todo: Выделить репозиторий
|
|
||||||
internal class SubsystemOperationTimeService : ISubsystemOperationTimeService
|
|
||||||
{
|
|
||||||
private readonly IAsbCloudDbContext db;
|
|
||||||
private readonly IWellService wellService;
|
|
||||||
private readonly ICrudRepository<SubsystemDto> subsystemService;
|
|
||||||
private readonly IDetectedOperationService detectedOperationService;
|
|
||||||
public const int IdSubsystemAKB = 1;
|
|
||||||
public const int IdSubsystemAKBRotor = 11;
|
|
||||||
public const int IdSubsystemAKBSlide = 12;
|
|
||||||
public const int IdSubsystemMSE = 2;
|
|
||||||
public const int IdSubsystemSpin = 65536;
|
|
||||||
public const int IdSubsystemTorque = 65537;
|
|
||||||
|
|
||||||
public SubsystemOperationTimeService(IAsbCloudDbContext db, IWellService wellService, ICrudRepository<SubsystemDto> subsystemService, IDetectedOperationService detectedOperationService)
|
|
||||||
{
|
|
||||||
this.db = db;
|
|
||||||
this.wellService = wellService;
|
|
||||||
this.subsystemService = subsystemService;
|
|
||||||
this.detectedOperationService = detectedOperationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<int> DeleteAsync(SubsystemOperationTimeRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
var well = await wellService.GetOrDefaultAsync(request.IdWell, token)
|
|
||||||
?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} does not exist");
|
|
||||||
|
|
||||||
var query = BuildQuery(request, well);
|
|
||||||
db.SubsystemOperationTimes.RemoveRange(query);
|
|
||||||
return await db.SaveChangesAsync(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<SubsystemOperationTimeDto>> GetOperationTimeAsync(SubsystemOperationTimeRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
var well = await wellService.GetOrDefaultAsync(request.IdWell, token)
|
|
||||||
?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} does not exist");
|
|
||||||
|
|
||||||
var dtos = await GetOperationTimeAsync(request, well, token);
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IEnumerable<SubsystemOperationTimeDto>> GetOperationTimeAsync(SubsystemOperationTimeRequest request, WellDto well, CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = BuildQuery(request, well);
|
|
||||||
IEnumerable<SubsystemOperationTime> data = await query.ToListAsync(token);
|
|
||||||
|
|
||||||
if (request.SelectMode == SubsystemOperationTimeRequest.SelectModeInner)
|
|
||||||
{
|
|
||||||
if (request.GtDate is not null)
|
|
||||||
data = data.Where(o => o.DateStart >= request.GtDate.Value);
|
|
||||||
|
|
||||||
if (request.LtDate is not null)
|
|
||||||
data = data.Where(o => o.DateEnd <= request.LtDate.Value);
|
|
||||||
}
|
|
||||||
else if (request.SelectMode == SubsystemOperationTimeRequest.SelectModeTrim)
|
|
||||||
{
|
|
||||||
var begin = request.GtDate?.ToUtcDateTimeOffset(well.Timezone.Hours);
|
|
||||||
var end = request.LtDate?.ToUtcDateTimeOffset(well.Timezone.Hours);
|
|
||||||
data = TrimOperation(data, begin, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dtos = data.Select(o => Convert(o, well.Timezone.Hours));
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<SubsystemStatDto>> GetStatAsync(SubsystemOperationTimeRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
var well = await wellService.GetOrDefaultAsync(request.IdWell, token)
|
|
||||||
?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} does not exist");
|
|
||||||
|
|
||||||
request.SelectMode = SubsystemOperationTimeRequest.SelectModeTrim;
|
|
||||||
var subsystemsTimes = await GetOperationTimeAsync(request, well, token);
|
|
||||||
if (subsystemsTimes is null)
|
|
||||||
return Enumerable.Empty<SubsystemStatDto>();
|
|
||||||
|
|
||||||
var detectedOperationSummaryRequest = new DetectedOperationSummaryRequest()
|
|
||||||
{
|
|
||||||
IdsTelemetries = new[] {well.IdTelemetry!.Value},
|
|
||||||
IdsOperationCategories = WellOperationCategory.MechanicalDrillingSubIds,
|
|
||||||
|
|
||||||
GeDateStart = request.GtDate,
|
|
||||||
LeDateStart = request.LtDate,
|
|
||||||
|
|
||||||
GeDepthStart = request.GtDepth,
|
|
||||||
LeDepthStart = request.LtDepth,
|
|
||||||
};
|
|
||||||
var operationsSummaries = await detectedOperationService.GetOperationSummaryAsync(detectedOperationSummaryRequest, token);
|
|
||||||
if(!operationsSummaries.Any())
|
|
||||||
return Enumerable.Empty<SubsystemStatDto>();
|
|
||||||
|
|
||||||
var statList = CalcStat(subsystemsTimes, operationsSummaries);
|
|
||||||
return statList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<SubsystemOperationTime> TrimOperation(IEnumerable<SubsystemOperationTime> data, DateTimeOffset? gtDate, DateTimeOffset? ltDate)
|
|
||||||
{
|
|
||||||
if (!ltDate.HasValue && !gtDate.HasValue)
|
|
||||||
return data.Select(d => d.Adapt<SubsystemOperationTime>());
|
|
||||||
|
|
||||||
var items = data.Select((item) =>
|
|
||||||
{
|
|
||||||
var operationTime = item.Adapt<SubsystemOperationTime>();
|
|
||||||
if (!(item.DepthStart.HasValue && item.DepthEnd.HasValue))
|
|
||||||
return operationTime;
|
|
||||||
|
|
||||||
var dateDiff = (item.DateEnd - item.DateStart).TotalSeconds;
|
|
||||||
var depthDiff = item.DepthEnd.Value - item.DepthStart.Value;
|
|
||||||
var a = depthDiff / dateDiff;
|
|
||||||
var b = item.DepthStart.Value;
|
|
||||||
|
|
||||||
if (gtDate.HasValue && item.DateStart < gtDate.Value)
|
|
||||||
{
|
|
||||||
operationTime.DateStart = gtDate.Value;
|
|
||||||
var x = (gtDate.Value - item.DateStart).TotalSeconds;
|
|
||||||
operationTime.DepthStart = (float)(a * x + b);
|
|
||||||
}
|
|
||||||
if (ltDate.HasValue && item.DateEnd > ltDate.Value)
|
|
||||||
{
|
|
||||||
operationTime.DateEnd = ltDate.Value;
|
|
||||||
var x = (ltDate.Value - item.DateStart).TotalSeconds;
|
|
||||||
operationTime.DepthEnd = (float)(a * x + b);
|
|
||||||
}
|
|
||||||
return operationTime;
|
|
||||||
});
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<SubsystemStatDto> CalcStat(
|
|
||||||
IEnumerable<SubsystemOperationTimeDto> subsystemsTimes,
|
|
||||||
IEnumerable<OperationsSummaryDto> operationsSummaries)
|
|
||||||
{
|
|
||||||
var groupedSubsystemsTimes = subsystemsTimes
|
|
||||||
.OrderBy(o => o.Id)
|
|
||||||
.GroupBy(o => o.IdSubsystem);
|
|
||||||
|
|
||||||
var result = groupedSubsystemsTimes.Select(g =>
|
|
||||||
{
|
|
||||||
var periodGroup = g.Sum(o => (o.DateEnd - o.DateStart).TotalHours);
|
|
||||||
var periodGroupDepth = g.Sum(o => o.DepthEnd - o.DepthStart);
|
|
||||||
var (sumOprationsDepth, sumOprationsDurationHours) = AggregateOperationsSummaries(g.Key, operationsSummaries);
|
|
||||||
var subsystemStat = new SubsystemStatDto()
|
|
||||||
{
|
|
||||||
IdSubsystem = g.Key,
|
|
||||||
SubsystemName = subsystemService.GetOrDefault(g.Key)?.Name ?? "unknown",
|
|
||||||
UsedTimeHours = periodGroup,
|
|
||||||
SumOperationDepthInterval = sumOprationsDepth,
|
|
||||||
SumOperationDurationHours = sumOprationsDurationHours,
|
|
||||||
SumDepthInterval = periodGroupDepth,
|
|
||||||
KUsage = periodGroupDepth / sumOprationsDepth,
|
|
||||||
OperationCount = g.Count(),
|
|
||||||
};
|
|
||||||
if (subsystemStat.KUsage > 1)
|
|
||||||
subsystemStat.KUsage = 1;
|
|
||||||
return subsystemStat;
|
|
||||||
});
|
|
||||||
|
|
||||||
var apdParts = result.Where(x => x.IdSubsystem == 11 || x.IdSubsystem == 12);
|
|
||||||
if (apdParts.Any())
|
|
||||||
{
|
|
||||||
var apdSum = new SubsystemStatDto()
|
|
||||||
{
|
|
||||||
IdSubsystem = IdSubsystemAKB,
|
|
||||||
SubsystemName = "АПД",
|
|
||||||
UsedTimeHours = apdParts.Sum(part => part.UsedTimeHours),
|
|
||||||
SumOperationDepthInterval = apdParts.Sum(part => part.SumOperationDepthInterval),
|
|
||||||
SumOperationDurationHours = apdParts.Sum(part => part.SumOperationDurationHours),
|
|
||||||
SumDepthInterval = apdParts.Sum(part => part.SumDepthInterval),
|
|
||||||
OperationCount = apdParts.Sum(part => part.OperationCount),
|
|
||||||
};
|
|
||||||
|
|
||||||
operationsSummaries = operationsSummaries.Where(o => o.EnabledSubsystems == 1);
|
|
||||||
|
|
||||||
var (_, sumOprationsDurationHours) = AggregateOperationsSummaries(IdSubsystemAKBRotor, operationsSummaries);
|
|
||||||
apdSum.KUsage = sumOprationsDurationHours / apdSum.SumOperationDurationHours;
|
|
||||||
if (apdSum.KUsage > 1)
|
|
||||||
apdSum.KUsage = 1;
|
|
||||||
result = result.Append(apdSum).OrderBy(m => m.IdSubsystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static (double SumDepth, double SumDurationHours) AggregateOperationsSummaries(int idSubsystem, IEnumerable<OperationsSummaryDto> operationsSummaries)
|
|
||||||
=> idSubsystem switch
|
|
||||||
{
|
|
||||||
IdSubsystemAKBRotor or IdSubsystemTorque => CalcOperationSummariesByCategories(operationsSummaries, WellOperationCategory.IdRotor),
|
|
||||||
IdSubsystemAKBSlide or IdSubsystemSpin => CalcOperationSummariesByCategories(operationsSummaries, WellOperationCategory.IdSlide),
|
|
||||||
IdSubsystemAKB or IdSubsystemMSE => CalcOperationSummariesByCategories(operationsSummaries, WellOperationCategory.IdRotor, WellOperationCategory.IdSlide),
|
|
||||||
_ => throw new ArgumentException($"idSubsystem: {idSubsystem} does not supported in this method", nameof(idSubsystem)),
|
|
||||||
};
|
|
||||||
|
|
||||||
private static (double SumDepth, double SumDurationHours) CalcOperationSummariesByCategories(
|
|
||||||
IEnumerable<OperationsSummaryDto> operationsSummaries,
|
|
||||||
params int[] idsOperationCategories)
|
|
||||||
{
|
|
||||||
var filtered = operationsSummaries.Where(sum => idsOperationCategories.Contains(sum.IdCategory));
|
|
||||||
var sumDepth = filtered.Sum(summ => summ.SumDepthIntervals);
|
|
||||||
var sumDurationHours = filtered.Sum(summ => summ.SumDurationHours);
|
|
||||||
return (sumDepth, sumDurationHours);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(int idCompany, DateTime? gtDate, DateTime? ltDate, CancellationToken token)
|
|
||||||
{
|
|
||||||
var activeWells = await wellService.GetAsync(new() { IdCompany = idCompany, IdState = 1 }, token);
|
|
||||||
var result = await GetStatAsync(activeWells, gtDate, ltDate, token);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(IEnumerable<int> wellIds, CancellationToken token)
|
|
||||||
{
|
|
||||||
var activeWells = await wellService.GetAsync(new() { Ids = wellIds, IdState = 1 }, token);
|
|
||||||
var result = await GetStatAsync(activeWells, null, null, token);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatAsync(IEnumerable<WellDto> wells, DateTime? gtDate, DateTime? ltDate, CancellationToken token)
|
|
||||||
{
|
|
||||||
if (!wells.Any())
|
|
||||||
return Enumerable.Empty<SubsystemActiveWellStatDto>();
|
|
||||||
|
|
||||||
var hoursOffset = wells
|
|
||||||
.FirstOrDefault(well => well.Timezone is not null)
|
|
||||||
?.Timezone.Hours
|
|
||||||
?? 5d;
|
|
||||||
|
|
||||||
var beginUTC = gtDate.HasValue
|
|
||||||
? gtDate.Value.ToUtcDateTimeOffset(hoursOffset)
|
|
||||||
: db.SubsystemOperationTimes.Min(s => s.DateStart)
|
|
||||||
.DateTime
|
|
||||||
.ToUtcDateTimeOffset(hoursOffset);
|
|
||||||
|
|
||||||
var endUTC = ltDate.HasValue
|
|
||||||
? ltDate.Value.ToUtcDateTimeOffset(hoursOffset)
|
|
||||||
: db.SubsystemOperationTimes.Max(s => s.DateEnd)
|
|
||||||
.DateTime
|
|
||||||
.ToUtcDateTimeOffset(hoursOffset);
|
|
||||||
|
|
||||||
IEnumerable<int> idsTelemetries = wells
|
|
||||||
.Where(w => w.IdTelemetry is not null)
|
|
||||||
.Select(w => w.IdTelemetry!.Value)
|
|
||||||
.Distinct();
|
|
||||||
|
|
||||||
var query = db.SubsystemOperationTimes
|
|
||||||
.Where(o => idsTelemetries.Contains(o.IdTelemetry) &&
|
|
||||||
o.DateStart >= beginUTC &&
|
|
||||||
o.DateEnd <= endUTC)
|
|
||||||
.AsNoTracking();
|
|
||||||
|
|
||||||
var subsystemsOperationTime = await query.ToArrayAsync(token);
|
|
||||||
|
|
||||||
var operationSummaries = await detectedOperationService
|
|
||||||
.GetOperationSummaryAsync(new ()
|
|
||||||
{
|
|
||||||
IdsTelemetries = idsTelemetries,
|
|
||||||
IdsOperationCategories = WellOperationCategory.MechanicalDrillingSubIds,
|
|
||||||
GeDateStart = beginUTC,
|
|
||||||
LeDateEnd = endUTC,
|
|
||||||
}, token);
|
|
||||||
|
|
||||||
var result = wells
|
|
||||||
.Select(well => {
|
|
||||||
var dtos = subsystemsOperationTime
|
|
||||||
.Where(s => s.IdTelemetry == well.IdTelemetry)
|
|
||||||
.Select(s => Convert(s, well.Timezone.Hours));
|
|
||||||
|
|
||||||
var wellStat = new SubsystemActiveWellStatDto{ Well = well };
|
|
||||||
|
|
||||||
var telemetryOperationSummaries = operationSummaries.Where(summ => summ.IdTelemetry == well.IdTelemetry);
|
|
||||||
if (telemetryOperationSummaries.Any())
|
|
||||||
{
|
|
||||||
var subsystemStat = CalcStat(dtos, telemetryOperationSummaries);
|
|
||||||
if (subsystemStat.Any())
|
|
||||||
{
|
|
||||||
wellStat.SubsystemAKB = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemAKB);
|
|
||||||
wellStat.SubsystemMSE = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemMSE);
|
|
||||||
wellStat.SubsystemSpinMaster = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemSpin);
|
|
||||||
wellStat.SubsystemTorqueMaster = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemTorque);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wellStat;
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<DatesRangeDto?> GetDateRangeOperationTimeAsync(SubsystemOperationTimeRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
var well = await wellService.GetOrDefaultAsync(request.IdWell, token)
|
|
||||||
?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} does not exist");
|
|
||||||
|
|
||||||
var query = BuildQuery(request, well);
|
|
||||||
if (query is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var result = await query
|
|
||||||
.GroupBy(o => o.IdTelemetry)
|
|
||||||
.Select(g => new DatesRangeDto
|
|
||||||
{
|
|
||||||
From = g.Min(o => o.DateStart).DateTime,
|
|
||||||
To = g.Max(o => o.DateEnd).DateTime
|
|
||||||
})
|
|
||||||
.FirstOrDefaultAsync(token);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQueryable<SubsystemOperationTime> BuildQuery(SubsystemOperationTimeRequest request, WellDto well)
|
|
||||||
{
|
|
||||||
var idTelemetry = well.IdTelemetry
|
|
||||||
?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} has no telemetry");
|
|
||||||
|
|
||||||
var query = db.SubsystemOperationTimes
|
|
||||||
.Include(o => o.Subsystem)
|
|
||||||
.Where(o => o.IdTelemetry == idTelemetry)
|
|
||||||
.AsNoTracking();
|
|
||||||
|
|
||||||
if (request.IdsSubsystems.Any())
|
|
||||||
query = query.Where(o => request.IdsSubsystems.Contains(o.IdSubsystem));
|
|
||||||
|
|
||||||
// # Dates range condition
|
|
||||||
// [GtDate LtDate]
|
|
||||||
// [DateStart DateEnd] [DateStart DateEnd]
|
|
||||||
if (request.GtDate.HasValue)
|
|
||||||
{
|
|
||||||
DateTimeOffset gtDate = request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
|
||||||
query = query.Where(o => o.DateEnd >= gtDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.LtDate.HasValue)
|
|
||||||
{
|
|
||||||
DateTimeOffset ltDate = request.LtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
|
||||||
query = query.Where(o => o.DateStart <= ltDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.GtDepth.HasValue)
|
|
||||||
query = query.Where(o => o.DepthEnd >= request.GtDepth.Value);
|
|
||||||
|
|
||||||
if (request.LtDepth.HasValue)
|
|
||||||
query = query.Where(o => o.DepthStart <= request.LtDepth.Value);
|
|
||||||
|
|
||||||
if (request?.SortFields?.Any() == true)
|
|
||||||
{
|
|
||||||
query = query.SortBy(request.SortFields);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
query = query
|
|
||||||
.OrderBy(o => o.DateStart)
|
|
||||||
.ThenBy(o => o.DepthStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request?.Skip > 0)
|
|
||||||
query = query.Skip((int)request.Skip);
|
|
||||||
|
|
||||||
if (request?.Take > 0)
|
|
||||||
query = query.Take((int)request.Take);
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SubsystemOperationTimeDto Convert(SubsystemOperationTime operationTime, double? timezoneHours = null)
|
|
||||||
{
|
|
||||||
var dto = operationTime.Adapt<SubsystemOperationTimeDto>();
|
|
||||||
var hours = timezoneHours ?? operationTime.Telemetry.TimeZone.Hours;
|
|
||||||
dto.DateStart = operationTime.DateStart.ToRemoteDateTime(hours);
|
|
||||||
dto.DateEnd = operationTime.DateEnd.ToRemoteDateTime(hours);
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
|
218
AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs
Normal file
218
AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.DetectedOperation;
|
||||||
|
using AsbCloudApp.Data.Subsystems;
|
||||||
|
using AsbCloudApp.Exceptions;
|
||||||
|
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.Subsystems;
|
||||||
|
|
||||||
|
internal class SubsystemService : ISubsystemService
|
||||||
|
{
|
||||||
|
private const int IdEnabledSubsystemSpinMaster = 128;
|
||||||
|
|
||||||
|
private const int IdSubsystemAPD = 1;
|
||||||
|
private const int IdSubsystemAPDRotor = 11;
|
||||||
|
private const int IdSubsystemAPDSlide = 12;
|
||||||
|
private const int IdSubsystemSpinMaster = 65536;
|
||||||
|
|
||||||
|
private readonly ICrudRepository<SubsystemDto> subsystemRepository;
|
||||||
|
|
||||||
|
private readonly IWellService wellService;
|
||||||
|
private readonly IDetectedOperationService detectedOperationService;
|
||||||
|
private readonly ITelemetryDataSaubService telemetryDataSaubService;
|
||||||
|
|
||||||
|
public SubsystemService(ICrudRepository<SubsystemDto> subsystemRepository,
|
||||||
|
IWellService wellService,
|
||||||
|
IDetectedOperationService detectedOperationService,
|
||||||
|
ITelemetryDataSaubService telemetryDataSaubService)
|
||||||
|
{
|
||||||
|
this.wellService = wellService;
|
||||||
|
this.subsystemRepository = subsystemRepository;
|
||||||
|
this.detectedOperationService = detectedOperationService;
|
||||||
|
this.telemetryDataSaubService = telemetryDataSaubService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<SubsystemStatDto>> GetStatAsync(SubsystemTimeRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var well = await wellService.GetOrDefaultAsync(request.IdWell, token)
|
||||||
|
?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} does not exist");
|
||||||
|
|
||||||
|
var detectedOperationSummaryRequest = new DetectedOperationSummaryRequest
|
||||||
|
{
|
||||||
|
IdsTelemetries = new[] { well.IdTelemetry!.Value },
|
||||||
|
IdsOperationCategories = WellOperationCategory.MechanicalDrillingSubIds,
|
||||||
|
|
||||||
|
GeDateStart = request.GeDate,
|
||||||
|
LeDateStart = request.LtDate,
|
||||||
|
|
||||||
|
GeDepthStart = request.GtDepth,
|
||||||
|
LeDepthStart = request.LtDepth,
|
||||||
|
};
|
||||||
|
|
||||||
|
var operations = await detectedOperationService.GetOperationSummaryAsync(detectedOperationSummaryRequest,
|
||||||
|
token);
|
||||||
|
|
||||||
|
if (!operations.Any())
|
||||||
|
return Enumerable.Empty<SubsystemStatDto>();
|
||||||
|
|
||||||
|
var stat = await CalcStatAsync(operations, token);
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(int idCompany, DateTime? gtDate, DateTime? ltDate,
|
||||||
|
CancellationToken token)
|
||||||
|
{
|
||||||
|
var activeWells = await wellService.GetAsync(new() { IdCompany = idCompany, IdState = 1 }, token);
|
||||||
|
var result = await GetStatAsync(activeWells, gtDate, ltDate, token);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatByActiveWells(IEnumerable<int> wellIds, CancellationToken token)
|
||||||
|
{
|
||||||
|
var activeWells = await wellService.GetAsync(new() { Ids = wellIds, IdState = 1 }, token);
|
||||||
|
var result = await GetStatAsync(activeWells, null, null, token);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<SubsystemStatDto>> CalcStatAsync(IEnumerable<OperationsSummaryDto> operations, CancellationToken token)
|
||||||
|
{
|
||||||
|
var subsystems = await subsystemRepository.GetAllAsync(token);
|
||||||
|
|
||||||
|
var groupedOperations = operations
|
||||||
|
.GroupBy(o => o.IdCategory);
|
||||||
|
|
||||||
|
var stat = groupedOperations.Select(groupOperations =>
|
||||||
|
{
|
||||||
|
var idSubsystem = groupOperations.Key switch
|
||||||
|
{
|
||||||
|
WellOperationCategory.IdRotor => IdSubsystemAPDRotor,
|
||||||
|
WellOperationCategory.IdSlide => IdSubsystemAPDSlide,
|
||||||
|
_ => throw new ArgumentException($"IdCategory: {groupOperations.Key} does not supported in this method",
|
||||||
|
nameof(groupOperations.Key)),
|
||||||
|
};
|
||||||
|
|
||||||
|
var operationsWithEnableSubsystems = groupOperations.Where(o => o.EnabledSubsystems >= 1);
|
||||||
|
|
||||||
|
var subsystemStat = new SubsystemStatDto
|
||||||
|
{
|
||||||
|
IdSubsystem = idSubsystem,
|
||||||
|
SubsystemName = subsystems.FirstOrDefault(s => s.Id == idSubsystem)?.Name ?? "unknown",
|
||||||
|
UsedTimeHours = operationsWithEnableSubsystems.Sum(o => o.SumDurationHours),
|
||||||
|
SumOperationDepthInterval = groupOperations.Sum(o => o.SumDepthIntervals),
|
||||||
|
SumOperationDurationHours = groupOperations.Sum(o => o.SumDurationHours),
|
||||||
|
SumDepthInterval = operationsWithEnableSubsystems.Sum(o => o.SumDepthIntervals),
|
||||||
|
OperationCount = operationsWithEnableSubsystems.Sum(o => o.Count),
|
||||||
|
};
|
||||||
|
|
||||||
|
subsystemStat.KUsage = subsystemStat.SumDepthInterval / subsystemStat.SumOperationDepthInterval;
|
||||||
|
|
||||||
|
return subsystemStat;
|
||||||
|
});
|
||||||
|
|
||||||
|
var apdSlidePart = stat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemAPDSlide);
|
||||||
|
|
||||||
|
if (apdSlidePart is not null)
|
||||||
|
{
|
||||||
|
var operationsWithSpinMaster = operations.Where(s => s.EnabledSubsystems == IdEnabledSubsystemSpinMaster);
|
||||||
|
|
||||||
|
var spin = new SubsystemStatDto
|
||||||
|
{
|
||||||
|
IdSubsystem = IdSubsystemSpinMaster,
|
||||||
|
SubsystemName = subsystems.FirstOrDefault(s => s.Id == IdSubsystemSpinMaster)?.Name ?? "unknown",
|
||||||
|
UsedTimeHours = operationsWithSpinMaster.Sum(o => o.SumDurationHours),
|
||||||
|
SumOperationDepthInterval = apdSlidePart.SumOperationDepthInterval,
|
||||||
|
SumOperationDurationHours = apdSlidePart.SumOperationDurationHours,
|
||||||
|
SumDepthInterval = operationsWithSpinMaster.Sum(o => o.SumDepthIntervals),
|
||||||
|
OperationCount = operationsWithSpinMaster.Sum(s => s.Count)
|
||||||
|
};
|
||||||
|
|
||||||
|
spin.KUsage = spin.SumDepthInterval / spin.SumOperationDepthInterval;
|
||||||
|
|
||||||
|
stat = stat.Append(spin);
|
||||||
|
}
|
||||||
|
|
||||||
|
var apdParts = stat.Where(s => s.IdSubsystem is IdSubsystemAPDRotor or IdSubsystemAPDSlide);
|
||||||
|
|
||||||
|
if (!apdParts.Any())
|
||||||
|
return stat;
|
||||||
|
|
||||||
|
var apdSum = new SubsystemStatDto
|
||||||
|
{
|
||||||
|
IdSubsystem = IdSubsystemAPD,
|
||||||
|
SubsystemName = "АПД",
|
||||||
|
UsedTimeHours = apdParts.Sum(part => part.UsedTimeHours),
|
||||||
|
SumOperationDepthInterval = apdParts.Sum(part => part.SumOperationDepthInterval),
|
||||||
|
SumOperationDurationHours = apdParts.Sum(part => part.SumOperationDurationHours),
|
||||||
|
SumDepthInterval = apdParts.Sum(part => part.SumDepthInterval),
|
||||||
|
OperationCount = apdParts.Sum(part => part.OperationCount),
|
||||||
|
};
|
||||||
|
|
||||||
|
apdSum.KUsage = apdSum.SumDepthInterval / apdSum.SumOperationDepthInterval;
|
||||||
|
|
||||||
|
stat = stat.Append(apdSum).OrderBy(m => m.IdSubsystem);
|
||||||
|
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatAsync(IEnumerable<WellDto> wells, DateTime? gtDate, DateTime? ltDate,
|
||||||
|
CancellationToken token)
|
||||||
|
{
|
||||||
|
if (!wells.Any())
|
||||||
|
return Enumerable.Empty<SubsystemActiveWellStatDto>();
|
||||||
|
|
||||||
|
var idsTelemetries = wells
|
||||||
|
.Where(w => w.IdTelemetry is not null)
|
||||||
|
.Select(w => w.IdTelemetry!.Value)
|
||||||
|
.Distinct();
|
||||||
|
|
||||||
|
var wellsStat = new List<SubsystemActiveWellStatDto>();
|
||||||
|
|
||||||
|
foreach (var well in wells)
|
||||||
|
{
|
||||||
|
var hoursOffset = well.Timezone.Hours;
|
||||||
|
|
||||||
|
var dateRange = telemetryDataSaubService.GetRange(well.Id);
|
||||||
|
|
||||||
|
var beginUTC = gtDate.HasValue
|
||||||
|
? gtDate.Value.ToUtcDateTimeOffset(hoursOffset)
|
||||||
|
: dateRange.From.ToUtcDateTimeOffset(hoursOffset);
|
||||||
|
|
||||||
|
var endUTC = ltDate.HasValue
|
||||||
|
? ltDate.Value.ToUtcDateTimeOffset(hoursOffset)
|
||||||
|
: dateRange.To.ToUtcDateTimeOffset(hoursOffset);
|
||||||
|
|
||||||
|
var operations = await detectedOperationService
|
||||||
|
.GetOperationSummaryAsync(new()
|
||||||
|
{
|
||||||
|
IdsTelemetries = idsTelemetries,
|
||||||
|
IdsOperationCategories = WellOperationCategory.MechanicalDrillingSubIds,
|
||||||
|
GeDateStart = beginUTC,
|
||||||
|
LeDateEnd = endUTC,
|
||||||
|
}, token);
|
||||||
|
|
||||||
|
var wellStat = new SubsystemActiveWellStatDto { Well = well };
|
||||||
|
|
||||||
|
var telemetryOperations = operations.Where(o => o.IdTelemetry == well.IdTelemetry);
|
||||||
|
|
||||||
|
if (!telemetryOperations.Any())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var subsystemStat = await CalcStatAsync(telemetryOperations, token);
|
||||||
|
|
||||||
|
if (!subsystemStat.Any())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wellStat.SubsystemAPD = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemAPD);
|
||||||
|
wellStat.SubsystemSpinMaster = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemSpinMaster);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wellsStat;
|
||||||
|
}
|
||||||
|
}
|
@ -1,56 +0,0 @@
|
|||||||
using AsbCloudDb.Model.Subsystems;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.Subsystems
|
|
||||||
{
|
|
||||||
public class SubsystemDetector
|
|
||||||
{
|
|
||||||
private readonly int idTelemetry;
|
|
||||||
private readonly int idSubsystem;
|
|
||||||
private readonly Func<short?, bool> isEnable;
|
|
||||||
private readonly Func<SubsystemOperationTime, bool> isValid;
|
|
||||||
(bool isEnable, DateTimeOffset date, float depth) pre = default;
|
|
||||||
|
|
||||||
public SubsystemDetector(
|
|
||||||
int idTelemetry,
|
|
||||||
int idSubsystem,
|
|
||||||
Func<short?, bool> isEnable,
|
|
||||||
Func<SubsystemOperationTime, bool> isValid)
|
|
||||||
{
|
|
||||||
this.idTelemetry = idTelemetry;
|
|
||||||
this.idSubsystem = idSubsystem;
|
|
||||||
this.isEnable = isEnable;
|
|
||||||
this.isValid = isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryDetect(short? mode, DateTimeOffset date, float depth, out SubsystemOperationTime? subsystemOperationTime)
|
|
||||||
{
|
|
||||||
var isEnable = this.isEnable(mode);
|
|
||||||
|
|
||||||
if (!pre.isEnable && isEnable)
|
|
||||||
{
|
|
||||||
pre = (true, date, depth);
|
|
||||||
}
|
|
||||||
else if (pre.isEnable && !isEnable)
|
|
||||||
{
|
|
||||||
var detected = new SubsystemOperationTime
|
|
||||||
{
|
|
||||||
IdTelemetry = idTelemetry,
|
|
||||||
IdSubsystem = idSubsystem,
|
|
||||||
DateStart = pre.date,
|
|
||||||
DateEnd = date,
|
|
||||||
DepthStart = pre.depth,
|
|
||||||
DepthEnd = depth,
|
|
||||||
};
|
|
||||||
pre.isEnable = false;
|
|
||||||
if (isValid(detected))
|
|
||||||
{
|
|
||||||
subsystemOperationTime = detected;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
subsystemOperationTime = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,9 +4,7 @@ using AsbCloudApp.Data.WITS;
|
|||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudApp.Services.Subsystems;
|
|
||||||
using AsbCloudInfrastructure.Background;
|
using AsbCloudInfrastructure.Background;
|
||||||
using AsbCloudInfrastructure.Services.SAUB;
|
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
using System;
|
||||||
@ -35,7 +33,7 @@ public class WellInfoService
|
|||||||
var wellService = services.GetRequiredService<IWellService>();
|
var wellService = services.GetRequiredService<IWellService>();
|
||||||
var operationsStatService = services.GetRequiredService<IOperationsStatService>();
|
var operationsStatService = services.GetRequiredService<IOperationsStatService>();
|
||||||
var processMapPlanWellDrillingRepository = services.GetRequiredService<IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto>>();
|
var processMapPlanWellDrillingRepository = services.GetRequiredService<IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto>>();
|
||||||
var subsystemOperationTimeService = services.GetRequiredService<ISubsystemOperationTimeService>();
|
var subsystemService = services.GetRequiredService<ISubsystemService>();
|
||||||
var telemetryDataSaubCache = services.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
var telemetryDataSaubCache = services.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
||||||
var messageHub = services.GetRequiredService<IIntegrationEventHandler<UpdateWellInfoEvent>>();
|
var messageHub = services.GetRequiredService<IIntegrationEventHandler<UpdateWellInfoEvent>>();
|
||||||
|
|
||||||
@ -57,7 +55,7 @@ public class WellInfoService
|
|||||||
|
|
||||||
var operationsStat = await operationsStatService.GetWellsStatAsync(wellsIds, token);
|
var operationsStat = await operationsStatService.GetWellsStatAsync(wellsIds, token);
|
||||||
|
|
||||||
var subsystemStat = await subsystemOperationTimeService
|
var subsystemStat = await subsystemService
|
||||||
.GetStatByActiveWells(wellsIds, token);
|
.GetStatByActiveWells(wellsIds, token);
|
||||||
subsystemStat = subsystemStat.ToArray();
|
subsystemStat = subsystemStat.ToArray();
|
||||||
|
|
||||||
@ -157,7 +155,7 @@ public class WellInfoService
|
|||||||
};
|
};
|
||||||
|
|
||||||
var wellSubsystemStat = subsystemStat.FirstOrDefault(s => s.Well.Id == well.Id);
|
var wellSubsystemStat = subsystemStat.FirstOrDefault(s => s.Well.Id == well.Id);
|
||||||
wellMapInfo.SaubUsage = wellSubsystemStat?.SubsystemAKB?.KUsage ?? 0d;
|
wellMapInfo.SaubUsage = wellSubsystemStat?.SubsystemAPD?.KUsage ?? 0d;
|
||||||
wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d;
|
wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d;
|
||||||
wellMapInfo.TorqueKUsage = wellSubsystemStat?.SubsystemTorqueMaster?.KUsage ?? 0d;
|
wellMapInfo.TorqueKUsage = wellSubsystemStat?.SubsystemTorqueMaster?.KUsage ?? 0d;
|
||||||
wellMapInfo.TvdLagDays = wellOperationsStat?.TvdLagDays;
|
wellMapInfo.TvdLagDays = wellOperationsStat?.TvdLagDays;
|
||||||
|
@ -32,8 +32,6 @@ namespace AsbCloudInfrastructure
|
|||||||
backgroundWorker.Add<WorkToDeleteOldReports>(TimeSpan.FromDays(1));
|
backgroundWorker.Add<WorkToDeleteOldReports>(TimeSpan.FromDays(1));
|
||||||
backgroundWorker.Add<WellInfoService.WorkWellInfoUpdate>(TimeSpan.FromMinutes(30));
|
backgroundWorker.Add<WellInfoService.WorkWellInfoUpdate>(TimeSpan.FromMinutes(30));
|
||||||
backgroundWorker.Add<WorkOperationDetection>(TimeSpan.FromMinutes(15));
|
backgroundWorker.Add<WorkOperationDetection>(TimeSpan.FromMinutes(15));
|
||||||
backgroundWorker.Add<WorkSubsystemAbfOperationTimeCalc>(TimeSpan.FromMinutes(30));
|
|
||||||
backgroundWorker.Add<WorkSubsystemOscillationOperationTimeCalc>(TimeSpan.FromMinutes(30));
|
|
||||||
backgroundWorker.Add<WorkLimitingParameterCalc>(TimeSpan.FromMinutes(30));
|
backgroundWorker.Add<WorkLimitingParameterCalc>(TimeSpan.FromMinutes(30));
|
||||||
backgroundWorker.Add(MakeMemoryMonitoringWork(), TimeSpan.FromMinutes(1));
|
backgroundWorker.Add(MakeMemoryMonitoringWork(), TimeSpan.FromMinutes(1));
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ using AsbCloudApp.Repositories;
|
|||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
|
||||||
using AsbCloudApp.Services.Subsystems;
|
|
||||||
using AsbCloudInfrastructure.Services.DailyReport;
|
using AsbCloudInfrastructure.Services.DailyReport;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@ -191,7 +190,7 @@ public class DailyReportServiceTest
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly SubsystemStatDto fakeStatSubsystemOperationTime = new()
|
private readonly SubsystemStatDto fakeSubsystemsStat = new()
|
||||||
{
|
{
|
||||||
SubsystemName = "АПД",
|
SubsystemName = "АПД",
|
||||||
SumDepthInterval = 250,
|
SumDepthInterval = 250,
|
||||||
@ -204,7 +203,7 @@ public class DailyReportServiceTest
|
|||||||
private readonly IDailyReportRepository dailyReportRepositoryMock = Substitute.For<IDailyReportRepository>();
|
private readonly IDailyReportRepository dailyReportRepositoryMock = Substitute.For<IDailyReportRepository>();
|
||||||
private readonly IScheduleRepository scheduleRepositoryMock = Substitute.For<IScheduleRepository>();
|
private readonly IScheduleRepository scheduleRepositoryMock = Substitute.For<IScheduleRepository>();
|
||||||
private readonly IWellOperationRepository wellOperationRepositoryMock = Substitute.For<IWellOperationRepository>();
|
private readonly IWellOperationRepository wellOperationRepositoryMock = Substitute.For<IWellOperationRepository>();
|
||||||
private readonly ISubsystemOperationTimeService subsystemOperationTimeServiceMock = Substitute.For<ISubsystemOperationTimeService>();
|
private readonly ISubsystemService subsystemServiceMock = Substitute.For<ISubsystemService>();
|
||||||
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingServiceMock = Substitute.For<IProcessMapReportWellDrillingService>();
|
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingServiceMock = Substitute.For<IProcessMapReportWellDrillingService>();
|
||||||
private readonly IDetectedOperationService detectedOperationServiceMock = Substitute.For<IDetectedOperationService>();
|
private readonly IDetectedOperationService detectedOperationServiceMock = Substitute.For<IDetectedOperationService>();
|
||||||
|
|
||||||
@ -245,7 +244,7 @@ public class DailyReportServiceTest
|
|||||||
dailyReportRepositoryMock,
|
dailyReportRepositoryMock,
|
||||||
scheduleRepositoryMock,
|
scheduleRepositoryMock,
|
||||||
wellOperationRepositoryMock,
|
wellOperationRepositoryMock,
|
||||||
subsystemOperationTimeServiceMock,
|
subsystemServiceMock,
|
||||||
processMapReportWellDrillingServiceMock,
|
processMapReportWellDrillingServiceMock,
|
||||||
detectedOperationServiceMock);
|
detectedOperationServiceMock);
|
||||||
|
|
||||||
@ -276,8 +275,8 @@ public class DailyReportServiceTest
|
|||||||
detectedOperationServiceMock.GetAsync(Arg.Any<DetectedOperationRequest>(), Arg.Any<CancellationToken>())
|
detectedOperationServiceMock.GetAsync(Arg.Any<DetectedOperationRequest>(), Arg.Any<CancellationToken>())
|
||||||
.ReturnsForAnyArgs(fakeWellOperationSlipsTime);
|
.ReturnsForAnyArgs(fakeWellOperationSlipsTime);
|
||||||
|
|
||||||
subsystemOperationTimeServiceMock.GetStatAsync(Arg.Any<SubsystemOperationTimeRequest>(), Arg.Any<CancellationToken>())
|
subsystemServiceMock.GetStatAsync(Arg.Any<SubsystemTimeRequest>(), Arg.Any<CancellationToken>())
|
||||||
.ReturnsForAnyArgs(new[] { fakeStatSubsystemOperationTime });
|
.ReturnsForAnyArgs(new[] { fakeSubsystemsStat });
|
||||||
|
|
||||||
scheduleRepositoryMock.GetAsync(idWell, dateDailyReport, Arg.Any<CancellationToken>())
|
scheduleRepositoryMock.GetAsync(idWell, dateDailyReport, Arg.Any<CancellationToken>())
|
||||||
.ReturnsForAnyArgs(new[] { fakeShedule });
|
.ReturnsForAnyArgs(new[] { fakeShedule });
|
||||||
|
92
AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs
Normal file
92
AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.Subsystems;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Controllers.Subsystems
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Наработка подсистем
|
||||||
|
/// </summary>
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
[Authorize]
|
||||||
|
public class SubsystemController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ISubsystemService subsystemService;
|
||||||
|
private readonly ITelemetryDataSaubService telemetryDataSaubService;
|
||||||
|
private readonly IWellService wellService;
|
||||||
|
|
||||||
|
public SubsystemController(
|
||||||
|
ISubsystemService subsystemService,
|
||||||
|
IWellService wellService,
|
||||||
|
ITelemetryDataSaubService telemetryDataSaubService)
|
||||||
|
{
|
||||||
|
this.subsystemService = subsystemService;
|
||||||
|
this.wellService = wellService;
|
||||||
|
this.telemetryDataSaubService = telemetryDataSaubService;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// получить статистику
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("stat")]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<SubsystemStatDto>), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
|
||||||
|
public async Task<IActionResult> GetStatAsync([FromQuery] SubsystemTimeRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
||||||
|
return Forbid();
|
||||||
|
var subsystemResult = await subsystemService.GetStatAsync(request, token);
|
||||||
|
return Ok(subsystemResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// получить период, за который будет рассчитываться статистика
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("operationsPeriod/{idWell}")]
|
||||||
|
[ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> GetStatDateRangeAsync([FromRoute] int idWell, CancellationToken token)
|
||||||
|
{
|
||||||
|
if (!await UserHasAccessToWellAsync(idWell, token))
|
||||||
|
return Forbid();
|
||||||
|
|
||||||
|
var dateRange = telemetryDataSaubService.GetRange(idWell);
|
||||||
|
|
||||||
|
return Ok(dateRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// получить статистику по активным скважинам
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gtDate"> Больше или равно дате </param>
|
||||||
|
/// <param name="ltDate"> Меньше или равно дате </param>
|
||||||
|
/// <param name="token"> Токен </param>
|
||||||
|
/// <returns> </returns>
|
||||||
|
[HttpGet("statByActiveWell")]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<SubsystemActiveWellStatDto>), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> GetStatByWellAsync(DateTime? gtDate, DateTime? ltDate, CancellationToken token)
|
||||||
|
{
|
||||||
|
var idCompany = User.GetCompanyId();
|
||||||
|
if (!idCompany.HasValue)
|
||||||
|
return Forbid();
|
||||||
|
var subsystemResult = await subsystemService.GetStatByActiveWells(idCompany.Value, gtDate, ltDate, token);
|
||||||
|
return Ok(subsystemResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> UserHasAccessToWellAsync(int idWell, CancellationToken token)
|
||||||
|
{
|
||||||
|
var idCompany = User.GetCompanyId();
|
||||||
|
if (idCompany is not null &&
|
||||||
|
await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token)
|
||||||
|
.ConfigureAwait(false))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,162 +0,0 @@
|
|||||||
using AsbCloudApp.Data;
|
|
||||||
using AsbCloudApp.Data.Subsystems;
|
|
||||||
using AsbCloudApp.Requests;
|
|
||||||
using AsbCloudApp.Services;
|
|
||||||
using AsbCloudApp.Services.Subsystems;
|
|
||||||
using AsbCloudDb.Model;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers.Subsystems
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Наработка подсистем
|
|
||||||
/// </summary>
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
[ApiController]
|
|
||||||
[Authorize]
|
|
||||||
public class SubsystemOperationTimeController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISubsystemOperationTimeService subsystemOperationTimeService;
|
|
||||||
private readonly ITelemetryDataSaubService telemetryDataSaubService;
|
|
||||||
private readonly IWellService wellService;
|
|
||||||
|
|
||||||
private readonly Dictionary<int, string> subsystemNames = new()
|
|
||||||
{
|
|
||||||
{ 1, "SAUB" },
|
|
||||||
{ 65537, "Torque Master" },
|
|
||||||
{ 65536, "Spin Master" }
|
|
||||||
};
|
|
||||||
|
|
||||||
public SubsystemOperationTimeController(
|
|
||||||
ISubsystemOperationTimeService subsystemOperationTimeService,
|
|
||||||
IWellService wellService,
|
|
||||||
ITelemetryDataSaubService telemetryDataSaubService)
|
|
||||||
{
|
|
||||||
this.subsystemOperationTimeService = subsystemOperationTimeService;
|
|
||||||
this.wellService = wellService;
|
|
||||||
this.telemetryDataSaubService = telemetryDataSaubService;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// получить статистику
|
|
||||||
/// </summary>
|
|
||||||
[HttpGet("stat")]
|
|
||||||
[ProducesResponseType(typeof(IEnumerable<SubsystemStatDto>), (int)System.Net.HttpStatusCode.OK)]
|
|
||||||
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
|
|
||||||
public async Task<IActionResult> GetStatAsync([FromQuery] SubsystemOperationTimeRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
|
||||||
return Forbid();
|
|
||||||
var subsystemResult = await subsystemOperationTimeService.GetStatAsync(request, token);
|
|
||||||
return Ok(subsystemResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// получить период, за который будет рассчитываться статистика
|
|
||||||
/// </summary>
|
|
||||||
[HttpGet("operationsPeriod/{idWell}")]
|
|
||||||
[ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)]
|
|
||||||
public async Task<IActionResult> GetStatDateRangeAsync([FromRoute] int idWell, CancellationToken token)
|
|
||||||
{
|
|
||||||
if (!await UserHasAccessToWellAsync(idWell, token))
|
|
||||||
return Forbid();
|
|
||||||
|
|
||||||
var dateRange = telemetryDataSaubService.GetRange(idWell);
|
|
||||||
|
|
||||||
return Ok(dateRange);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// получить статистику по активным скважинам
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="GtDate"> Больше или равно дате </param>
|
|
||||||
/// <param name="LtDate"> Меньше или равно дате </param>
|
|
||||||
/// <param name="token"> Токен </param>
|
|
||||||
/// <returns> </returns>
|
|
||||||
[HttpGet("statByActiveWell")]
|
|
||||||
[ProducesResponseType(typeof(IEnumerable<SubsystemActiveWellStatDto>), (int)System.Net.HttpStatusCode.OK)]
|
|
||||||
public async Task<IActionResult> GetStatByWellAsync(DateTime? GtDate, DateTime? LtDate, CancellationToken token)
|
|
||||||
{
|
|
||||||
var idCompany = User.GetCompanyId();
|
|
||||||
if (!idCompany.HasValue)
|
|
||||||
return Forbid();
|
|
||||||
var subsystemResult = await subsystemOperationTimeService.GetStatByActiveWells(idCompany.Value, GtDate, LtDate, token);
|
|
||||||
return Ok(subsystemResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// получить доступный диапазон дат наработки подсистемы.
|
|
||||||
/// </summary>
|
|
||||||
[HttpGet("datesRange")]
|
|
||||||
[ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)]
|
|
||||||
public async Task<IActionResult> GetDateRangeOperationTimeAsync([FromQuery] SubsystemOperationTimeRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
|
||||||
return Forbid();
|
|
||||||
var result = await subsystemOperationTimeService.GetDateRangeOperationTimeAsync(request, token);
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// получить список наработок подсистем
|
|
||||||
/// </summary>
|
|
||||||
[HttpGet("operationTime")]
|
|
||||||
[ProducesResponseType(typeof(IEnumerable<SubsystemOperationTimeDto>), (int)System.Net.HttpStatusCode.OK)]
|
|
||||||
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
|
|
||||||
public async Task<IActionResult> GetOperationTimeAsync(
|
|
||||||
[FromQuery] SubsystemOperationTimeRequest request,
|
|
||||||
CancellationToken token)
|
|
||||||
{
|
|
||||||
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
|
||||||
return Forbid();
|
|
||||||
|
|
||||||
var result = await subsystemOperationTimeService.GetOperationTimeAsync(request, token);
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Удалить наработки.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpDelete]
|
|
||||||
[Permission]
|
|
||||||
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
|
||||||
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
|
|
||||||
public async Task<IActionResult> DeleteAsync(
|
|
||||||
[FromQuery] SubsystemOperationTimeRequest request,
|
|
||||||
CancellationToken token)
|
|
||||||
{
|
|
||||||
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
|
||||||
return Forbid();
|
|
||||||
var result = await subsystemOperationTimeService.DeleteAsync(request, token);
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение словаря названий подсистем
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpGet("names")]
|
|
||||||
[ProducesResponseType(typeof(Dictionary<int, string>), (int)System.Net.HttpStatusCode.OK)]
|
|
||||||
public IActionResult GetSubsystemsNames()
|
|
||||||
{
|
|
||||||
return Ok(subsystemNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task<bool> UserHasAccessToWellAsync(int idWell, CancellationToken token)
|
|
||||||
{
|
|
||||||
var idCompany = User.GetCompanyId();
|
|
||||||
if (idCompany is not null &&
|
|
||||||
await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token)
|
|
||||||
.ConfigureAwait(false))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user