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; }
|
public DateTime DateEnd { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Продолжительность операции в часах
|
/// Продолжительность операции в минутах
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double DurationHours => (DateEnd - DateStart).TotalHours;
|
public double DurationMinutes => (DateEnd - DateStart).TotalMinutes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// глубина на начало операции, м
|
/// глубина на начало операции, м
|
||||||
|
@ -17,6 +17,11 @@ namespace AsbCloudApp.Requests
|
|||||||
[Required]
|
[Required]
|
||||||
public int IdWell { get; set; }
|
public int IdWell { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Идентификатор бурильщика
|
||||||
|
/// </summary>
|
||||||
|
public int? IdDriller { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Больше или равно дате
|
/// Больше или равно дате
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -71,9 +71,7 @@ public class DetectorDrilling : DetectorAbstract
|
|||||||
|
|
||||||
private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end)
|
private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
{
|
{
|
||||||
var telemetryRange = telemetry[begin..end]
|
var telemetryRange = telemetry[begin..end];
|
||||||
.OrderBy(t => t.DateTime).ToList();
|
|
||||||
|
|
||||||
var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed);
|
var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed);
|
||||||
var dispersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed / avgRotorSpeed - 1, 2));
|
var dispersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed / avgRotorSpeed - 1, 2));
|
||||||
return (avgRotorSpeed, dispersion);
|
return (avgRotorSpeed, dispersion);
|
||||||
|
@ -27,6 +27,8 @@ internal class SubsystemService : ISubsystemService
|
|||||||
private readonly IDetectedOperationService detectedOperationService;
|
private readonly IDetectedOperationService detectedOperationService;
|
||||||
private readonly ITelemetryDataSaubService telemetryDataSaubService;
|
private readonly ITelemetryDataSaubService telemetryDataSaubService;
|
||||||
|
|
||||||
|
private IDictionary<int, SubsystemDto> subsystems = new Dictionary<int, SubsystemDto>();
|
||||||
|
|
||||||
public SubsystemService(ICrudRepository<SubsystemDto> subsystemRepository,
|
public SubsystemService(ICrudRepository<SubsystemDto> subsystemRepository,
|
||||||
IWellService wellService,
|
IWellService wellService,
|
||||||
IDetectedOperationService detectedOperationService,
|
IDetectedOperationService detectedOperationService,
|
||||||
@ -43,21 +45,25 @@ internal class SubsystemService : ISubsystemService
|
|||||||
var well = await wellService.GetOrDefaultAsync(request.IdWell, token)
|
var well = await wellService.GetOrDefaultAsync(request.IdWell, token)
|
||||||
?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} does not exist");
|
?? 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 },
|
IdsTelemetries = new[] { well.IdTelemetry!.Value },
|
||||||
IdsOperationCategories = WellOperationCategory.MechanicalDrillingSubIds,
|
IdsCategories = WellOperationCategory.MechanicalDrillingSubIds,
|
||||||
|
|
||||||
GeDateStart = request.GeDate,
|
GeDateStart = request.GeDate,
|
||||||
LeDateStart = request.LeDate,
|
LeDateEnd = request.LeDate,
|
||||||
|
|
||||||
GeDepthStart = request.GeDepth,
|
GeDepth = request.GeDepth,
|
||||||
LeDepthStart = request.LeDepth,
|
LeDepth = request.LeDepth,
|
||||||
};
|
};
|
||||||
|
|
||||||
var operations = await detectedOperationService.GetOperationSummaryAsync(detectedOperationSummaryRequest,
|
var operations = await detectedOperationService.GetOperationsAsync(detectedOperationSummaryRequest,
|
||||||
token);
|
token);
|
||||||
|
|
||||||
|
if (request.IdDriller.HasValue)
|
||||||
|
operations = operations.Where(o => o.Driller is not null && o.Driller.Id == request.IdDriller.Value);
|
||||||
|
|
||||||
if (!operations.Any())
|
if (!operations.Any())
|
||||||
return Enumerable.Empty<SubsystemStatDto>();
|
return Enumerable.Empty<SubsystemStatDto>();
|
||||||
|
|
||||||
@ -82,37 +88,67 @@ internal class SubsystemService : ISubsystemService
|
|||||||
return result;
|
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
|
var oscillationStat = CalcOscillationStat(operations);
|
||||||
.GroupBy(o => o.IdCategory);
|
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)
|
||||||
{
|
{
|
||||||
var idSubsystem = groupOperations.Key switch
|
operations = operations.Where(o => o.IdCategory == WellOperationCategory.IdSlide);
|
||||||
|
|
||||||
|
var (sumDepthInterval, usedTimeHours, operationCount) = AggregateOperations(IdSubsystemOscillation, operations);
|
||||||
|
|
||||||
|
var oscillationStat = new SubsystemStatDto
|
||||||
|
{
|
||||||
|
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 =>
|
||||||
|
{
|
||||||
|
var idSubsystem = group.Key switch
|
||||||
{
|
{
|
||||||
WellOperationCategory.IdRotor => IdSubsystemAPDRotor,
|
WellOperationCategory.IdRotor => IdSubsystemAPDRotor,
|
||||||
WellOperationCategory.IdSlide => IdSubsystemAPDSlide,
|
WellOperationCategory.IdSlide => IdSubsystemAPDSlide,
|
||||||
_ => throw new ArgumentException($"IdCategory: {groupOperations.Key} does not supported in this method",
|
_ => throw new ArgumentException($"IdCategory: {group.Key} does not supported in this method", nameof(group.Key))
|
||||||
nameof(groupOperations.Key)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var operationsWithEnableSubsystems = groupOperations.Where(o =>
|
var (sumDepthInterval, usedTimeHours, operationCount) = AggregateOperations(idSubsystem, group);
|
||||||
(EnabledSubsystemsFlags.AutoRotor |
|
|
||||||
EnabledSubsystemsFlags.AutoSlide |
|
|
||||||
EnabledSubsystemsFlags.AutoOscillation).HasEnabledSubsystems(o.EnabledSubsystems));
|
|
||||||
|
|
||||||
var subsystemStat = new SubsystemStatDto
|
var subsystemStat = new SubsystemStatDto
|
||||||
{
|
{
|
||||||
IdSubsystem = idSubsystem,
|
IdSubsystem = idSubsystem,
|
||||||
SubsystemName = subsystems.FirstOrDefault(s => s.Id == idSubsystem)?.Name ?? "unknown",
|
SubsystemName = subsystems.TryGetValue(idSubsystem, out var subsystemDto) ? subsystemDto.Name : "unknown",
|
||||||
UsedTimeHours = operationsWithEnableSubsystems.Sum(o => o.SumDurationHours),
|
UsedTimeHours = usedTimeHours,
|
||||||
SumOperationDepthInterval = groupOperations.Sum(o => o.SumDepthIntervals),
|
SumOperationDepthInterval = group.Sum(o => o.DepthEnd - o.DepthStart),
|
||||||
SumOperationDurationHours = groupOperations.Sum(o => o.SumDurationHours),
|
SumOperationDurationHours = group.Sum(o => o.DurationMinutes / 60),
|
||||||
SumDepthInterval = operationsWithEnableSubsystems.Sum(o => o.SumDepthIntervals),
|
SumDepthInterval = sumDepthInterval,
|
||||||
OperationCount = operationsWithEnableSubsystems.Sum(o => o.Count),
|
OperationCount = operationCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
subsystemStat.KUsage = subsystemStat.SumDepthInterval / subsystemStat.SumOperationDepthInterval;
|
subsystemStat.KUsage = subsystemStat.SumDepthInterval / subsystemStat.SumOperationDepthInterval;
|
||||||
@ -120,50 +156,50 @@ internal class SubsystemService : ISubsystemService
|
|||||||
return subsystemStat;
|
return subsystemStat;
|
||||||
});
|
});
|
||||||
|
|
||||||
var apdSlidePart = stat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemAPDSlide);
|
if (!apdRotorAndSlide.Any())
|
||||||
|
return Enumerable.Empty<SubsystemStatDto>();
|
||||||
if (apdSlidePart is not null)
|
|
||||||
{
|
|
||||||
var operationsWithOscillation =
|
|
||||||
operations.Where(o => EnabledSubsystemsFlags.AutoOscillation.HasEnabledSubsystems(o.EnabledSubsystems));
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
var apdSum = new SubsystemStatDto
|
var apdSum = new SubsystemStatDto
|
||||||
{
|
{
|
||||||
IdSubsystem = IdSubsystemAPD,
|
IdSubsystem = IdSubsystemAPD,
|
||||||
SubsystemName = "АПД",
|
SubsystemName = subsystems.TryGetValue(IdSubsystemAPD, out var subsystemDto) ? subsystemDto.Name : "unknown",
|
||||||
UsedTimeHours = apdParts.Sum(part => part.UsedTimeHours),
|
UsedTimeHours = apdRotorAndSlide.Sum(part => part.UsedTimeHours),
|
||||||
SumOperationDepthInterval = apdParts.Sum(part => part.SumOperationDepthInterval),
|
SumOperationDepthInterval = apdRotorAndSlide.Sum(part => part.SumOperationDepthInterval),
|
||||||
SumOperationDurationHours = apdParts.Sum(part => part.SumOperationDurationHours),
|
SumOperationDurationHours = apdRotorAndSlide.Sum(part => part.SumOperationDurationHours),
|
||||||
SumDepthInterval = apdParts.Sum(part => part.SumDepthInterval),
|
SumDepthInterval = apdRotorAndSlide.Sum(part => part.SumDepthInterval),
|
||||||
OperationCount = apdParts.Sum(part => part.OperationCount),
|
OperationCount = apdRotorAndSlide.Sum(part => part.OperationCount),
|
||||||
};
|
};
|
||||||
|
|
||||||
apdSum.KUsage = apdSum.SumDepthInterval / apdSum.SumOperationDepthInterval;
|
apdSum.KUsage = apdSum.SumDepthInterval / apdSum.SumOperationDepthInterval;
|
||||||
|
|
||||||
stat = stat.Append(apdSum).OrderBy(m => m.IdSubsystem);
|
var apdStat = new List<SubsystemStatDto> { apdSum };
|
||||||
|
apdStat.AddRange(apdRotorAndSlide);
|
||||||
|
|
||||||
return stat;
|
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,
|
private async Task<IEnumerable<SubsystemActiveWellStatDto>> GetStatAsync(IEnumerable<WellDto> wells,
|
||||||
@ -195,14 +231,16 @@ internal class SubsystemService : ISubsystemService
|
|||||||
? ltDate.Value.ToUtcDateTimeOffset(hoursOffset)
|
? ltDate.Value.ToUtcDateTimeOffset(hoursOffset)
|
||||||
: dateRange.To.ToUtcDateTimeOffset(hoursOffset);
|
: dateRange.To.ToUtcDateTimeOffset(hoursOffset);
|
||||||
|
|
||||||
var operations = await detectedOperationService
|
var request = new DetectedOperationRequest
|
||||||
.GetOperationSummaryAsync(new()
|
|
||||||
{
|
{
|
||||||
IdsTelemetries = idsTelemetries,
|
IdsTelemetries = idsTelemetries,
|
||||||
IdsOperationCategories = WellOperationCategory.MechanicalDrillingSubIds,
|
IdsCategories = WellOperationCategory.MechanicalDrillingSubIds,
|
||||||
GeDateStart = beginUTC,
|
GeDateStart = beginUTC,
|
||||||
LeDateEnd = endUTC,
|
LeDateEnd = endUTC,
|
||||||
}, token);
|
};
|
||||||
|
|
||||||
|
var operations = await detectedOperationService
|
||||||
|
.GetOperationsAsync(request, token);
|
||||||
|
|
||||||
var wellStat = new SubsystemActiveWellStatDto { Well = well };
|
var wellStat = new SubsystemActiveWellStatDto { Well = well };
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user