forked from ddrilling/AsbCloudServer
Наработка подсистем
1. Добавлен фильр по бурильщику 2. Рефакторинг класса
This commit is contained in:
parent
697d1061f7
commit
b32f115568
@ -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>
|
||||
/// глубина на начало операции, м
|
||||
|
@ -17,6 +17,11 @@ namespace AsbCloudApp.Requests
|
||||
[Required]
|
||||
public int IdWell { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор бурильщика
|
||||
/// </summary>
|
||||
public int? IdDriller { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Больше или равно дате
|
||||
/// </summary>
|
||||
|
@ -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);
|
||||
|
@ -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 };
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user