forked from ddrilling/AsbCloudServer
fixed
This commit is contained in:
parent
4f27adf9ea
commit
79108c754a
@ -47,14 +47,17 @@ namespace AsbCloudApp.Requests
|
||||
/// информация попадает в выборку, если интервал выборки частично или полностью пересекается с запрашиваемым интервалом
|
||||
/// </summary>
|
||||
public const int SelectModeOuter = 0;
|
||||
|
||||
/// <summary>
|
||||
/// информация попадает в выборку, если интервал выборки строго полностью пересекается с запрашиваемым интервалом.
|
||||
/// </summary>
|
||||
public const int SelectModeInner = 1;
|
||||
|
||||
/// <summary>
|
||||
/// аналогично outer, но интервалы в частично пересекающиеся укорачиваются по границам интервала выборки.
|
||||
/// </summary>
|
||||
public const int SelectModeTrim = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Режим выборки элементов
|
||||
/// </summary>
|
||||
|
@ -1,19 +1,41 @@
|
||||
using AsbCloudApp.Data.Subsystems;
|
||||
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.Subsystems
|
||||
{
|
||||
#nullable enable
|
||||
/// <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);
|
||||
}
|
||||
#nullable disable
|
||||
|
@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
@ -9,9 +6,8 @@ namespace AsbCloudDb.Model.Subsystems
|
||||
{
|
||||
[Table("t_subsystem"), Comment("Описание подсистем")]
|
||||
public class Subsystem : IId
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
{
|
||||
[Column("id"), Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
@ -22,6 +18,5 @@ namespace AsbCloudDb.Model.Subsystems
|
||||
[StringLength(255)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,7 @@ namespace AsbCloudDb.Model.Subsystems
|
||||
[Table("t_subsystem_operation_time"), Comment("наработки подсистем")]
|
||||
public partial class SubsystemOperationTime : IId
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
[Column("id"), Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("id_telemetry"), Comment("ИД телеметрии по которой выдается информация")]
|
||||
@ -20,23 +19,23 @@ namespace AsbCloudDb.Model.Subsystems
|
||||
public int IdSubsystem { get; set; }
|
||||
|
||||
[Column("date_start"), Comment("дата/время включения подсистемы")]
|
||||
public DateTimeOffset DateStart { get; set; }
|
||||
public DateTimeOffset DateStart { get; set; }
|
||||
|
||||
[Column("date_end"), Comment("дата/время выключения подсистемы")]
|
||||
public DateTimeOffset DateEnd { get; set; }
|
||||
public DateTimeOffset DateEnd { get; set; }
|
||||
|
||||
[Column("depth_start"), Comment("глубина забоя на момент включения подсистемы")]
|
||||
public float? DepthStart { get; set; }
|
||||
|
||||
[Column("depth_end"), Comment("глубина забоя на момент выключения подсистемы")]
|
||||
public float? DepthEnd { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[ForeignKey(nameof(IdSubsystem))]
|
||||
public virtual Subsystem Subsystem { get; set; }
|
||||
[ForeignKey(nameof(IdSubsystem))]
|
||||
public virtual Subsystem Subsystem { get; set; } = null!;
|
||||
|
||||
[JsonIgnore]
|
||||
[ForeignKey(nameof(IdTelemetry))]
|
||||
public virtual Telemetry Telemetry { get; set; }
|
||||
|
||||
|
||||
|
||||
public virtual Telemetry Telemetry { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ using Npgsql;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@ -26,17 +25,18 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
{
|
||||
connectionString = configuration.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken token)
|
||||
{
|
||||
var timeToStartAnalysis = DateTime.Now;
|
||||
var timeToStart = DateTime.Now;
|
||||
var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||
.UseNpgsql(connectionString)
|
||||
.Options;
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
if (DateTime.Now > timeToStartAnalysis)
|
||||
if (DateTime.Now > timeToStart)
|
||||
{
|
||||
timeToStartAnalysis = DateTime.Now + period;
|
||||
timeToStart = DateTime.Now + period;
|
||||
try
|
||||
{
|
||||
using var context = new AsbCloudDbContext(options);
|
||||
@ -49,7 +49,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
}
|
||||
GC.Collect();
|
||||
}
|
||||
var ms = (int)(timeToStartAnalysis - DateTime.Now).TotalMilliseconds;
|
||||
var ms = (int)(timeToStart - DateTime.Now).TotalMilliseconds;
|
||||
ms = ms > 100 ? ms : 100;
|
||||
await Task.Delay(ms, token).ConfigureAwait(false);
|
||||
}
|
||||
@ -76,7 +76,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
.Select(t => t.Id)
|
||||
.ToListAsync(token);
|
||||
|
||||
var JounedlastDetectedDates = telemetryIds
|
||||
var telemetryLastDetectedDates = telemetryIds
|
||||
.GroupJoin(lastDetectedDates,
|
||||
t => t,
|
||||
o => o.IdTelemetry,
|
||||
@ -85,8 +85,9 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
IdTelemetry = outer,
|
||||
inner.SingleOrDefault()?.LastDate,
|
||||
});
|
||||
|
||||
var affected = 0;
|
||||
foreach (var item in JounedlastDetectedDates)
|
||||
foreach (var item in telemetryLastDetectedDates)
|
||||
{
|
||||
var newOperationsSaub = await OperationTimeSaubAsync(item.IdTelemetry, item.LastDate ?? DateTimeOffset.MinValue, db, token);
|
||||
if (newOperationsSaub?.Any() == true)
|
||||
@ -103,139 +104,157 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
}
|
||||
return affected;
|
||||
}
|
||||
private static async Task<IEnumerable<SubsystemOperationTime>?> OperationTimeSaubAsync(int idTelemetry, DateTimeOffset begin, IAsbCloudDbContext db, CancellationToken token)
|
||||
{
|
||||
var operationTimeSaub =
|
||||
$"select tt.date, tt.mode, tt.well_depth" +
|
||||
$" from (select date, mode, well_depth, lag(mode,1) over (order by date) as mode_prev" +
|
||||
$" from t_telemetry_data_saub where id_telemetry = @idTelemetry) as tt" +
|
||||
$" where tt.mode != tt.mode_prev and tt.date >= @begin order by tt.date;";
|
||||
using var command = db.Database.GetDbConnection().CreateCommand();
|
||||
command.CommandText = operationTimeSaub;
|
||||
var telemetry = new NpgsqlParameter("@idTelemetry", idTelemetry);
|
||||
command.Parameters.Add(telemetry);
|
||||
var dateStart = new NpgsqlParameter("@begin", begin);
|
||||
command.Parameters.Add(dateStart);
|
||||
db.Database.OpenConnection();
|
||||
using var result = await command.ExecuteReaderAsync(token);
|
||||
var telemetryOpearationSaubSubsystems = new List<SubsystemsSpinWithDepth>();
|
||||
if (result.HasRows)
|
||||
private static async Task<IEnumerable<SubsystemOperationTime>> OperationTimeSaubAsync(int idTelemetry, DateTimeOffset begin, IAsbCloudDbContext db, CancellationToken token)
|
||||
{
|
||||
static int? GetSubsytemId(short mode)
|
||||
{
|
||||
return mode +1;
|
||||
}
|
||||
|
||||
var query =
|
||||
$"select tt.date, tt.mode, tt.well_depth " +
|
||||
$"from ( " +
|
||||
$" select " +
|
||||
$" date, " +
|
||||
$" mode, " +
|
||||
$" well_depth, " +
|
||||
$" lag(mode,1) over (order by date) as mode_prev " +
|
||||
$" from t_telemetry_data_saub " +
|
||||
$" where id_telemetry = @idTelemetry " +
|
||||
$" order by date ) as tt " +
|
||||
$"where (tt.mode_prev is null or tt.mode != tt.mode_prev) and tt.date >= @begin " +
|
||||
$"order by tt.date;";
|
||||
|
||||
var idTelemetryParam = new NpgsqlParameter("@idTelemetry", idTelemetry);
|
||||
var beginParam = new NpgsqlParameter("@begin", begin);
|
||||
|
||||
await db.Database.OpenConnectionAsync(token);
|
||||
using var command = db.Database.GetDbConnection().CreateCommand();
|
||||
command.CommandText = query;
|
||||
command.Parameters.Add(idTelemetryParam);
|
||||
command.Parameters.Add(beginParam);
|
||||
|
||||
using var result = await command.ExecuteReaderAsync(token);
|
||||
|
||||
var subsystemOperationTime = new List<SubsystemOperationTime>(32);
|
||||
|
||||
if (result.Read())
|
||||
{
|
||||
var mode = result.GetFieldValue<short>(1);
|
||||
var idSubsystem = GetSubsytemId(mode);
|
||||
var dateStart = result.GetFieldValue<DateTimeOffset>(0);
|
||||
var depthStart = result.GetFieldValue<float>(2);
|
||||
while (result.Read())
|
||||
{
|
||||
var itemEntity = new SubsystemsSpinWithDepth()
|
||||
var dateEnd = result.GetFieldValue<DateTimeOffset>(0);
|
||||
var depthEnd = result.GetFieldValue<float>(2);
|
||||
if (idSubsystem.HasValue)
|
||||
{
|
||||
Date = result.GetFieldValue<DateTimeOffset>(0),
|
||||
IdSubsystem = result.GetFieldValue<short>(1)+1,
|
||||
Depth = result.GetFieldValue<float>(2)
|
||||
};
|
||||
telemetryOpearationSaubSubsystems.Add(itemEntity);
|
||||
var operationTimeItem = new SubsystemOperationTime()
|
||||
{
|
||||
IdTelemetry = idTelemetry,
|
||||
IdSubsystem = idSubsystem.Value,
|
||||
DateStart = dateStart,
|
||||
DateEnd = dateEnd,
|
||||
DepthStart = depthStart,
|
||||
DepthEnd = depthEnd
|
||||
};
|
||||
subsystemOperationTime.Add(operationTimeItem);
|
||||
}
|
||||
mode = result.GetFieldValue<short>(1);
|
||||
idSubsystem = GetSubsytemId(mode);
|
||||
dateStart = dateEnd;
|
||||
depthStart = depthEnd;
|
||||
}
|
||||
}
|
||||
var resultSubsystemOperationTime = new List<SubsystemOperationTime>();
|
||||
var firstItem = telemetryOpearationSaubSubsystems.FirstOrDefault();
|
||||
if (firstItem is null)
|
||||
return null;
|
||||
int idSubsystem = firstItem.IdSubsystem;
|
||||
DateTimeOffset dateBegin = firstItem.Date;
|
||||
float? depthStart = firstItem.Depth;
|
||||
for (int i = 1; i < telemetryOpearationSaubSubsystems.Count; i++)
|
||||
{
|
||||
if (telemetryOpearationSaubSubsystems[i].IdSubsystem != idSubsystem)
|
||||
{
|
||||
var operationTimeItem = new SubsystemOperationTime()
|
||||
{
|
||||
IdTelemetry = idTelemetry,
|
||||
DateStart = dateBegin,
|
||||
IdSubsystem = telemetryOpearationSaubSubsystems[i - 1].IdSubsystem,
|
||||
DateEnd = telemetryOpearationSaubSubsystems[i].Date,
|
||||
DepthStart = depthStart,
|
||||
DepthEnd = telemetryOpearationSaubSubsystems[i].Depth
|
||||
|
||||
};
|
||||
dateBegin = telemetryOpearationSaubSubsystems[i].Date;
|
||||
depthStart = telemetryOpearationSaubSubsystems[i].Depth;
|
||||
idSubsystem = telemetryOpearationSaubSubsystems[i].IdSubsystem;
|
||||
resultSubsystemOperationTime.Add(operationTimeItem);
|
||||
|
||||
}
|
||||
}
|
||||
return resultSubsystemOperationTime;
|
||||
return subsystemOperationTime;
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<SubsystemOperationTime>?> OperationTimeSpinAsync(int idTelemetry, DateTimeOffset begin, IAsbCloudDbContext db, CancellationToken token)
|
||||
{
|
||||
Predicate<int> isSubsystemTorqueState = (int state) => state == 7;
|
||||
Predicate<short> isSubsystemTorqueMode = (short mode) => (mode & 2) > 0;
|
||||
Predicate<int> isSubsystemSpin = (int state) => state != 0 & state != 6 & state != 7;
|
||||
var operationTimeSpinWithDepth =
|
||||
$"select tspin.\"date\", tspin.\"mode\", tspin.\"state\", tsaub.\"well_depth\"" +
|
||||
$" from (select \"date\" ,\"mode\" ,lag(mode, 1) over (order by \"date\") as mode_pre, state , " +
|
||||
$"lag(state, 1) over (order by \"date\") as state_pre from t_telemetry_data_spin where id_telemetry = @idTelemetry and date >= @begin) as tspin " +
|
||||
$"join (select \"date\", well_depth from t_telemetry_data_saub where id_telemetry = @idTelemetry and date >= @begin) as tsaub " +
|
||||
$"on EXTRACT(EPOCH from tspin.date) = EXTRACT(EPOCH from tsaub.date) " +
|
||||
$"where mode!=mode_pre or state != state_pre order by \"date\";";
|
||||
using var command = db.Database.GetDbConnection().CreateCommand();
|
||||
command.CommandText = operationTimeSpinWithDepth;
|
||||
var telemetry = new NpgsqlParameter("@idTelemetry", idTelemetry);
|
||||
command.Parameters.Add(telemetry);
|
||||
var dateStart = new NpgsqlParameter("@begin", begin);
|
||||
command.Parameters.Add(dateStart);
|
||||
db.Database.OpenConnection();
|
||||
using var result = await command.ExecuteReaderAsync(token);
|
||||
var telemetryOpearationSpinSubsystems = new List<SubsystemsSpinWithDepth>();
|
||||
if (result.HasRows)
|
||||
static int? GetSubsytemId(short mode, int state)
|
||||
{
|
||||
if (state == 7 && (mode & 2) > 0)
|
||||
return idSubsytemTorqueMaster;
|
||||
|
||||
if (state != 0 & state != 6 & state != 7)
|
||||
return idSubsytemSpinMaster;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var query =
|
||||
$"select " +
|
||||
$" tspin.date, " +
|
||||
$" tspin.mode, " +
|
||||
$" tspin.state, " +
|
||||
$" tsaub.well_depth " +
|
||||
$"from ( " +
|
||||
$" select " +
|
||||
$" date, " +
|
||||
$" mode, " +
|
||||
$" lag(mode, 1) over (order by date) as mode_pre, " +
|
||||
$" state, " +
|
||||
$" lag(state, 1) over (order by date) as state_pre " +
|
||||
$" from t_telemetry_data_spin " +
|
||||
$" where id_telemetry = @idTelemetry and date >= @begin" +
|
||||
$" order by date ) as tspin " +
|
||||
$"left outer join ( " +
|
||||
$" select " +
|
||||
$" date, " +
|
||||
$" well_depth " +
|
||||
$" from t_telemetry_data_saub " +
|
||||
$" where id_telemetry = @idTelemetry and date >= @begin) as tsaub " +
|
||||
$"on EXTRACT(EPOCH from tspin.date) = EXTRACT(EPOCH from tsaub.date) " +
|
||||
$"where mode_pre is null or state_pre is null or mode != mode_pre or state != state_pre " +
|
||||
$"order by date;";
|
||||
|
||||
var idTelemetryParam = new NpgsqlParameter("@idTelemetry", idTelemetry);
|
||||
var beginParam = new NpgsqlParameter("@begin", begin);
|
||||
|
||||
await db.Database.OpenConnectionAsync(token);
|
||||
using var command = db.Database.GetDbConnection().CreateCommand();
|
||||
command.CommandText = query;
|
||||
command.Parameters.Add(idTelemetryParam);
|
||||
command.Parameters.Add(beginParam);
|
||||
|
||||
using var result = await command.ExecuteReaderAsync(token);
|
||||
|
||||
var subsystemOperationTime = new List<SubsystemOperationTime>(32);
|
||||
|
||||
if (result.Read())
|
||||
{
|
||||
var mode = result.GetFieldValue<short>(1);
|
||||
var state = result.GetFieldValue<int>(2);
|
||||
var idSubsystem = GetSubsytemId(mode, state);
|
||||
var dateStart = result.GetFieldValue<DateTimeOffset>(0);
|
||||
var depthStart = result.GetFieldValue<float?>(3);
|
||||
|
||||
while (result.Read())
|
||||
{
|
||||
var itemEntity = new SubsystemsSpinWithDepth()
|
||||
var dateEnd = result.GetFieldValue<DateTimeOffset>(0);
|
||||
var depthEnd = result.GetFieldValue<float?>(3);
|
||||
if (idSubsystem.HasValue)
|
||||
{
|
||||
Date = result.GetFieldValue<DateTimeOffset>(0),
|
||||
Mode = result.GetFieldValue<short>(1),
|
||||
State = result.GetFieldValue<int>(2),
|
||||
Depth = result.GetFieldValue<float>(3)
|
||||
};
|
||||
int? subsystemId = isSubsystemTorqueState(itemEntity.State) && isSubsystemTorqueMode(itemEntity.Mode)
|
||||
? idSubsytemTorqueMaster
|
||||
: isSubsystemSpin(itemEntity.State)
|
||||
? idSubsytemSpinMaster
|
||||
: 0;
|
||||
if (subsystemId.HasValue)
|
||||
{
|
||||
itemEntity.IdSubsystem = subsystemId.Value;
|
||||
telemetryOpearationSpinSubsystems.Add(itemEntity);
|
||||
var operationTimeItem = new SubsystemOperationTime()
|
||||
{
|
||||
IdTelemetry = idTelemetry,
|
||||
IdSubsystem = idSubsystem.Value,
|
||||
DateStart = dateStart,
|
||||
DateEnd = dateEnd,
|
||||
DepthStart = depthStart,
|
||||
DepthEnd = depthEnd
|
||||
};
|
||||
subsystemOperationTime.Add(operationTimeItem);
|
||||
}
|
||||
mode = result.GetFieldValue<short>(1);
|
||||
state = result.GetFieldValue<int>(2);
|
||||
idSubsystem = GetSubsytemId(mode, state);
|
||||
dateStart = dateEnd;
|
||||
depthStart = depthEnd;
|
||||
}
|
||||
}
|
||||
var resultSubsystemOperationTime = new List<SubsystemOperationTime>();
|
||||
var firstItem = telemetryOpearationSpinSubsystems.FirstOrDefault();
|
||||
if (firstItem is null)
|
||||
return null;
|
||||
int idSubsystem = firstItem.IdSubsystem;
|
||||
DateTimeOffset dateBegin = firstItem.Date;
|
||||
float? depthStart = firstItem.Depth;
|
||||
for (int i = 1; i < telemetryOpearationSpinSubsystems.Count; i++)
|
||||
{
|
||||
if (telemetryOpearationSpinSubsystems[i].IdSubsystem != idSubsystem)
|
||||
{
|
||||
var operationTimeItem = new SubsystemOperationTime()
|
||||
{
|
||||
IdTelemetry = idTelemetry,
|
||||
DateStart = dateBegin,
|
||||
IdSubsystem = telemetryOpearationSpinSubsystems[i - 1].IdSubsystem,
|
||||
DateEnd = telemetryOpearationSpinSubsystems[i].Date,
|
||||
DepthStart = depthStart,
|
||||
DepthEnd = telemetryOpearationSpinSubsystems[i].Depth
|
||||
};
|
||||
dateBegin = telemetryOpearationSpinSubsystems[i].Date;
|
||||
depthStart = telemetryOpearationSpinSubsystems[i].Depth;
|
||||
idSubsystem = telemetryOpearationSpinSubsystems[i].IdSubsystem;
|
||||
if (telemetryOpearationSpinSubsystems[i - 1].IdSubsystem != 0)
|
||||
{
|
||||
resultSubsystemOperationTime.Add(operationTimeItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultSubsystemOperationTime;
|
||||
return subsystemOperationTime;
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
|
@ -29,6 +29,8 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
this.wellService = wellService;
|
||||
this.subsystemService = subsystemService;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<int> DeleteAsync(SubsystemOperationTimeRequest request, CancellationToken token)
|
||||
{
|
||||
var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
|
||||
@ -41,39 +43,40 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
return await db.SaveChangesAsync(token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IEnumerable<SubsystemOperationTimeDto>?> GetOperationTimeAsync(SubsystemOperationTimeRequest request, CancellationToken token)
|
||||
{
|
||||
var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
|
||||
if (well?.IdTelemetry is null || well.Timezone is null)
|
||||
return null;
|
||||
|
||||
var query = BuildQuery(request);
|
||||
|
||||
if (query is null)
|
||||
return null;
|
||||
|
||||
IEnumerable<SubsystemOperationTime> data = await query.ToListAsync(token);
|
||||
|
||||
if (request.SelectMode == SubsystemOperationTimeRequest.SelectModeInner)
|
||||
{
|
||||
if (request.GtDate is not null)
|
||||
query = query.Where(o => o.DateStart >= request.GtDate.Value || o.DateEnd >= request.GtDate.Value);
|
||||
data = data.Where(o => o.DateStart >= request.GtDate.Value);
|
||||
|
||||
if (request.LtDate is not null)
|
||||
query = query.Where(o => o.DateEnd <= request.LtDate.Value || o.DateStart <= request.LtDate.Value);
|
||||
data = data.Where(o => o.DateEnd <= request.LtDate.Value);
|
||||
}
|
||||
if (request.SelectMode == SubsystemOperationTimeRequest.SelectModeTrim)
|
||||
{
|
||||
if (!request.GtDate.HasValue)
|
||||
throw new ArgumentNullException(nameof(request.GtDate));
|
||||
var begin = request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
if (!request.LtDate.HasValue)
|
||||
throw new ArgumentNullException(nameof(request.LtDate));
|
||||
var end = request.LtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
IEnumerable<SubsystemOperationTime>? data = query.ToList();
|
||||
data = Trim(data, begin, end);
|
||||
if (data is not null)
|
||||
return data.Select(o => Convert(o, well));
|
||||
return null;
|
||||
else if (request.SelectMode == SubsystemOperationTimeRequest.SelectModeTrim)
|
||||
{
|
||||
var begin = request.GtDate?.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
var end = request.LtDate?.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
data = Trim(data, begin, end);
|
||||
}
|
||||
var dtos = query.Select(o => Convert(o, well));
|
||||
|
||||
var dtos = data.Select(o => Convert(o, well));
|
||||
return dtos;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IEnumerable<SubsystemStatDto>?> GetStatAsync(SubsystemOperationTimeRequest request, CancellationToken token)
|
||||
{
|
||||
request.SelectMode = SubsystemOperationTimeRequest.SelectModeTrim;
|
||||
@ -83,110 +86,104 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
var statList = CalcStat(data, request);
|
||||
return statList;
|
||||
}
|
||||
private IEnumerable<SubsystemOperationTime>? Trim(IEnumerable<SubsystemOperationTime>? data, DateTimeOffset gtDate, DateTimeOffset ltDate)
|
||||
|
||||
private static IEnumerable<SubsystemOperationTime> Trim(IEnumerable<SubsystemOperationTime> data, DateTimeOffset? gtDate, DateTimeOffset? ltDate)
|
||||
{
|
||||
if (data is null)
|
||||
return null;
|
||||
var ItemsNormal = data.Where(q =>
|
||||
(q.DateStart >= gtDate) && (q.DateEnd <= ltDate)).ToList();
|
||||
var itemsToTrim = data.Where(q =>
|
||||
q.DateStart < gtDate || ltDate < q.DateEnd)
|
||||
.Select(o => new SubsystemOperationTime
|
||||
var items = data.Select((item) =>
|
||||
{
|
||||
if (gtDate.HasValue && item.DateStart < gtDate.Value)
|
||||
{
|
||||
Id = o.Id,
|
||||
DateStart = gtDate < o.DateStart ? o.DateStart : gtDate,
|
||||
DateEnd = ltDate > o.DateEnd ? o.DateEnd : ltDate,
|
||||
IdSubsystem = o.IdSubsystem,
|
||||
IdTelemetry = o.IdTelemetry,
|
||||
DepthStart = gtDate > o.DateEnd ? o.DepthStart : null,
|
||||
DepthEnd = ltDate < o.DateStart ? o.DepthEnd : null,
|
||||
Subsystem = o.Subsystem,
|
||||
Telemetry = o.Telemetry
|
||||
})
|
||||
.ToList();
|
||||
ItemsNormal.AddRange(itemsToTrim);
|
||||
return ItemsNormal.OrderBy(o => o.DateStart).ToList();
|
||||
item.DateStart = gtDate.Value;
|
||||
item.DepthStart = null;
|
||||
}
|
||||
if (ltDate.HasValue && item.DateEnd > ltDate.Value)
|
||||
{
|
||||
item.DateEnd = ltDate.Value;
|
||||
item.DepthEnd = null;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
private IEnumerable<SubsystemStatDto> CalcStat(IEnumerable<SubsystemOperationTimeDto> listOperationTimeSubsystems, SubsystemOperationTimeRequest request)
|
||||
|
||||
private IEnumerable<SubsystemStatDto> CalcStat(IEnumerable<SubsystemOperationTimeDto> dtos, SubsystemOperationTimeRequest request)
|
||||
{
|
||||
var result = new List<SubsystemStatDto>();
|
||||
var groupedDataSubsystems = listOperationTimeSubsystems
|
||||
.GroupBy(x => x.IdSubsystem);
|
||||
var periodGroupTotal = groupedDataSubsystems
|
||||
.Sum(g => g.Sum(o=> (o.DateEnd - o.DateStart).TotalHours));
|
||||
var gtDate = request.GtDate ?? listOperationTimeSubsystems.Min(d => d.DateStart);
|
||||
var ltDate = request.LtDate ?? listOperationTimeSubsystems.Max(d => d.DateEnd);
|
||||
var periodRequest = listOperationTimeSubsystems
|
||||
.Sum(o => (o.DateEnd - o.DateStart).TotalHours);
|
||||
foreach (var item in groupedDataSubsystems)
|
||||
{
|
||||
var periodGroup = item.Sum(g => (g.DateEnd - g.DateStart).TotalHours);
|
||||
int idSubsystem = item.First().IdSubsystem;
|
||||
var groupedDataSubsystems = dtos
|
||||
.GroupBy(o => o.IdSubsystem);
|
||||
|
||||
var periodGroupTotal = dtos.Sum(o => (o.DateEnd - o.DateStart).TotalHours);
|
||||
|
||||
var gtDate = request.GtDate ?? dtos.Min(o => o.DateStart);
|
||||
var ltDate = request.LtDate ?? dtos.Max(o => o.DateEnd);
|
||||
|
||||
var periodRequest = (ltDate - gtDate).TotalHours;
|
||||
|
||||
var result = groupedDataSubsystems.Select(item =>
|
||||
{
|
||||
var periodGroup = item.Sum(o => (o.DateEnd - o.DateStart).TotalHours);
|
||||
var subsystemStat = new SubsystemStatDto()
|
||||
{
|
||||
IdSubsystem = idSubsystem,
|
||||
SubsystemName = subsystemService.GetOrDefault(idSubsystem)?.Name ?? "unknown",
|
||||
UsedTimeHours =periodGroup,
|
||||
KUsage = 1d*periodGroup / periodRequest,
|
||||
K2 = 1d*periodGroup / periodGroupTotal,
|
||||
IdSubsystem = item.Key,
|
||||
SubsystemName = subsystemService.GetOrDefault(item.Key)?.Name ?? "unknown",
|
||||
UsedTimeHours = periodGroup,
|
||||
KUsage = 1d * periodGroup / periodRequest,
|
||||
K2 = 1d * periodGroup / periodGroupTotal,
|
||||
};
|
||||
result.Add(subsystemStat);
|
||||
}
|
||||
return subsystemStat;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private IQueryable<SubsystemOperationTime>? BuildQuery(SubsystemOperationTimeRequest request)
|
||||
{
|
||||
if (request.SelectMode > 0 && request.GtDate is null && request.LtDate is null)
|
||||
return null;
|
||||
|
||||
var well = wellService.GetOrDefault(request.IdWell);
|
||||
if (well?.IdTelemetry is null || well.Timezone is null)
|
||||
return null;
|
||||
|
||||
var query = db.SubsystemOperationTimes
|
||||
.Include(o => o.Subsystem)
|
||||
.Where(o => o.IdTelemetry == well.IdTelemetry);
|
||||
DateTimeOffset gtDateWellTime;
|
||||
DateTimeOffset ltDateWellTime;
|
||||
.Include(o => o.Subsystem)
|
||||
.Where(o => o.IdTelemetry == well.IdTelemetry)
|
||||
.AsNoTracking();
|
||||
|
||||
if (request.IdsSubsystems?.Any() == true)
|
||||
query = query.Where(o => request.IdsSubsystems.Contains(o.IdSubsystem));
|
||||
|
||||
if (request.GtDate is not null && request.LtDate is not null)
|
||||
// # Dates range condition
|
||||
// [GtDate LtDate]
|
||||
// [DateStart DateEnd] [DateStart DateEnd]
|
||||
if (request.GtDate.HasValue)
|
||||
{
|
||||
gtDateWellTime = request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
ltDateWellTime = request.LtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
//query = query.Where(o => (o.DateStart >= gtDateWellTime)
|
||||
//|| (o.DateEnd <= ltDateWellTime));
|
||||
query = query.Where(q =>
|
||||
(q.DateStart < gtDateWellTime && q.DateEnd <= ltDateWellTime && q.DateEnd > gtDateWellTime) ||
|
||||
(q.DateStart >= gtDateWellTime && q.DateEnd > ltDateWellTime && q.DateStart < ltDateWellTime) ||
|
||||
(q.DateStart < gtDateWellTime && q.DateEnd > ltDateWellTime) ||
|
||||
(q.DateStart >= gtDateWellTime && q.DateEnd <= ltDateWellTime));
|
||||
}
|
||||
else if (request.GtDate is not null)
|
||||
{
|
||||
gtDateWellTime = request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
query = query.Where(o => o.DateStart >= gtDateWellTime);
|
||||
DateTimeOffset gtDate = request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
query = query.Where(o => o.DateEnd >= gtDate);
|
||||
}
|
||||
|
||||
else if (request.LtDate is not null)
|
||||
if (request.LtDate.HasValue)
|
||||
{
|
||||
ltDateWellTime = request.LtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
query = query.Where(o => o.DateEnd <= ltDateWellTime);
|
||||
DateTimeOffset ltDate = request.LtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours);
|
||||
query = query.Where(o => o.DateStart <= ltDate);
|
||||
}
|
||||
|
||||
|
||||
if (request.GtDepth is not null)
|
||||
query = query.Where(o => o.DepthStart >= request.GtDepth.Value);
|
||||
|
||||
if (request.LtDepth is not null)
|
||||
query = query.Where(o => o.DepthEnd <= request.LtDepth.Value);
|
||||
|
||||
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);
|
||||
@ -198,7 +195,8 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
|
||||
return query;
|
||||
}
|
||||
private SubsystemOperationTimeDto Convert(SubsystemOperationTime operationTime, WellDto well)
|
||||
|
||||
private static SubsystemOperationTimeDto Convert(SubsystemOperationTime operationTime, WellDto well)
|
||||
{
|
||||
var dto = operationTime.Adapt<SubsystemOperationTimeDto>();
|
||||
dto.DateStart = operationTime.DateStart.ToRemoteDateTime(well.Timezone.Hours);
|
||||
|
@ -27,21 +27,17 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
var well = await wellService.GetOrDefaultAsync(idWell, token);
|
||||
if (well?.IdTelemetry is null || well.Timezone is null)
|
||||
return null;
|
||||
var wellSubsystem = await dbContext.SubsystemOperationTimes
|
||||
var entities = await dbContext.SubsystemOperationTimes
|
||||
.Include(e => e.Subsystem)
|
||||
.AsNoTracking()
|
||||
.Where(o => o.IdTelemetry == well.IdTelemetry)
|
||||
.DistinctBy(o => o.IdSubsystem)
|
||||
.Select(d => Convert( new ()
|
||||
{
|
||||
Id = d.Subsystem.Id,
|
||||
Name = d.Subsystem.Name,
|
||||
Description = d.Subsystem.Description,
|
||||
|
||||
}))
|
||||
.ToListAsync(token);
|
||||
return wellSubsystem;
|
||||
.Select(o => o.Subsystem)
|
||||
.Distinct()
|
||||
.ToArrayAsync(token);
|
||||
var dtos = entities.Select(e => e.Adapt<SubsystemDto>());
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SubsystemDto>?> GetSubsystemAsync(int? idWell, CancellationToken token)
|
||||
{
|
||||
if (idWell.HasValue)
|
||||
@ -52,11 +48,6 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
var subsystem = await GetAllAsync(token);
|
||||
return subsystem;
|
||||
}
|
||||
new private static SubsystemDto Convert(Subsystem subsystem)
|
||||
{
|
||||
var dto = subsystem.Adapt<SubsystemDto>();
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
}
|
||||
|
@ -19,5 +19,5 @@ namespace AsbCloudWebApi.Controllers.Subsystems
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,11 @@ namespace AsbCloudWebApi.Controllers.Subsystems
|
||||
{
|
||||
private readonly ISubsystemOperationTimeService subsystemOperationTimeService;
|
||||
private readonly IWellService wellService;
|
||||
private readonly ICrudService<SubsystemDto> subsystemServiceCrud;
|
||||
private readonly ISubsystemService subsystemService;
|
||||
public SubsystemOperationTimeController(ISubsystemOperationTimeService subsystemOperationTimeService, IWellService wellService, ICrudService<SubsystemDto> subsystemServiceCrud, ISubsystemService subsystemService)
|
||||
public SubsystemOperationTimeController(ISubsystemOperationTimeService subsystemOperationTimeService, IWellService wellService, ISubsystemService subsystemService)
|
||||
{
|
||||
this.subsystemOperationTimeService = subsystemOperationTimeService;
|
||||
this.wellService = wellService;
|
||||
this.subsystemServiceCrud = subsystemServiceCrud;
|
||||
this.subsystemService = subsystemService;
|
||||
}
|
||||
/// <summary>
|
||||
@ -53,8 +51,8 @@ namespace AsbCloudWebApi.Controllers.Subsystems
|
||||
if (idWell.HasValue)
|
||||
if (!await UserHasAccesToWellAsync(idWell.Value, token))
|
||||
return Forbid();
|
||||
var result = await subsystemService.GetSubsystemAsync(idWell, token);
|
||||
return Ok(result);
|
||||
var result = await subsystemService.GetSubsystemAsync(idWell, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
Loading…
Reference in New Issue
Block a user