WellMapInfoDto разделен на части.

1-я (медленная) заполняется в фоновом процессе и кешируется, 2-я при запросе из кешей телеметрии.
This commit is contained in:
ngfrolov 2023-06-29 15:54:54 +05:00
parent 968f6db348
commit 69f5639571
Signed by untrusted user who does not match committer: ng.frolov
GPG Key ID: E99907A0357B29A7
6 changed files with 125 additions and 64 deletions

View File

@ -15,7 +15,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsbCloudDb", "AsbCloudDb\As
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsbCloudWebApi.Tests", "AsbCloudWebApi.Tests\AsbCloudWebApi.Tests.csproj", "{9CF6FBB1-9AF5-45AB-A521-24F11A79B540}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsbCloudWebApi.Tests", "AsbCloudWebApi.Tests\AsbCloudWebApi.Tests.csproj", "{9CF6FBB1-9AF5-45AB-A521-24F11A79B540}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignalRTestClient", "SignalRTestClient\SignalRTestClient.csproj", "{E6B97963-4CEA-47B6-A0C8-625FFA9B7D69}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SignalRTestClient", "SignalRTestClient\SignalRTestClient.csproj", "{E6B97963-4CEA-47B6-A0C8-625FFA9B7D69}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -1,7 +1,44 @@
using System; using AsbCloudApp.Data.SAUB;
using System;
namespace AsbCloudApp.Data namespace AsbCloudApp.Data
{ {
/// <summary>
/// Инфо о скважине для отображения на карте последними данными телеметрии
/// </summary>
public class WellMapInfoWithTelemetryStat : WellMapInfoDto
{
/// <summary>
/// Последние полученные данные от АПД
/// </summary>
public TelemetryDataSaubDto? LastDataSaub { get; set; }
/// <summary>
/// Последние полученные данные от Осцилляции
/// </summary>
public TelemetryDataSpinDto? LastDataSpin { get; set; }
/// <summary>
/// Дата полседнего получения данных от ННБ
/// </summary>
public DateTime? LastDataDdsDate { get; set; }
/// <summary>
/// Дата полседнего получения данных от ГТИ
/// </summary>
public DateTime? LastDataGtrDate { get; set; }
/// <summary>
/// Дата полседнего получения данных от СКПБ
/// </summary>
public DateTime? LastDataDpcsDate { get; set; }
/// <summary>
/// Дата полседнего получения данных от станции контроля параметров цементирования (СКЦ)
/// </summary>
public DateTime? LastDataCpmsDate { get; set; }
}
/// <summary> /// <summary>
/// Инфо о скважине для отображения на карте /// Инфо о скважине для отображения на карте
/// </summary> /// </summary>
@ -14,19 +51,6 @@ namespace AsbCloudApp.Data
/// </summary> /// </summary>
public int IdState { get; set; } public int IdState { get; set; }
/// <summary>
/// Режим АПД:
/// 0 - "РУЧНОЙ"
/// 1 - "БУРЕНИЕ В РОТОРЕ"
/// 2 - "ПРОРАБОТКА"
/// 3 - "БУРЕНИЕ В СЛАЙДЕ"
/// 4 - "СПУСК СПО"
/// 5 - "ПОДЪЕМ СПО"
/// 6 - "ПОДЪЕМ С ПРОРАБОТКОЙ"
/// 10 - "БЛОКИРОВКА"
/// </summary>
public int IdMode { get; set; }
/// <summary> /// <summary>
/// Коэф-т использования автоподачи долота (суммарный ротор + слайд) /// Коэф-т использования автоподачи долота (суммарный ротор + слайд)
/// </summary> /// </summary>
@ -42,36 +66,6 @@ namespace AsbCloudApp.Data
/// </summary> /// </summary>
public double TorqueKUsage { get; set; } public double TorqueKUsage { get; set; }
/// <summary>
/// Состояние МСЕ
/// </summary>
public double IdStateMse { get; set; }
/// <summary>
/// Дата/время получения данных от системы АПД
/// </summary>
public DateTime LastTelemetrySaubDate { get; set; }
/// <summary>
/// Дата/время получения данных от системы осцилляции
/// </summary>
public DateTime LastTelemetrySpinDate { get; set; }
/// <summary>
/// Дата/время получения данных от ННБ
/// </summary>
public DateTime LastTelemetryDdsDate { get; set; }
/// <summary>
/// Дата/время получения данных от ГТИ
/// </summary>
public DateTime LastTelemetryGtrDate { get; set; }
/// <summary>
/// Дата/время получения данных от СКПБ
/// </summary>
public DateTime LastTelemetryDpcsDate { get; set; }
/// <summary> /// <summary>
/// <para>Дата начала первой фактической операции</para> /// <para>Дата начала первой фактической операции</para>
/// <para>Используется как дата начала бурения</para> /// <para>Используется как дата начала бурения</para>

View File

@ -136,6 +136,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<ILimitingParameterService, LimitingParameterService>(); services.AddTransient<ILimitingParameterService, LimitingParameterService>();
services.AddTransient<IProcessMapReportMakerService, ProcessMapReportMakerService>(); services.AddTransient<IProcessMapReportMakerService, ProcessMapReportMakerService>();
services.AddTransient<IProcessMapReportService, ProcessMapReportService>(); services.AddTransient<IProcessMapReportService, ProcessMapReportService>();
services.AddTransient<WellInfoService>();
services.AddTransient<TrajectoryService>(); services.AddTransient<TrajectoryService>();

View File

@ -1,6 +1,7 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap; using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Data.SAUB; using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Data.WITS;
using AsbCloudApp.Repositories; using AsbCloudApp.Repositories;
using AsbCloudApp.Requests; using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
@ -18,18 +19,36 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services namespace AsbCloudInfrastructure.Services
{ {
public class WellInfoService public class WellInfoService
{ {
class WellMapInfoWithComanies : WellMapInfoDto class WellMapInfoWithComanies : WellMapInfoDto
{ {
public int? IdTelemetry { get; set; }
public IEnumerable<int> IdsCompanies { get; set; } = null!; public IEnumerable<int> IdsCompanies { get; set; } = null!;
} }
private const string workId = "Well statistics update"; private const string workId = "Well statistics update";
private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30); private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30);
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache;
private readonly TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache;
private readonly IWitsRecordRepository<Record7Dto> witsRecord7Repository;
private readonly IWitsRecordRepository<Record1Dto> witsRecord1Repository;
private static IEnumerable<WellMapInfoWithComanies> WellMapInfo = Enumerable.Empty<WellMapInfoWithComanies>(); private static IEnumerable<WellMapInfoWithComanies> WellMapInfo = Enumerable.Empty<WellMapInfoWithComanies>();
public WellInfoService(
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache,
TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache,
IWitsRecordRepository<Record7Dto> witsRecord7Repository,
IWitsRecordRepository<Record1Dto> witsRecord1Repository)
{
this.telemetryDataSaubCache = telemetryDataSaubCache;
this.telemetryDataSpinCache = telemetryDataSpinCache;
this.witsRecord7Repository = witsRecord7Repository;
this.witsRecord1Repository = witsRecord1Repository;
}
public static WorkPeriodic MakeWork() public static WorkPeriodic MakeWork()
{ {
@ -75,23 +94,22 @@ namespace AsbCloudInfrastructure.Services
WellMapInfo = activeWells.Select(well => { WellMapInfo = activeWells.Select(well => {
var wellMapInfo = well.Adapt<WellMapInfoWithComanies>(); var wellMapInfo = well.Adapt<WellMapInfoWithComanies>();
var wellOperationsStat = operationsStat.FirstOrDefault(s => s.Id == well.Id); wellMapInfo.IdState = well.IdState;
var wellLastFactSection = wellOperationsStat?.Sections.LastOrDefault(s => s.Fact is not null);
double? currentDepth = null; double? currentDepth = null;
double? planTotalDepth = null;
DateTime lastTelemetryDate = default;
if (well.IdTelemetry.HasValue) if (well.IdTelemetry.HasValue)
{ {
wellMapInfo.IdTelemetry = well.IdTelemetry.Value;
var lastSaubTelemetry = telemetryDataSaubCache.GetLastOrDefault(well.IdTelemetry.Value); var lastSaubTelemetry = telemetryDataSaubCache.GetLastOrDefault(well.IdTelemetry.Value);
if(lastSaubTelemetry is not null) if(lastSaubTelemetry is not null)
{ {
currentDepth = lastSaubTelemetry.WellDepth; currentDepth = lastSaubTelemetry.WellDepth;
lastTelemetryDate = lastSaubTelemetry.DateTime;
} }
} }
var wellOperationsStat = operationsStat.FirstOrDefault(s => s.Id == well.Id);
var wellLastFactSection = wellOperationsStat?.Sections.LastOrDefault(s => s.Fact is not null);
currentDepth ??= wellLastFactSection?.Fact?.WellDepthEnd; currentDepth ??= wellLastFactSection?.Fact?.WellDepthEnd;
var wellProcessMaps = processMaps var wellProcessMaps = processMaps
@ -111,9 +129,16 @@ namespace AsbCloudInfrastructure.Services
idSection ??= welllProcessMap?.IdWellSectionType; idSection ??= welllProcessMap?.IdWellSectionType;
} }
double? planTotalDepth = null;
planTotalDepth = wellDepthByProcessMap.FirstOrDefault(p => p.Id == well.Id)?.DepthEnd; planTotalDepth = wellDepthByProcessMap.FirstOrDefault(p => p.Id == well.Id)?.DepthEnd;
planTotalDepth ??= wellOperationsStat?.Total.Plan?.WellDepthEnd; planTotalDepth ??= wellOperationsStat?.Total.Plan?.WellDepthEnd;
wellMapInfo.FirstFactOperationDateStart = wellOperationsStat?.Total.Fact?.Start
?? wellOperationsStat?.Total.Plan?.Start;
wellMapInfo.LastPredictOperationDateEnd = wellOperationsStat?.Total.Plan?.End?
.AddDays(wellOperationsStat?.TvdLagDays ?? 0d);
wellMapInfo.WellDepth = new() wellMapInfo.WellDepth = new()
{ {
Plan = planTotalDepth, Plan = planTotalDepth,
@ -135,17 +160,51 @@ namespace AsbCloudInfrastructure.Services
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?.SubsystemAKB?.KUsage ?? 0d;
wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d; wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d;
wellMapInfo.TorqueKUsage = wellSubsystemStat?.SubsystemTorqueMaster?.KUsage ?? 0d;
wellMapInfo.TvdLagPercent = wellOperationsStat?.TvdLagDays ?? 0d; wellMapInfo.TvdLagPercent = wellOperationsStat?.TvdLagDays ?? 0d;
wellMapInfo.IdsCompanies = well.Companies.Select(c => c.Id); wellMapInfo.IdsCompanies = well.Companies.Select(c => c.Id);
return wellMapInfo; return wellMapInfo;
}).ToArray(); }).ToArray();
} }
public static IEnumerable<WellMapInfoDto> Where(Func<WellMapInfoDto, bool> predicate) private WellMapInfoWithTelemetryStat Convert(WellMapInfoWithComanies wellInfo)
=> WellMapInfo.Where(predicate); {
var result = wellInfo.Adapt<WellMapInfoWithTelemetryStat>();
if (wellInfo.IdTelemetry.HasValue)
{
result.LastDataSaub = telemetryDataSaubCache.GetLastOrDefault(wellInfo.IdTelemetry.Value);
result.LastDataSpin = telemetryDataSpinCache.GetLastOrDefault(wellInfo.IdTelemetry.Value);
result.LastDataDdsDate = GetLastOrDefaultDdsTelemetry(wellInfo.IdTelemetry.Value);
result.LastDataGtrDate = null;
result.LastDataDpcsDate = null;
result.LastDataDpcsDate = null;
}
public static WellMapInfoDto? FirstOrDefault(Func<WellMapInfoDto, bool> predicate) return result;
=> WellMapInfo.FirstOrDefault(predicate); }
private DateTime? GetLastOrDefaultDdsTelemetry(int idTelemetry)
{
var lastDdsRecord1Date = witsRecord1Repository.GetLastOrDefault(idTelemetry)?.DateTime;
var lastDdsRecord7Date = witsRecord7Repository.GetLastOrDefault(idTelemetry)?.DateTime;
if (lastDdsRecord1Date.HasValue && lastDdsRecord7Date.HasValue)
if (lastDdsRecord1Date.Value > lastDdsRecord7Date.Value)
return lastDdsRecord1Date.Value;
else
return lastDdsRecord7Date.Value;
return lastDdsRecord1Date ?? lastDdsRecord7Date;
}
public WellMapInfoWithTelemetryStat? FirstOrDefault(Func<WellMapInfoDto, bool> predicate)
{
var first = WellMapInfo.FirstOrDefault(predicate);
if (first is WellMapInfoWithComanies wellMapInfoWithComanies)
return Convert(wellMapInfoWithComanies);
return null;
}
} }
} }

View File

@ -16,12 +16,12 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services namespace AsbCloudInfrastructure.Services
{ {
public class WellService : CrudCacheRepositoryBase<WellDto, Well>, IWellService public class WellService : CrudCacheRepositoryBase<WellDto, Well>, IWellService
{ {
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;
private readonly ICrudRepository<CompanyTypeDto> companyTypesService; private readonly ICrudRepository<CompanyTypeDto> companyTypesService;
private readonly ITimezoneService timezoneService; private readonly ITimezoneService timezoneService;
private readonly WellInfoService wellInfoService;
private readonly IWellOperationRepository wellOperationRepository; private readonly IWellOperationRepository wellOperationRepository;
public ITelemetryService TelemetryService => telemetryService; public ITelemetryService TelemetryService => telemetryService;
@ -35,12 +35,12 @@ namespace AsbCloudInfrastructure.Services
.Include(w => w.RelationCompaniesWells) .Include(w => w.RelationCompaniesWells)
.ThenInclude(r => r.Company); .ThenInclude(r => r.Company);
public WellService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService, ITimezoneService timezoneService) public WellService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService, ITimezoneService timezoneService, WellInfoService wellInfoService)
: base(db, memoryCache, MakeQueryWell) : base(db, memoryCache, MakeQueryWell)
{ {
this.telemetryService = telemetryService; this.telemetryService = telemetryService;
this.timezoneService = timezoneService; this.timezoneService = timezoneService;
this.wellInfoService = wellInfoService;
this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this); this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this);
companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache); companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache);
} }
@ -92,13 +92,10 @@ namespace AsbCloudInfrastructure.Services
Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude, Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude,
Wells = gCluster.Select(well => Wells = gCluster.Select(well =>
{ {
var dto = WellInfoService.FirstOrDefault(w => w.Id == well.Id); var dto = wellInfoService.FirstOrDefault(w => w.Id == well.Id);
dto ??= well.Adapt<WellMapInfoDto>(); dto ??= well.Adapt<WellMapInfoWithTelemetryStat>();
dto.Latitude ??= gCluster.Key.Latitude ?? gDeposit.Key.Latitude; dto.Latitude ??= gCluster.Key.Latitude ?? gDeposit.Key.Latitude;
dto.Longitude ??= gCluster.Key.Longitude ?? gDeposit.Key.Longitude; dto.Longitude ??= gCluster.Key.Longitude ?? gDeposit.Key.Longitude;
if (well.IdTelemetry is not null)
dto.LastTelemetryDate = telemetryService.GetDatesRange(well.IdTelemetry.Value).To;
return dto; return dto;
}), }),
}), }),

View File

@ -0,0 +1,10 @@
@baseUrl = http://127.0.0.1:5000
@contentType = application/json
@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE
@idWell = 1
GET {{baseUrl}}/api/well/wellTree
Content-Type: {{contentType}}
accept: */*
Authorization: {{auth}}