DetectedOperationExportService replace DetectOperationsAsync(..) by WorkOperationDetection.DetectOperationsAsync(..)

This commit is contained in:
ngfrolov 2024-02-08 12:23:23 +05:00
parent b7dcf313a2
commit bb4c11bd3e
Signed by: ng.frolov
GPG Key ID: E99907A0357B29A7
2 changed files with 43 additions and 114 deletions

View File

@ -1,6 +1,5 @@
using AsbCloudDb.Model;
using ClosedXML.Excel;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.IO;
@ -9,22 +8,21 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.DetectedOperation;
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
using AsbCloudApp.Repositories;
using Microsoft.AspNetCore.Http.Extensions;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Services;
using AsbCloudApp.Data;
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
namespace AsbCloudInfrastructure.Services.DetectOperations;
public class DetectedOperationExportService
{
private readonly DetectorAbstract[] detectors =
{
new DetectorDrilling(),
new DetectorSlipsTime()
};
private const int headerRowsCount = 1;
private readonly IAsbCloudDbContext db;
private readonly IWellService wellService;
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
private const int headerRowsCount = 1;
private const string cellDepositName = "B1";
private const string cellClusterName = "B2";
@ -42,14 +40,14 @@ public class DetectedOperationExportService
private const int columnIdReasonOfEnd = 9;
private const int columnComment = 10;
//TODO: удалить неиспользуемую зависимость
private readonly IAsbCloudDbContext dbContext;
private readonly IWellOperationRepository wellOperationRepository;
public DetectedOperationExportService(IAsbCloudDbContext dbContext, IWellOperationRepository wellOperationRepository)
public DetectedOperationExportService(
IAsbCloudDbContext db,
IWellService wellService,
IWellOperationCategoryRepository wellOperationCategoryRepository)
{
this.dbContext = dbContext;
this.wellOperationRepository = wellOperationRepository;
this.db = db;
this.wellService = wellService;
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
}
/// <summary>
@ -57,15 +55,12 @@ public class DetectedOperationExportService
/// </summary>
/// <param name="idWell">ключ скважины</param>
/// <param name="host">хост</param>
/// <param name="cancellationToken"></param>
/// <param name="token"></param>
/// <returns></returns>
/// <exception cref="ArgumentInvalidException"></exception>
public async Task<Stream> ExportAsync(int idWell, string host, CancellationToken cancellationToken)
public async Task<Stream> ExportAsync(int idWell, string host, CancellationToken token)
{
var well = await dbContext.Set<Well>()
.Include(w => w.Cluster)
.ThenInclude(c => c.Deposit)
.FirstOrDefaultAsync(w => w.Id == idWell, cancellationToken);
var well = await wellService.GetOrDefaultAsync(idWell, token);
if (well is null)
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} does not exist");
@ -73,19 +68,19 @@ public class DetectedOperationExportService
if (!well.IdTelemetry.HasValue)
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} has no telemetry");
var operations = await DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, cancellationToken);
var operations = await WorkOperationDetection.DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, db, token);
return await GenerateExcelFileStreamAsync(well, host, operations, cancellationToken);
return await GenerateExcelFileStreamAsync(well, host, operations, token);
}
private async Task<Stream> GenerateExcelFileStreamAsync(Well well, string host, IEnumerable<OperationDetectorResult> operationDetectorResults,
private async Task<Stream> GenerateExcelFileStreamAsync(WellDto well, string host, IEnumerable<DetectedOperation> operationDetectorResults,
CancellationToken cancellationToken)
{
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
using var workbook = new XLWorkbook(excelTemplateStream);
await AddToWorkbookAsync(workbook, well, host, operationDetectorResults, cancellationToken);
AddToWorkbook(workbook, well, host, operationDetectorResults);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
@ -93,36 +88,34 @@ public class DetectedOperationExportService
return memoryStream;
}
private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, string host, IEnumerable<OperationDetectorResult> operationDetectorResults,
CancellationToken cancellationToken)
private void AddToWorkbook(XLWorkbook workbook, WellDto well, string host, IEnumerable<DetectedOperation> operations)
{
const string sheetName = "Операции";
if (!operationDetectorResults.Any())
if (!operations.Any())
return;
var sheet = workbook.GetWorksheet(sheetName);
await AddToSheetAsync(sheet, well, host, operationDetectorResults
.OrderBy(x => x.Operation.DateStart).ThenBy(x => x.Operation.DepthStart).ToArray(),
cancellationToken);
var orderedOperations = operations
.OrderBy(x => x.DateStart)
.ThenBy(x => x.DepthStart).ToArray();
AddToSheet(sheet, well, host, orderedOperations);
}
private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, string host, IList<OperationDetectorResult> operationDetectorResults,
CancellationToken cancellationToken)
private void AddToSheet(IXLWorksheet sheet, WellDto well, string host, IList<DetectedOperation> operations)
{
var wellOperationCategories = await dbContext.WellOperationCategories.ToListAsync(cancellationToken);
var wellOperationCategories = wellOperationCategoryRepository.Get(true);
sheet.Cell(cellDepositName).SetCellValue(well.Cluster.Deposit.Caption);
sheet.Cell(cellClusterName).SetCellValue(well.Cluster.Caption);
sheet.Cell(cellDepositName).SetCellValue(well.Deposit);
sheet.Cell(cellClusterName).SetCellValue(well.Cluster);
sheet.Cell(cellWellName).SetCellValue(well.Caption);
sheet.Cell(cellDeltaDate).SetCellValue(operationDetectorResults.Max(o => o.Operation.DateEnd) - operationDetectorResults.Min(o => o.Operation.DateStart));
sheet.Cell(cellDeltaDate).SetCellValue((TimeSpan)(Enumerable.Max<DetectedOperation, DateTimeOffset>(operations, (Func<DetectedOperation, DateTimeOffset>)(o => o.DateEnd)) - Enumerable.Min<DetectedOperation, DateTimeOffset>(operations, (Func<DetectedOperation, DateTimeOffset>)(o => o.DateStart))));
var detectedOperations = operationDetectorResults.Select(o => o.Operation).ToArray();
for (int i = 0; i < operationDetectorResults.Count; i++)
for (int i = 0; i < operations.Count; i++)
{
var current = detectedOperations[i];
var current = operations[i];
var dateStart = current.DateStart.ToRemoteDateTime(well.Timezone.Hours);
var dateEnd = current.DateEnd.ToRemoteDateTime(well.Timezone.Hours);
@ -153,17 +146,18 @@ public class DetectedOperationExportService
var link = $"{host}/well/{well.Id}/telemetry/monitoring{query}";
row.Cell(columnDateStart).SetHyperlink(link);
var deltaDepth = i > 0 && i + 1 < detectedOperations.Length
? current.DepthStart - detectedOperations[i - 1].DepthEnd
var deltaDepth = i > 0 && i + 1 < operations.Count
? current.DepthStart - operations[i - 1].DepthEnd
: 0;
row.Cell(columnDeltaDepth).SetCellValue(deltaDepth);
var comment = CreateComment(operationDetectorResults[i]);
var comment = CreateComment(operations[i]);
row.Cell(columnComment).SetCellValue(comment);
}
}
private static string GetCategoryName(IEnumerable<WellOperationCategory> wellOperationCategories, DetectedOperation current)
private static string GetCategoryName(IEnumerable<WellOperationCategoryDto> wellOperationCategories, DetectedOperation current)
{
var idCategory = current.IdCategory;
if (idCategory == WellOperationCategory.IdSlide &&
@ -204,9 +198,8 @@ public class DetectedOperationExportService
return memoryStream;
}
private static string CreateComment(OperationDetectorResult operationDetectorResult)
private static string CreateComment(DetectedOperation operation)
{
var operation = operationDetectorResult.Operation;
switch (operation.IdCategory)
{
case WellOperationCategory.IdRotor:
@ -224,69 +217,4 @@ public class DetectedOperationExportService
return string.Empty;
}
}
private async Task<IEnumerable<OperationDetectorResult>> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin,
CancellationToken token)
{
var query = dbContext.TelemetryDataSaub
.AsNoTracking()
.Where(d => d.IdTelemetry == idTelemetry)
.Where(d => d.BlockPosition >= 0)
.Select(d => new DetectableTelemetry
{
DateTime = d.DateTime,
IdUser = d.IdUser,
WellDepth = d.WellDepth,
Pressure = d.Pressure,
HookWeight = d.HookWeight,
BlockPosition = d.BlockPosition,
BitDepth = d.BitDepth,
RotorSpeed = d.RotorSpeed,
})
.OrderBy(d => d.DateTime);
var startDate = begin;
var detectedOperationResults = new List<OperationDetectorResult>(8);
DetectedOperation? lastDetectedOperation = null;
const int minOperationLength = 5;
const int maxDetectorsInterpolationFrameLength = 30;
const int gap = maxDetectorsInterpolationFrameLength + minOperationLength;
while (true)
{
var data = await query
.Where(d => d.DateTime > startDate)
.ToArrayAsync(token);
if (data.Length < gap)
break;
var isDetected = false;
var positionBegin = 0;
var positionEnd = data.Length - gap;
while (positionEnd > positionBegin)
{
foreach (var detector in detectors)
{
if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result))
continue;
detectedOperationResults.Add(result!);
lastDetectedOperation = result!.Operation;
isDetected = true;
positionBegin = result.TelemetryEnd;
break;
}
positionBegin += 1;
}
if (isDetected)
startDate = lastDetectedOperation!.DateEnd;
else
startDate = data[positionEnd].DateTime;
}
return detectedOperationResults;
}
}

View File

@ -86,7 +86,8 @@ public class WorkOperationDetection: Work
}
}
private static async Task<IEnumerable<DetectedOperation>> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin, IAsbCloudDbContext db, CancellationToken token)
//todo: move this logic to DetectedOperationsService
internal static async Task<IEnumerable<DetectedOperation>> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin, IAsbCloudDbContext db, CancellationToken token)
{
var query = db.TelemetryDataSaub
.AsNoTracking()