This commit is contained in:
ai.astrakhantsev 2022-12-27 14:30:52 +05:00
parent 90ee5d10d1
commit bfc9376733
16 changed files with 431 additions and 12 deletions

View File

@ -1,6 +1,6 @@
using System;
namespace AsbCloudApp.Data
namespace AsbCloudApp.Data.ProcessMap
{
#nullable enable
/// <summary>

View File

@ -0,0 +1,62 @@
using System;
namespace AsbCloudApp.Data.ProcessMap
{
#nullable enable
/// <summary>
/// Модель РТК
/// </summary>
public class ProcessMapReportDto
{
/// <summary>
/// Идентификатор скважины
/// </summary>
public int IdWell { get; set; }
/// <summary>
/// Глубина по стволу, м
/// </summary>
public double Depth { get; set; }
/// <summary>
/// Дата/ время
/// </summary>
public DateTimeOffset Date { get; set; }
/// <summary>
/// Т мех бурения, ч
/// </summary>
public double MechDrillingTime { get; set; }
/// <summary>
/// Слайд
/// </summary>
public ProcessMapReportRowDto Slide { get; set; } = null!;
/// <summary>
/// Ротор
/// </summary>
public ProcessMapReportRowDto Rotor { get; set; } = null!;
/// <summary>
/// название секции скважины
/// </summary>
public string? WellSectionTypeName { get; set; }
/// <summary>
/// название секции скважины
/// </summary>
public int? IdWellSectionType { get; set; }
/// <summary>
/// Категория
/// </summary>
public string? Category { get; set; }
/// <summary>
/// Идентификатор категории
/// </summary>
public int? IdCategory { get; set; }
}
#nullable disable
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AsbCloudApp.Data.ProcessMap
{
#nullable enable
/// <summary>
/// Параметры РТК
/// </summary>
public class ProcessMapReportParamsDto
{
/// <summary>
/// Уставка план
/// </summary>
public double SetPointPlan { get; set; }
/// <summary>
/// Уставка факт
/// </summary>
public double? SetPointFact { get; set; }
/// <summary>
/// Факт
/// </summary>
public double? Fact { get; set; }
/// <summary>
/// Ограничение
/// </summary>
public double? Limit { get; set; }
/// <summary>
/// Процент бурения по уставке ,%
/// </summary>
public double? PercDrillingSetPoint { get; set; }
}
#nullable disable
}

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AsbCloudApp.Data.ProcessMap
{
#nullable enable
/// <summary>
/// Строки РТК
/// </summary>
public class ProcessMapReportRowDto
{
/// <summary>
/// Перепад давления, атм
/// </summary>
public ProcessMapReportParamsDto PressureDrop { get; set; } = null!;
/// <summary>
/// Нагрузка, т
/// </summary>
public ProcessMapReportParamsDto Load { get; set; } = null!;
/// <summary>
/// Момент на ВСП, кНхМ
/// </summary>
public ProcessMapReportParamsDto TopDriveTorque { get; set; } = null!;
/// <summary>
/// Ограничение скорости, м/ч
/// </summary>
public ProcessMapReportParamsDto SpeedLimit { get; set; } = null!;
/// <summary>
/// Процент использования системы АПД, %
/// </summary>
public double PercentageADFSystemUsage { get; set; }
/// <summary>
/// Фактическая механическая скорость, м/ч
/// </summary>
public double ActualMechanicalSpeed { get; set; }
/// <summary>
/// Проходка, м
/// </summary>
public double? SectionPenetration { get; set; }
}
#nullable disable
}

View File

@ -1,4 +1,4 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap;
using System;
using System.Collections.Generic;
using System.Threading;

View File

@ -0,0 +1,24 @@
using AsbCloudApp.Data.ProcessMap;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
#nullable enable
/// <summary>
/// Сервис формирования РТК
/// </summary>
public interface IProcessMapService
{
/// <summary>
/// Получение моделей РТК
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<ProcessMapReportDto>> GetProcessMapAsync(int idWell, CancellationToken token);
}
#nullable disable
}

View File

@ -121,5 +121,13 @@ namespace AsbCloudApp.Services
/// <param name="idWell"></param>
/// <returns></returns>
DateTimeOffset? FirstOperationDate(int idWell);
/// <summary>
/// Получение операций по идентификатору скважины
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<WellOperationDto>> GetOperationsByIdWellAsync(int idWell, CancellationToken token);
}
}

View File

@ -2,7 +2,6 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using System;
namespace AsbCloudDb.Model
{

View File

@ -136,6 +136,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<IFileCategoryService, FileCategoryService>();
services.AddTransient<ILimitingParameterService, LimitingParameterService>();
services.AddTransient<IProcessMapReportService, ProcessMapReportService>();
services.AddTransient<IProcessMapService, ProcessMapService>();
// admin crud services:
services.AddTransient<ICrudRepository<TelemetryDto>, CrudCacheRepositoryBase<TelemetryDto, Telemetry>>(s =>

View File

@ -1,4 +1,5 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;

View File

@ -0,0 +1 @@
,ASB/andas,asb,19.12.2022 11:39,file:///C:/Users/andas/AppData/Roaming/LibreOffice/4;

View File

@ -1,6 +1,7 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.DailyReport;
using ClosedXML.Excel;
using System.Collections.Generic;
using System.IO;
@ -10,25 +11,35 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.ProcessMap
{
#nullable enable
public class ProcessMapReportService : IProcessMapReportService
{
private readonly IAsbCloudDbContext context;
private readonly IProcessMapRepository processMapRepository;
private readonly IProcessMapService processMapService;
public ProcessMapReportService(IAsbCloudDbContext context, IProcessMapRepository processMapRepository)
public ProcessMapReportService(IAsbCloudDbContext context, IProcessMapRepository processMapRepository, IProcessMapService processMapService)
{
this.context = context;
this.processMapRepository = processMapRepository;
this.processMapService = processMapService;
}
public async Task<Stream> MakeReportAsync(int idWell, CancellationToken token)
{
var dtos = (await processMapRepository.GetByIdWellAsync(idWell, token))
.GroupBy(x => x.IdWellSectionType);
var stream = GetExcelTemplateStream();
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
FillProcessMapToWorkbook(workbook, dtos);
var data = processMapService.GetProcessMapAsync(idWell, token);
//var dtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false);
//if (dtos is not null)
//{
// var processMapReportDto = await processMapService.GetProcessMapAsync(dtos, token).ConfigureAwait(false);
// FillProcessMapToWorkbook(workbook, processMapReportDto);
//}
FillProcessMapToWorkbook(workbook, new List<ProcessMapReportDto>());
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
@ -36,20 +47,44 @@ namespace AsbCloudInfrastructure.Services.ProcessMap
return memoryStream;
}
private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable<IGrouping<int, ProcessMapDto>> dto)
private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable<ProcessMapReportDto> dto)
{
var rowsCount = 4;
var columnCount = 2;
var countMerge = 27;
var sheet = workbook.Worksheets.FirstOrDefault();
if (sheet is null)
return;
sheet.Row(rowsCount).Cell(columnCount).Value = "saddadasdasdasds";
sheet.Range(rowsCount, columnCount, rowsCount, countMerge).Row(1).Merge();
SetBorder(sheet.Row(rowsCount).Cell(columnCount).Style);
rowsCount++;
sheet.Row(rowsCount).Cell(columnCount).Value = 2;
sheet.Row(rowsCount).Cell(columnCount).Value = 3;
columnCount++;
sheet.Row(rowsCount).Cell(columnCount).Value = 4;
}
private Stream GetExcelTemplateStream()
{
var stream = System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceStream("AsbCloudInfrastructure.Services.ProcessMap.ProcessMapReportTemplate.xlsx");
return stream;
return stream!;
}
private static IXLStyle SetBorder(IXLStyle style)
{
style.Border.RightBorder = XLBorderStyleValues.Medium;
style.Border.LeftBorder = XLBorderStyleValues.Medium;
style.Border.TopBorder = XLBorderStyleValues.Medium;
style.Border.BottomBorder = XLBorderStyleValues.Medium;
style.Border.InsideBorder = XLBorderStyleValues.Medium;
return style;
}
}
#nullable disable
}

View File

@ -0,0 +1,159 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using DocumentFormat.OpenXml.Bibliography;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.ProcessMap
{
#nullable enable
public class ProcessMapService : IProcessMapService
{
private readonly IWellOperationService wellOperationService;
private readonly IProcessMapRepository processMapRepository;
public ProcessMapService(IWellOperationService wellOperationService,
IProcessMapRepository processMapRepository)
{
this.wellOperationService = wellOperationService;
this.processMapRepository = processMapRepository;
}
public async Task<IEnumerable<ProcessMapReportDto>> GetProcessMapAsync(int idWell, CancellationToken token)
{
var categoryIds = new int[] { WellOperationCategory.IdSlide, WellOperationCategory.IdRotor };
var allOperations = (await wellOperationService.GetOperationsByIdWellAsync(idWell, token).ConfigureAwait(false))
.Where(x => categoryIds.Contains(x.IdCategory))
.Where(x => x.IdType == 1)
.OrderBy(x => x.IdWellSectionType)
.ThenBy(x => x.DateStart)
.ToList();
var processMapDtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false);
var result = allOperations
.GroupBy(x => x.IdWellSectionType)
.SelectMany(x => handleSections(allOperations, processMapDtos!, x))
.ToList();
return result;
}
private static List<ProcessMapReportDto> handleSections(IEnumerable<WellOperationDto> allWellOperation, IEnumerable<ProcessMapDto> processMap, IEnumerable<WellOperationDto> wellOperation)
{
var result = new List<ProcessMapReportDto>();
var minDepth = wellOperation.Min(o => o.DepthStart);
var maxDepth = wellOperation.Max(o => o.DepthEnd);
for (var depth = minDepth; depth <= maxDepth; depth += 100)
{
var currentDepth = result.Count() > 0 ? depth + (100 - depth % 100) : depth;
var operation = allWellOperation.First(x => x.DepthEnd >= currentDepth);
var minDate = operation.DateStart;
var maxDate = operation.DateStart.AddHours(operation.DurationHours);
var currentDate = GetDate(currentDepth, minDepth, maxDepth, minDate, maxDate);
var currentHours = GetHourse(currentDepth, minDepth, maxDepth, operation.DurationHours);
var processMapData = processMap.FirstOrDefault(x => x.IdWellSectionType == operation.IdWellSectionType);
var dto = GetRecord(currentDepth, currentDate, currentHours, operation, processMap);
if (operation.DepthStart < currentDepth)
{
var prevOperation = allWellOperation.FirstOrDefault(x => x.DepthEnd == operation.DepthStart);
if (prevOperation is not null)
{
var prevDepth = currentDepth - prevOperation.DepthEnd;
var prevMinDate = prevOperation.DateStart;
var prevMaxDate = operation.DateStart.AddHours(operation.DurationHours);
var prevDate = GetDate(prevDepth, prevOperation.DepthStart, prevOperation.DepthEnd, minDate, maxDate);
var prevHours = GetHourse(currentDepth, prevOperation.DepthStart, prevOperation.DepthEnd, prevOperation.DurationHours);
if (dto.IdCategory != prevOperation.IdCategory)
FillRecordRow(prevDepth, prevHours, dto, prevOperation.IdCategory, processMap);
dto.MechDrillingTime = currentHours + prevHours;
}
}
result.Add(dto);
}
return result;
}
private static ProcessMapReportDto GetRecord(double depth, DateTimeOffset sate, double hours, WellOperationDto operation, IEnumerable<ProcessMapDto> processMap)
{
var dto = new ProcessMapReportDto
{
IdWell = operation.IdWell,
Depth = depth,
Date = sate,
MechDrillingTime = hours,
Category = operation.IdCategory == WellOperationCategory.IdSlide ? "Слайд" : "Ротор",
IdCategory = operation.IdCategory,
IdWellSectionType = operation.IdWellSectionType,
WellSectionTypeName = operation.WellSectionTypeName
};
FillRecordRow(depth, hours, dto, operation.IdCategory, processMap);
return dto;
}
private static void FillRecordRow(double depth, double hours, ProcessMapReportDto dto, int idCategory, IEnumerable<ProcessMapDto> processMap)
{
var row = new ProcessMapReportRowDto {
SectionPenetration = depth,
ActualMechanicalSpeed = depth / hours,
PercentageADFSystemUsage = dto.Depth / depth * 100
};
var processMapData = processMap.FirstOrDefault(x => x.IdWell == dto.IdWell && x.IdWellSectionType == dto.IdWellSectionType);
if (processMapData is not null)
{
row.PressureDrop = new ProcessMapReportParamsDto
{
SetPointPlan = processMapData.Pressure.Plan
};
row.Load = new ProcessMapReportParamsDto
{
SetPointPlan = processMapData.AxialLoad.Plan
};
row.TopDriveTorque = new ProcessMapReportParamsDto
{
SetPointPlan = processMapData.TopDriveTorque.Plan
};
row.SpeedLimit = new ProcessMapReportParamsDto
{
};
}
if (idCategory == WellOperationCategory.IdSlide)
dto.Slide = row;
else
dto.Rotor = row;
}
private static DateTimeOffset GetDate(double depth, double deptStart, double deptEnd, DateTimeOffset dateStart, DateTimeOffset dateEnd)
{
var a = depth - deptStart;
var b = deptEnd - deptStart;
var c = dateEnd - dateStart;
var result = dateStart + (a / b) * c;
return result;
}
private static double GetHourse(double depth, double deptStart, double deptEnd, double hourse)
{
var a = depth - deptStart;
var b = deptEnd - deptStart;
var result = 0 + (a / b) * hourse;
return result;
}
}
#nullable disable
}

View File

@ -139,6 +139,43 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return result;
}
public async Task<IEnumerable<WellOperationDto>> GetOperationsByIdWellAsync(int idWell, CancellationToken token)
{
var timezone = wellService.GetTimezone(idWell);
var query = BuildQuery(idWell);
var dateStart = query.Min(o => o.DateStart);
query = query
.OrderBy(e => e.DateStart)
.ThenBy(e => e.DepthEnd)
.ThenBy(e => e.Id);
var entities = await query.AsNoTracking()
.ToListAsync(token)
.ConfigureAwait(false);
var nptHours = 0d;
var result = new List<WellOperationDto>();
foreach (var entity in entities)
{
var dto = entity.Adapt<WellOperationDto>();
dto.Day = (entity.DateStart - dateStart).TotalDays;
dto.WellSectionTypeName = entity.WellSectionType.Caption;
dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
dto.CategoryName = entity.OperationCategory.Name;
if (entity.IdType == idOperationTypeFact)
{
if (WellOperationCategory.NonProductiveTimeSubIds.Contains(entity.IdCategory))
nptHours += entity.DurationHours;
dto.NptHours = nptHours;
}
result.Add(dto);
}
return result;
}
public async Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync(
int idWell,
int? operationType = default,

View File

@ -1,4 +1,4 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap;
using FluentValidation;
namespace AsbCloudInfrastructure.Validators

View File

@ -1,4 +1,4 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;