Наработка подсистем

1. Добавлен фильр по бурильщику
2. Рефакторинг класса
This commit is contained in:
Степанов Дмитрий 2023-12-19 00:41:02 +05:00
parent 697d1061f7
commit b32f115568
4 changed files with 125 additions and 84 deletions

View File

@ -39,9 +39,9 @@ namespace AsbCloudApp.Data.DetectedOperation
public DateTime DateEnd { get; set; }
/// <summary>
/// Продолжительность операции в часах
/// Продолжительность операции в минутах
/// </summary>
public double DurationHours => (DateEnd - DateStart).TotalHours;
public double DurationMinutes => (DateEnd - DateStart).TotalMinutes;
/// <summary>
/// глубина на начало операции, м

View File

@ -17,6 +17,11 @@ namespace AsbCloudApp.Requests
[Required]
public int IdWell { get; set; }
/// <summary>
/// Идентификатор бурильщика
/// </summary>
public int? IdDriller { get; set; }
/// <summary>
/// Больше или равно дате
/// </summary>

View File

@ -71,9 +71,7 @@ public class DetectorDrilling : DetectorAbstract
private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end)
{
var telemetryRange = telemetry[begin..end]
.OrderBy(t => t.DateTime).ToList();
var telemetryRange = telemetry[begin..end];
var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed);
var dispersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed / avgRotorSpeed - 1, 2));
return (avgRotorSpeed, dispersion);

View File

@ -27,6 +27,8 @@ internal class SubsystemService : ISubsystemService
private readonly IDetectedOperationService detectedOperationService;
private readonly ITelemetryDataSaubService telemetryDataSaubService;
private IDictionary<int, SubsystemDto> subsystems = new Dictionary<int, SubsystemDto>();
public SubsystemService(ICrudRepository<SubsystemDto> subsystemRepository,
IWellService wellService,
IDetectedOperationService detectedOperationService,
@ -43,21 +45,25 @@ internal class SubsystemService : ISubsystemService
var well = await wellService.GetOrDefaultAsync(request.IdWell, token)
?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} does not exist");
var detectedOperationSummaryRequest = new DetectedOperationSummaryRequest
var detectedOperationSummaryRequest = new DetectedOperationRequest
{
IdWell = request.IdWell,
IdsTelemetries = new[] { well.IdTelemetry!.Value },
IdsOperationCategories = WellOperationCategory.MechanicalDrillingSubIds,
IdsCategories = WellOperationCategory.MechanicalDrillingSubIds,
GeDateStart = request.GeDate,
LeDateStart = request.LeDate,
LeDateEnd = request.LeDate,
GeDepthStart = request.GeDepth,
LeDepthStart = request.LeDepth,
GeDepth = request.GeDepth,
LeDepth = request.LeDepth,
};
var operations = await detectedOperationService.GetOperationSummaryAsync(detectedOperationSummaryRequest,
var operations = await detectedOperationService.GetOperationsAsync(detectedOperationSummaryRequest,
token);
if (request.IdDriller.HasValue)
operations = operations.Where(o => o.Driller is not null && o.Driller.Id == request.IdDriller.Value);
if (!operations.Any())
return Enumerable.Empty<SubsystemStatDto>();
@ -81,89 +87,119 @@ internal class SubsystemService : ISubsystemService
var result = await GetStatAsync(activeWells, null, null, token);
return result;
}
private async Task<IEnumerable<SubsystemStatDto>> CalcStatAsync(IEnumerable<OperationsSummaryDto> operations, CancellationToken token)
private async Task<IEnumerable<SubsystemStatDto>> CalcStatAsync(IEnumerable<DetectedOperationDto> operations, CancellationToken token)
{
var subsystems = await subsystemRepository.GetAllAsync(token);
if (!subsystems.Any())
subsystems = (await subsystemRepository.GetAllAsync(token)).ToDictionary(s => s.Id, s => s);
var groupedOperations = operations
.GroupBy(o => o.IdCategory);
var oscillationStat = CalcOscillationStat(operations);
var apdStat = CalcApdStat(operations);
var stat = groupedOperations.Select(groupOperations =>
var stat = new List<SubsystemStatDto> { oscillationStat };
stat.AddRange(apdStat);
return stat;
}
private SubsystemStatDto CalcOscillationStat(IEnumerable<DetectedOperationDto> operations)
{
operations = operations.Where(o => o.IdCategory == WellOperationCategory.IdSlide);
var (sumDepthInterval, usedTimeHours, operationCount) = AggregateOperations(IdSubsystemOscillation, operations);
var oscillationStat = new SubsystemStatDto
{
var idSubsystem = groupOperations.Key switch
IdSubsystem = IdSubsystemOscillation,
SubsystemName = subsystems.TryGetValue(IdSubsystemOscillation, out var subsystemDto) ? subsystemDto.Name : "unknown",
UsedTimeHours = usedTimeHours,
SumOperationDepthInterval = operations.Sum(o => o.DepthEnd - o.DepthStart),
SumOperationDurationHours = operations.Sum(o => o.DurationMinutes / 60),
SumDepthInterval = sumDepthInterval,
OperationCount = operationCount,
};
oscillationStat.KUsage = oscillationStat.SumDepthInterval / oscillationStat.SumOperationDepthInterval;
return oscillationStat;
}
private IEnumerable<SubsystemStatDto> CalcApdStat(IEnumerable<DetectedOperationDto> operations)
{
var apdRotorAndSlide = operations
.Where(o => WellOperationCategory.MechanicalDrillingSubIds.Contains(o.IdCategory))
.GroupBy(o => o.IdCategory)
.Select(group =>
{
WellOperationCategory.IdRotor => IdSubsystemAPDRotor,
WellOperationCategory.IdSlide => IdSubsystemAPDSlide,
_ => throw new ArgumentException($"IdCategory: {groupOperations.Key} does not supported in this method",
nameof(groupOperations.Key)),
};
var operationsWithEnableSubsystems = groupOperations.Where(o =>
(EnabledSubsystemsFlags.AutoRotor |
EnabledSubsystemsFlags.AutoSlide |
EnabledSubsystemsFlags.AutoOscillation).HasEnabledSubsystems(o.EnabledSubsystems));
var subsystemStat = new SubsystemStatDto
{
IdSubsystem = idSubsystem,
SubsystemName = subsystems.FirstOrDefault(s => s.Id == idSubsystem)?.Name ?? "unknown",
UsedTimeHours = operationsWithEnableSubsystems.Sum(o => o.SumDurationHours),
SumOperationDepthInterval = groupOperations.Sum(o => o.SumDepthIntervals),
SumOperationDurationHours = groupOperations.Sum(o => o.SumDurationHours),
SumDepthInterval = operationsWithEnableSubsystems.Sum(o => o.SumDepthIntervals),
OperationCount = operationsWithEnableSubsystems.Sum(o => o.Count),
};
var idSubsystem = group.Key switch
{
WellOperationCategory.IdRotor => IdSubsystemAPDRotor,
WellOperationCategory.IdSlide => IdSubsystemAPDSlide,
_ => throw new ArgumentException($"IdCategory: {group.Key} does not supported in this method", nameof(group.Key))
};
subsystemStat.KUsage = subsystemStat.SumDepthInterval / subsystemStat.SumOperationDepthInterval;
return subsystemStat;
});
var (sumDepthInterval, usedTimeHours, operationCount) = AggregateOperations(idSubsystem, group);
var apdSlidePart = stat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemAPDSlide);
var subsystemStat = new SubsystemStatDto
{
IdSubsystem = idSubsystem,
SubsystemName = subsystems.TryGetValue(idSubsystem, out var subsystemDto) ? subsystemDto.Name : "unknown",
UsedTimeHours = usedTimeHours,
SumOperationDepthInterval = group.Sum(o => o.DepthEnd - o.DepthStart),
SumOperationDurationHours = group.Sum(o => o.DurationMinutes / 60),
SumDepthInterval = sumDepthInterval,
OperationCount = operationCount,
};
if (apdSlidePart is not null)
{
var operationsWithOscillation =
operations.Where(o => EnabledSubsystemsFlags.AutoOscillation.HasEnabledSubsystems(o.EnabledSubsystems));
subsystemStat.KUsage = subsystemStat.SumDepthInterval / subsystemStat.SumOperationDepthInterval;
var spinMaster = new SubsystemStatDto
{
IdSubsystem = IdSubsystemOscillation,
SubsystemName = subsystems.FirstOrDefault(s => s.Id == IdSubsystemOscillation)?.Name ?? "unknown",
UsedTimeHours = operationsWithOscillation.Sum(o => o.SumDurationHours),
SumOperationDepthInterval = apdSlidePart.SumOperationDepthInterval,
SumOperationDurationHours = apdSlidePart.SumOperationDurationHours,
SumDepthInterval = operationsWithOscillation.Sum(o => o.SumDepthIntervals),
OperationCount = operationsWithOscillation.Sum(s => s.Count)
};
spinMaster.KUsage = spinMaster.SumDepthInterval / spinMaster.SumOperationDepthInterval;
stat = stat.Append(spinMaster);
}
var apdParts = stat.Where(s => s.IdSubsystem is IdSubsystemAPDRotor or IdSubsystemAPDSlide);
if (!apdParts.Any())
return stat;
return subsystemStat;
});
if (!apdRotorAndSlide.Any())
return Enumerable.Empty<SubsystemStatDto>();
var apdSum = new SubsystemStatDto
{
IdSubsystem = IdSubsystemAPD,
SubsystemName = "АПД",
UsedTimeHours = apdParts.Sum(part => part.UsedTimeHours),
SumOperationDepthInterval = apdParts.Sum(part => part.SumOperationDepthInterval),
SumOperationDurationHours = apdParts.Sum(part => part.SumOperationDurationHours),
SumDepthInterval = apdParts.Sum(part => part.SumDepthInterval),
OperationCount = apdParts.Sum(part => part.OperationCount),
SubsystemName = subsystems.TryGetValue(IdSubsystemAPD, out var subsystemDto) ? subsystemDto.Name : "unknown",
UsedTimeHours = apdRotorAndSlide.Sum(part => part.UsedTimeHours),
SumOperationDepthInterval = apdRotorAndSlide.Sum(part => part.SumOperationDepthInterval),
SumOperationDurationHours = apdRotorAndSlide.Sum(part => part.SumOperationDurationHours),
SumDepthInterval = apdRotorAndSlide.Sum(part => part.SumDepthInterval),
OperationCount = apdRotorAndSlide.Sum(part => part.OperationCount),
};
apdSum.KUsage = apdSum.SumDepthInterval / apdSum.SumOperationDepthInterval;
stat = stat.Append(apdSum).OrderBy(m => m.IdSubsystem);
return stat;
var apdStat = new List<SubsystemStatDto> { apdSum };
apdStat.AddRange(apdRotorAndSlide);
return apdStat;
}
private static (double SumDepthInterval, double UsedTimeHours, int Count) AggregateOperations(int idSubsystem,
IEnumerable<DetectedOperationDto> operations) =>
idSubsystem switch
{
IdSubsystemAPDRotor => CalcOperationsByEnableSubsystems(operations, EnabledSubsystemsFlags.AutoRotor),
IdSubsystemAPDSlide => CalcOperationsByEnableSubsystems(operations,
EnabledSubsystemsFlags.AutoSlide | EnabledSubsystemsFlags.AutoOscillation),
IdSubsystemOscillation => CalcOperationsByEnableSubsystems(operations, EnabledSubsystemsFlags.AutoOscillation),
_ => throw new ArgumentException($"IdSubsystem: {idSubsystem} does not supported in this method", nameof(idSubsystem))
};
private static (double SumDepthInterval, double UsedTimeHours, int OperationCount) CalcOperationsByEnableSubsystems(
IEnumerable<DetectedOperationDto> operations,
EnabledSubsystemsFlags enabledSubsystems)
{
var filtered = operations.Where(o => enabledSubsystems.HasEnabledSubsystems(o.EnabledSubsystems));
var sumDepthInterval = filtered.Sum(o => o.DepthEnd - o.DepthStart);
var usedTimeHours = filtered.Sum(o => o.DurationMinutes / 60);
var operationCount = filtered.Count();
return (sumDepthInterval, usedTimeHours, operationCount);
}
private async Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatAsync(IEnumerable<WellDto> wells,
@ -195,14 +231,16 @@ internal class SubsystemService : ISubsystemService
? ltDate.Value.ToUtcDateTimeOffset(hoursOffset)
: dateRange.To.ToUtcDateTimeOffset(hoursOffset);
var request = new DetectedOperationRequest
{
IdsTelemetries = idsTelemetries,
IdsCategories = WellOperationCategory.MechanicalDrillingSubIds,
GeDateStart = beginUTC,
LeDateEnd = endUTC,
};
var operations = await detectedOperationService
.GetOperationSummaryAsync(new()
{
IdsTelemetries = idsTelemetries,
IdsOperationCategories = WellOperationCategory.MechanicalDrillingSubIds,
GeDateStart = beginUTC,
LeDateEnd = endUTC,
}, token);
.GetOperationsAsync(request, token);
var wellStat = new SubsystemActiveWellStatDto { Well = well };