forked from ddrilling/AsbCloudServer
DetectedOperationExportService replace DetectOperationsAsync(..) by WorkOperationDetection.DetectOperationsAsync(..)
This commit is contained in:
parent
b7dcf313a2
commit
bb4c11bd3e
@ -1,6 +1,5 @@
|
|||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -9,22 +8,21 @@ using System.Reflection;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data.DetectedOperation;
|
using AsbCloudApp.Data.DetectedOperation;
|
||||||
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using Microsoft.AspNetCore.Http.Extensions;
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
using AsbCloudApp.Exceptions;
|
using AsbCloudApp.Exceptions;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
||||||
|
|
||||||
public class DetectedOperationExportService
|
public class DetectedOperationExportService
|
||||||
{
|
{
|
||||||
private readonly DetectorAbstract[] detectors =
|
private readonly IAsbCloudDbContext db;
|
||||||
{
|
private readonly IWellService wellService;
|
||||||
new DetectorDrilling(),
|
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
|
||||||
new DetectorSlipsTime()
|
private const int headerRowsCount = 1;
|
||||||
};
|
|
||||||
|
|
||||||
private const int headerRowsCount = 1;
|
|
||||||
|
|
||||||
private const string cellDepositName = "B1";
|
private const string cellDepositName = "B1";
|
||||||
private const string cellClusterName = "B2";
|
private const string cellClusterName = "B2";
|
||||||
@ -42,14 +40,14 @@ public class DetectedOperationExportService
|
|||||||
private const int columnIdReasonOfEnd = 9;
|
private const int columnIdReasonOfEnd = 9;
|
||||||
private const int columnComment = 10;
|
private const int columnComment = 10;
|
||||||
|
|
||||||
//TODO: удалить неиспользуемую зависимость
|
public DetectedOperationExportService(
|
||||||
private readonly IAsbCloudDbContext dbContext;
|
IAsbCloudDbContext db,
|
||||||
private readonly IWellOperationRepository wellOperationRepository;
|
IWellService wellService,
|
||||||
|
IWellOperationCategoryRepository wellOperationCategoryRepository)
|
||||||
public DetectedOperationExportService(IAsbCloudDbContext dbContext, IWellOperationRepository wellOperationRepository)
|
|
||||||
{
|
{
|
||||||
this.dbContext = dbContext;
|
this.db = db;
|
||||||
this.wellOperationRepository = wellOperationRepository;
|
this.wellService = wellService;
|
||||||
|
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -57,15 +55,12 @@ public class DetectedOperationExportService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell">ключ скважины</param>
|
/// <param name="idWell">ключ скважины</param>
|
||||||
/// <param name="host">хост</param>
|
/// <param name="host">хост</param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="ArgumentInvalidException"></exception>
|
/// <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>()
|
var well = await wellService.GetOrDefaultAsync(idWell, token);
|
||||||
.Include(w => w.Cluster)
|
|
||||||
.ThenInclude(c => c.Deposit)
|
|
||||||
.FirstOrDefaultAsync(w => w.Id == idWell, cancellationToken);
|
|
||||||
|
|
||||||
if (well is null)
|
if (well is null)
|
||||||
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} does not exist");
|
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} does not exist");
|
||||||
@ -73,19 +68,19 @@ public class DetectedOperationExportService
|
|||||||
if (!well.IdTelemetry.HasValue)
|
if (!well.IdTelemetry.HasValue)
|
||||||
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} has no telemetry");
|
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)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
||||||
|
|
||||||
using var workbook = new XLWorkbook(excelTemplateStream);
|
using var workbook = new XLWorkbook(excelTemplateStream);
|
||||||
|
|
||||||
await AddToWorkbookAsync(workbook, well, host, operationDetectorResults, cancellationToken);
|
AddToWorkbook(workbook, well, host, operationDetectorResults);
|
||||||
|
|
||||||
MemoryStream memoryStream = new MemoryStream();
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
workbook.SaveAs(memoryStream, new SaveOptions { });
|
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||||
@ -93,36 +88,34 @@ public class DetectedOperationExportService
|
|||||||
return memoryStream;
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, string host, IEnumerable<OperationDetectorResult> operationDetectorResults,
|
private void AddToWorkbook(XLWorkbook workbook, WellDto well, string host, IEnumerable<DetectedOperation> operations)
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
const string sheetName = "Операции";
|
const string sheetName = "Операции";
|
||||||
|
|
||||||
if (!operationDetectorResults.Any())
|
if (!operations.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var sheet = workbook.GetWorksheet(sheetName);
|
var sheet = workbook.GetWorksheet(sheetName);
|
||||||
|
|
||||||
await AddToSheetAsync(sheet, well, host, operationDetectorResults
|
var orderedOperations = operations
|
||||||
.OrderBy(x => x.Operation.DateStart).ThenBy(x => x.Operation.DepthStart).ToArray(),
|
.OrderBy(x => x.DateStart)
|
||||||
cancellationToken);
|
.ThenBy(x => x.DepthStart).ToArray();
|
||||||
|
|
||||||
|
AddToSheet(sheet, well, host, orderedOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, string host, IList<OperationDetectorResult> operationDetectorResults,
|
private void AddToSheet(IXLWorksheet sheet, WellDto well, string host, IList<DetectedOperation> operations)
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
var wellOperationCategories = await dbContext.WellOperationCategories.ToListAsync(cancellationToken);
|
var wellOperationCategories = wellOperationCategoryRepository.Get(true);
|
||||||
|
|
||||||
sheet.Cell(cellDepositName).SetCellValue(well.Cluster.Deposit.Caption);
|
sheet.Cell(cellDepositName).SetCellValue(well.Deposit);
|
||||||
sheet.Cell(cellClusterName).SetCellValue(well.Cluster.Caption);
|
sheet.Cell(cellClusterName).SetCellValue(well.Cluster);
|
||||||
sheet.Cell(cellWellName).SetCellValue(well.Caption);
|
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 < operations.Count; i++)
|
||||||
|
|
||||||
for (int i = 0; i < operationDetectorResults.Count; i++)
|
|
||||||
{
|
{
|
||||||
var current = detectedOperations[i];
|
var current = operations[i];
|
||||||
var dateStart = current.DateStart.ToRemoteDateTime(well.Timezone.Hours);
|
var dateStart = current.DateStart.ToRemoteDateTime(well.Timezone.Hours);
|
||||||
var dateEnd = current.DateEnd.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}";
|
var link = $"{host}/well/{well.Id}/telemetry/monitoring{query}";
|
||||||
row.Cell(columnDateStart).SetHyperlink(link);
|
row.Cell(columnDateStart).SetHyperlink(link);
|
||||||
|
|
||||||
var deltaDepth = i > 0 && i + 1 < detectedOperations.Length
|
var deltaDepth = i > 0 && i + 1 < operations.Count
|
||||||
? current.DepthStart - detectedOperations[i - 1].DepthEnd
|
? current.DepthStart - operations[i - 1].DepthEnd
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
row.Cell(columnDeltaDepth).SetCellValue(deltaDepth);
|
row.Cell(columnDeltaDepth).SetCellValue(deltaDepth);
|
||||||
|
|
||||||
var comment = CreateComment(operationDetectorResults[i]);
|
var comment = CreateComment(operations[i]);
|
||||||
row.Cell(columnComment).SetCellValue(comment);
|
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;
|
var idCategory = current.IdCategory;
|
||||||
if (idCategory == WellOperationCategory.IdSlide &&
|
if (idCategory == WellOperationCategory.IdSlide &&
|
||||||
@ -204,9 +198,8 @@ public class DetectedOperationExportService
|
|||||||
return memoryStream;
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string CreateComment(OperationDetectorResult operationDetectorResult)
|
private static string CreateComment(DetectedOperation operation)
|
||||||
{
|
{
|
||||||
var operation = operationDetectorResult.Operation;
|
|
||||||
switch (operation.IdCategory)
|
switch (operation.IdCategory)
|
||||||
{
|
{
|
||||||
case WellOperationCategory.IdRotor:
|
case WellOperationCategory.IdRotor:
|
||||||
@ -224,69 +217,4 @@ public class DetectedOperationExportService
|
|||||||
return string.Empty;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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
|
var query = db.TelemetryDataSaub
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
|
Loading…
Reference in New Issue
Block a user