diff --git a/AsbCloudApp/Data/WellMapInfoDto.cs b/AsbCloudApp/Data/WellMapInfoDto.cs
index 967afcca..392d1877 100644
--- a/AsbCloudApp/Data/WellMapInfoDto.cs
+++ b/AsbCloudApp/Data/WellMapInfoDto.cs
@@ -2,6 +2,7 @@
namespace AsbCloudApp.Data
{
+#nullable enable
///
/// Инфо о скважине для отображения на карте
///
@@ -22,7 +23,7 @@ namespace AsbCloudApp.Data
///
/// Плановая и текущая глубина
///
- public PlanFactDto WellDepth { get; set; }
+ public PlanFactBase WellDepth { get; set; } = null!;
///
/// Отставание от ГГД, %
@@ -32,12 +33,12 @@ namespace AsbCloudApp.Data
///
/// Механическая скорость проходки, последней операции бурения
///
- public PlanFactDto ROP { get; set; }
+ public PlanFactBase ROP { get; set; } = null!;
///
/// Рейсовая скорость проходки, последнего рейса
///
- public PlanFactDto RaceSpeed { get; set; }
+ public PlanFactBase RaceSpeed { get; set; } = null!;
///
/// Процент использования АКБ
@@ -49,4 +50,5 @@ namespace AsbCloudApp.Data
///
public double SpinUsage { get; set; }
}
+#nullable disable
}
diff --git a/AsbCloudApp/Requests/WellRequest.cs b/AsbCloudApp/Requests/WellRequest.cs
index feb7259a..0d7d6e85 100644
--- a/AsbCloudApp/Requests/WellRequest.cs
+++ b/AsbCloudApp/Requests/WellRequest.cs
@@ -1,4 +1,6 @@
-namespace AsbCloudApp.Requests
+using System.Collections.Generic;
+
+namespace AsbCloudApp.Requests
{
#nullable enable
///
@@ -15,6 +17,11 @@
/// id состояния
///
public int? IdState { get; set; }
+
+ ///
+ /// Идентификаторы скважин
+ ///
+ public IEnumerable? Ids { get; set; }
}
#nullable disable
}
diff --git a/AsbCloudApp/Services/IWellService.cs b/AsbCloudApp/Services/IWellService.cs
index 6bd3da44..7ea8a20c 100644
--- a/AsbCloudApp/Services/IWellService.cs
+++ b/AsbCloudApp/Services/IWellService.cs
@@ -103,7 +103,6 @@ namespace AsbCloudApp.Services
///
///
///
-#warning GetWellTreeAsync(..) is dummy. Remove it before pullrequest.
Task> GetWellTreeAsync(int idCompany, CancellationToken token);
}
#nullable disable
diff --git a/AsbCloudApp/Services/Subsystems/ISubsystemOperationTimeService.cs b/AsbCloudApp/Services/Subsystems/ISubsystemOperationTimeService.cs
index 91b78023..8df7ee07 100644
--- a/AsbCloudApp/Services/Subsystems/ISubsystemOperationTimeService.cs
+++ b/AsbCloudApp/Services/Subsystems/ISubsystemOperationTimeService.cs
@@ -47,6 +47,7 @@ namespace AsbCloudApp.Services.Subsystems
///
///
Task GetDateRangeOperationTimeAsync(SubsystemOperationTimeRequest request, CancellationToken token);
+
///
/// Получение статистики по наработке подсистем по активным скважинам
///
@@ -56,6 +57,14 @@ namespace AsbCloudApp.Services.Subsystems
///
///
Task> GetStatByActiveWells(int idCompany, DateTime? gtDate, DateTime? ltDate, CancellationToken token);
+
+ ///
+ /// Получение статистики по наработке подсистем по активным скважинам
+ ///
+ ///
+ ///
+ ///
+ Task> GetStatByActiveWells(IEnumerable wellIds, CancellationToken token);
}
#nullable disable
}
diff --git a/AsbCloudDb/Model/Well.cs b/AsbCloudDb/Model/Well.cs
index 74345480..df011310 100644
--- a/AsbCloudDb/Model/Well.cs
+++ b/AsbCloudDb/Model/Well.cs
@@ -67,5 +67,8 @@ namespace AsbCloudDb.Model
[InverseProperty(nameof(DrillingProgramPart.Well))]
public virtual ICollection DrillingProgramParts { get; set; }
+
+ [InverseProperty(nameof(ProcessMap.Well))]
+ public virtual ICollection ProcessMaps { get; set; }
}
}
diff --git a/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs b/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs
index 280b0d92..f74100bf 100644
--- a/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs
+++ b/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs
@@ -187,20 +187,27 @@ namespace AsbCloudInfrastructure.Services.Subsystems
return depthIntervalSubsystem;
}
-
- private async Task> GetActiveWellsByCompany(int idCompany, CancellationToken token)
- {
- var listWell = await wellService.GetAsync(new() { IdCompany = idCompany }, token);
- var active = listWell.Where(w => w.IdState == 1);
- return active;
- }
///
public async Task> GetStatByActiveWells(int idCompany, DateTime? gtDate, DateTime? ltDate, CancellationToken token)
- {
- var wells = await GetActiveWellsByCompany(idCompany, 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> GetStatByActiveWells(IEnumerable 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> GetStatAsync(IEnumerable wells, DateTime? gtDate, DateTime? ltDate, CancellationToken token)
+ {
if (!wells.Any())
- return Enumerable.Empty();
+ return Enumerable.Empty();
var hoursOffset = wells
.FirstOrDefault(well => well.Timezone is not null)
@@ -209,7 +216,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
var beginUTC = gtDate.HasValue
? gtDate.Value.ToUtcDateTimeOffset(hoursOffset)
- :DateTime.Today.AddDays(-1).ToUtcDateTimeOffset(hoursOffset);
+ : DateTime.Today.AddDays(-1).ToUtcDateTimeOffset(hoursOffset);
var endUTC = ltDate.HasValue
? ltDate.Value.ToUtcDateTimeOffset(hoursOffset)
@@ -243,7 +250,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
var subsystemStat = idTelemetry > 0 && dtos.Any()
? CalcStat(dtos, (depthIntervalRotor, depthIntervalSlide))
: Enumerable.Empty();
-
+
return new SubsystemActiveWellStatDto
{
Well = well,
diff --git a/AsbCloudInfrastructure/Services/WellInfoService.cs b/AsbCloudInfrastructure/Services/WellInfoService.cs
new file mode 100644
index 00000000..b8b6128a
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/WellInfoService.cs
@@ -0,0 +1,154 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.ProcessMap;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using AsbCloudApp.Services.Subsystems;
+using AsbCloudDb.Model;
+using AsbCloudInfrastructure.Background;
+using Mapster;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudInfrastructure.Services
+{
+#nullable enable
+ public class WellInfoService
+ {
+ class WellMapInfoWithComanies : WellMapInfoDto
+ {
+ public IEnumerable IdsCompanies { get; set; } = null!;
+ }
+
+ private const string workId = "Well statistics update";
+ private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30);
+
+ private static IEnumerable WellMapInfo = Enumerable.Empty();
+
+ public static WorkPeriodic MakeWork()
+ {
+ var workPeriodic = new WorkPeriodic(workId, WorkAction, workPeriod)
+ {
+ Timeout = TimeSpan.FromMinutes(30)
+ };
+ return workPeriodic;
+ }
+
+ private static async Task WorkAction(string workName, IServiceProvider serviceProvider, CancellationToken token)
+ {
+ var db = serviceProvider.GetRequiredService();
+ var wellService = serviceProvider.GetRequiredService();
+ var operationsStatService = serviceProvider.GetRequiredService();
+ var processMapRepository = serviceProvider.GetRequiredService();
+ var subsystemOperationTimeService = serviceProvider.GetRequiredService();
+
+ var activeWells = await wellService.GetAsync(new() {IdState = 1}, token);
+
+ IEnumerable activeWellsIds = activeWells
+ .Select(w => w.Id);
+
+ var idTelemetries = activeWells
+ .Where(w => w.IdTelemetry != null)
+ .Select(t => t.IdTelemetry);
+
+ var lastTelemetryInfo = await db.TelemetryDataSaub
+ .Where(t => idTelemetries.Contains(t.IdTelemetry))
+ .Select(t => new
+ {
+ t.IdTelemetry,
+ t.WellDepth,
+ t.DateTime,
+ })
+ .GroupBy(t => t.IdTelemetry)
+ .Select(g => g.OrderByDescending(t => t.DateTime)
+ .First()
+ )
+ .AsNoTracking()
+ .ToArrayAsync(token);
+
+ var processMapRequests = activeWellsIds.Select(id => new ProcessMapRequest { IdWell = id });
+ var processMaps = await processMapRepository.GetProcessMapAsync(processMapRequests, token);
+
+ var wellDepthByProcessMap = processMaps
+ .GroupBy(p => p.IdWell)
+ .Select(g => new
+ {
+ Id = g.Key,
+ DepthEnd = g.Max(p => p.DepthEnd)
+ });
+
+ var operationsStat = await operationsStatService.GetWellsStatAsync(activeWellsIds, token);
+ var subsystemStat = await subsystemOperationTimeService.GetStatByActiveWells(activeWellsIds, token);
+
+ WellMapInfo = activeWells.Select(well => {
+ var wellMapInfo = well.Adapt();
+
+ // From teltemetryTracker
+ var wellLastTelemetryInfo = lastTelemetryInfo.FirstOrDefault(t => t.IdTelemetry == well.IdTelemetry);
+
+ var wellOperationsStat = operationsStat.FirstOrDefault(s => s.Id == well.Id);
+ var wellLastFactSection = wellOperationsStat?.Sections.LastOrDefault(s => s.Fact is not null);
+
+ var wellSubsystemStat = subsystemStat.FirstOrDefault(s => s.Well.Id == well.Id);
+
+ double currentDepth = wellLastTelemetryInfo?.WellDepth
+ ?? wellLastFactSection?.Fact.WellDepthEnd
+ ?? 0d;
+
+ var wellProcessMaps = processMaps
+ .Where(p => p.IdWell == well.Id)
+ .OrderBy(p => p.DepthEnd);
+
+ int? idSection = wellLastFactSection?.Id;
+
+ ProcessMapDto? welllProcessMap;
+ if (idSection is not null)
+ {
+ welllProcessMap = wellProcessMaps.FirstOrDefault(p => p.IdWellSectionType == idSection);
+ }
+ else
+ {
+ welllProcessMap = wellProcessMaps.FirstOrDefault(p => p.DepthStart <= currentDepth && p.DepthEnd >= currentDepth);
+ idSection ??= welllProcessMap?.IdWellSectionType;
+ }
+
+ wellMapInfo.LastTelemetryDate = wellLastTelemetryInfo?.DateTime.ToRemoteDateTime(5) ?? new DateTime();
+ wellMapInfo.WellDepth = new()
+ {
+ Plan = wellDepthByProcessMap.FirstOrDefault(p => p.Id == well.Id)?.DepthEnd,
+ Fact = currentDepth,
+ };
+
+ wellMapInfo.ROP = new()
+ {
+ Plan = welllProcessMap?.RopPlan,
+ Fact = wellOperationsStat?.Total.Fact?.Rop,
+ };
+
+ wellMapInfo.RaceSpeed = new()
+ {
+ Plan = wellOperationsStat?.Total.Plan?.RouteSpeed,
+ Fact = wellOperationsStat?.Total.Fact?.RouteSpeed,
+ };
+
+ wellMapInfo.SaubUsage = wellSubsystemStat?.SubsystemAKB?.KUsage ?? 0d;
+ wellMapInfo.SpinUsage = wellSubsystemStat?.SubsystemSpinMaster?.KUsage ?? 0d;
+ wellMapInfo.TvdLagPercent = 0;// From WellOperationService?
+ wellMapInfo.IdsCompanies = well.Companies.Select(c => c.Id);
+ return wellMapInfo;
+ }).ToArray();
+ }
+
+ public static IEnumerable Where(Func predicate)
+ => WellMapInfo.Where(predicate);
+
+ public static WellMapInfoDto? FirstOrDefault(Func predicate)
+ => WellMapInfo.FirstOrDefault(predicate);
+ }
+#nullable disable
+}
diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs
index a29d1573..8023fe41 100644
--- a/AsbCloudInfrastructure/Services/WellService.cs
+++ b/AsbCloudInfrastructure/Services/WellService.cs
@@ -69,7 +69,7 @@ namespace AsbCloudInfrastructure.Services
return lastTelemetryDate;
}
-#warning GetWellTreeAsync(..) is dummy. Remove it before pullrequest.
+ ///
public async Task> GetWellTreeAsync(int idCompany, CancellationToken token)
{
var wells = await GetEntitiesAsync(new() { IdCompany = idCompany }, token);
@@ -93,15 +93,13 @@ namespace AsbCloudInfrastructure.Services
Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude,
Wells = gCluster.Select(well =>
{
- var dto = well.Adapt();
- if (dto.Latitude is null)
- dto.Latitude = gCluster.Key.Latitude ?? gDeposit.Key.Latitude;
-
- if (dto.Longitude is null)
- dto.Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude;
-
+ var dto = WellInfoService.FirstOrDefault(w => w.Id == well.Id);
+ dto ??= well.Adapt();
+ dto.Latitude ??= gCluster.Key.Latitude ?? gDeposit.Key.Latitude;
+ dto.Longitude ??= gCluster.Key.Longitude ?? gDeposit.Key.Longitude;
if (well.IdTelemetry is not null)
dto.LastTelemetryDate = telemetryService.GetLastTelemetryDate(well.IdTelemetry.Value);
+
return dto;
}),
}),
@@ -120,10 +118,12 @@ namespace AsbCloudInfrastructure.Services
{
var wells = await GetCacheAsync(token);
+ if (request.Ids?.Any() == true)
+ wells = wells.Where(well => request.Ids.Contains(well.Id));
+
if (request.IdCompany.HasValue)
wells = wells.Where(well => well.RelationCompaniesWells.Any(r => r.IdCompany == request.IdCompany.Value));
-
if (request.IdState.HasValue)
wells = wells.Where(well => well.IdState == request.IdState.Value);
diff --git a/AsbCloudInfrastructure/Startup.cs b/AsbCloudInfrastructure/Startup.cs
index 36a85cc1..e93dc5e5 100644
--- a/AsbCloudInfrastructure/Startup.cs
+++ b/AsbCloudInfrastructure/Startup.cs
@@ -27,7 +27,8 @@ namespace AsbCloudInfrastructure
var wellService = provider.GetRequiredService();
wellService.EnshureTimezonesIsSetAsync(CancellationToken.None).Wait();// TODO: make this background work
- var backgroundWorker = provider.GetRequiredService();
+ var backgroundWorker = provider.GetRequiredService();
+ backgroundWorker.Push(WellInfoService.MakeWork());
backgroundWorker.Push(OperationDetectionWorkFactory.MakeWork());
backgroundWorker.Push(SubsystemOperationTimeCalcWorkFactory.MakeWork());
backgroundWorker.Push(LimitingParameterCalcWorkFactory.MakeWork());
diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs
index 0336fb7e..9c018348 100644
--- a/ConsoleApp1/Program.cs
+++ b/ConsoleApp1/Program.cs
@@ -1,11 +1,17 @@
-using iTextSharp.text.pdf;
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
-using Document = iTextSharp.text.Document;
+using AsbCloudApp.Data;
+using AsbCloudApp.Services;
+using AsbCloudDb.Model;
+using AsbCloudInfrastructure;
using CliWrap;
+using Mapster;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApp1
{
@@ -13,160 +19,20 @@ namespace ConsoleApp1
{
static void Main(/*string[] args*/)
{
- // string[] fileExtension = { ".xlsx", ".xls", ".ods", ".odt", ".doc", ".docx", ".pdf" };
- // Console.WriteLine($"start convert");
- // var inputFiles = new List();
- // var resultFile = "C:\\Test\\result.pdf";
- // inputFiles.Add("11112222.docx");
- // inputFiles.Add("11117777.pdf");
- // inputFiles.Add("22223333.xls");
- // inputFiles.Add("33334444.xlsx");
- // //inputFiles.Add("33334444.tts");
-
- // var listOutNames = new List();
- // var filteredFilesNames = inputFiles
- // .Distinct()
- // .Where(f => fileExtension.Any(fe => f.ToLower().EndsWith(fe)))
- // .ToList();
- // FileInfo fileInfo = new FileInfo(resultFile);
-
- // //matchesExtensions(inputFiles);
- // foreach (var FileName in inputFiles)
- // {
- // var outputFile = Path.ChangeExtension(FileName, ".pdf");
- // var outFile = StartConvertProcessAsync(FileName, outputFile);
- // Console.WriteLine($"convert file - {FileName}");
- // Console.ReadLine();
- // listOutNames.Add(outFile.Result.ToString());
- // }
- // Console.WriteLine("merged files");
- // Console.ReadLine();
- // DoMerged(listOutNames, resultFile);
-
-
-
- //static void matchesExtensions(List inputFiles)
- // {
- // string[] fileExtension = { ".xlsx", ".xls", ".ods", ".odt", ".doc", ".docx", ".pdf" };
- // foreach (var file in inputFiles)
- // {
- // var fileExt = Path.GetExtension(file);
- // if (fileExtension.All(fe => fileExt != fe))
- // {
- // throw new FileFormatException($"Файл с именем: {file} не может быть добавлен в список файлов для конвертации и слияния в общий файл программы бурения. Не поддерживаемый формат файла");
- // }
-
- // }
- // }
- if (OperatingSystem.IsWindows())
- {
- Console.WriteLine("win");
- Console.ReadLine();
- }
- if (OperatingSystem.IsLinux())
- {
- Console.WriteLine("linux");
- Console.ReadLine();
- }
-
- }
-
- public static void DoMerged(IEnumerable inputFiles, string outFile)
- {
- using var stream = new FileStream(outFile, FileMode.Create);
- using var doc = new Document();
- using var pdf = new PdfCopy(doc, stream);
- doc.Open();
- var inputFilesList = inputFiles.ToList();
- foreach (var file in inputFilesList)
- {
- var reader = new PdfReader(file);
- for (int i = 0; i < reader.NumberOfPages; i++)
- {
- PdfImportedPage page = pdf.GetImportedPage(reader, i + 1);
- pdf.AddPage(page);
- }
- pdf.FreeReader(reader);
- reader.Close();
- };
- }
-
- private static (string programFile, string programArg) getOptionsStartupProcess(string inputFileName, string resultFileDir)
- {
- (string programFile, string programArg) startupOptions;
- if (OperatingSystem.IsWindows())
- {
- startupOptions.programFile = "C:\\Program Files\\LibreOffice\\program\\soffice.exe";
- startupOptions.programArg = $"-headless -convert-to pdf {inputFileName} --outdir {resultFileDir}";
- return startupOptions;
- }
- if (OperatingSystem.IsLinux())
- {
- startupOptions.programFile = "/usr/bin/soffice";
- startupOptions.programArg = $"--headless --convert-to pdf {inputFileName} --outdir {resultFileDir}";
- return (startupOptions);
- }
-
- throw new NotSupportedException("Вызов процесса в текущей операционной системе не возможен");
- }
-
- //public static void StartConvertProcess(string inputFileName, string outFileName)
- //{
- // using (Process pdfprocess = new Process())
- // {
- // pdfprocess.StartInfo.UseShellExecute = true;
- // //pdfprocess.StartInfo.LoadUserProfile = true;
- // pdfprocess.StartInfo.FileName = "soffice";
- // pdfprocess.StartInfo.Arguments = $"--headless --convert-to pdf {inputFileName} --outdir {outFileName}";
- // pdfprocess.StartInfo.WorkingDirectory = "/usr/bin";
- // pdfprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
- // pdfprocess.Start();
- // if (!pdfprocess.WaitForExit(1000 * 60 * 1))
- // {
- // pdfprocess.Kill();
- // }
- // pdfprocess.Close();
- // }
- //}
- private static async Task StartConvertProcessAsync(string inputFileName, string outFileName)
- {
-
- var progrAndArg = getOptionsStartupProcess(inputFileName, outFileName);
-
- //string outPath = "/home/eddie/Test/OutFiles";
- string outPath = "C:\\Test\\OutFiles";
- var result = Cli.Wrap("C:\\Program Files\\LibreOffice\\program\\soffice.exe")
- .WithArguments($"-headless -convert-to pdf C:\\Test\\InFiles\\{inputFileName} -outdir {outPath}");
- await result.ExecuteAsync();
- var outFile = $"{outPath}\\{outFileName}";
- return outFile;
- }
-
- public static async Task GetConverteAndMergedFileAsync(IEnumerable filesNames, string resultPath)
- {
- string[] fileExtension = { ".xlsx", ".xls", ".ods", ".odt", ".doc", ".docx", ".pdf" };
- //var filteredFilesNames = filesNames.Distinct();
- var filteredFilesNames = filesNames
- .Distinct()
- .Where(f => fileExtension.Any(fe => f.ToLower().EndsWith(fe)))
- .ToList();
- var listFileNames = filteredFilesNames
- .ToList()
- .Select(o => new {
- inputFile = o,
- convertedFile = Path.ChangeExtension(o, ".pdf")
+ var db = ServiceFactory.Context;
+ var q = db.TelemetryDataSaub
+ .Select(t => new {
+ t.IdTelemetry,
+ t.DateTime,
+ t.WellDepth,
+ })
+ .GroupBy(t => t.IdTelemetry)
+ .Select(g => new {
+ Id = g.Key,
+ First = g.OrderBy(t => t.DateTime).FirstOrDefault(),
+ Last = g.OrderBy(t => t.DateTime).LastOrDefault(),
});
- foreach (var excelFileName in listFileNames)
- {
- await StartConvertProcessAsync(excelFileName.inputFile, excelFileName.convertedFile);
- Console.WriteLine($"convert file - {excelFileName.inputFile}");
- Console.ReadLine();
- }
-
- Console.WriteLine("merged files");
- Console.ReadLine();
- DoMerged(listFileNames.Select(c => c.convertedFile), resultPath);
-
- }
+ var d = q.AsNoTracking().ToArray();
+ }
}
}