CS2-37: Fixed OperationsToInterval() analytics. Half done.

This commit is contained in:
KharchenkoVV 2021-08-13 12:32:43 +05:00
parent eaf1b9509d
commit b218187117
2 changed files with 131 additions and 29 deletions

View File

@ -6,6 +6,6 @@ namespace AsbCloudApp.Data
public class TelemetryOperationInfoDto
{
public DateTimeOffset IntervalBegin { get; set; }
public IEnumerable<TelemetryOperationDetailsDto> Operations { get; set; }
public IList<TelemetryOperationDetailsDto> Operations { get; set; }
}
}

View File

@ -178,6 +178,7 @@ namespace AsbCloudInfrastructure.Services
.ConfigureAwait(false);
}
// This method is not finished (only half done). It returns not correct Dtos.
public async Task<IEnumerable<TelemetryOperationInfoDto>> GetOperationsToIntervalAsync(int idWell,
int intervalSeconds, int workBeginSeconds, CancellationToken token = default)
{
@ -190,36 +191,40 @@ namespace AsbCloudInfrastructure.Services
var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId((int)telemetryId);
var operations = await (from a in db.TelemetryAnalysis
where a.IdTelemetry == telemetryId
join o in db.TelemetryOperations on a.IdOperation equals o.Id
group a by new
{
Interval = Math.Floor((a.UnixDate - workBeginSeconds + timezoneOffset) / intervalSeconds),
OperationId = a.IdOperation,
o.Name
} into g
select new
{
IntervalStart = g.Min(d => d.UnixDate),
OperationName = g.Key.Name,
OperationsDuration = g.Sum(an => an.DurationSec)
}).AsNoTracking().ToListAsync(token)
.ConfigureAwait(false);
// Get'n'Group all operations only by start date and by name (if there were several operations in interval).
// Without dividing these operations duration by given interval
var ops = await (from a in db.TelemetryAnalysis
where a.IdTelemetry == telemetryId
join o in db.TelemetryOperations on a.IdOperation equals o.Id
group a by new
{
Interval = Math.Floor((a.UnixDate - workBeginSeconds + timezoneOffset) / intervalSeconds),
o.Name
} into g
select new
{
IntervalStart = g.Min(d => d.UnixDate),
OperationName = g.Key.Name,
OperationDuration = g.Sum(an => an.DurationSec)
}).AsNoTracking()
.OrderBy(op => op.IntervalStart)
.ToListAsync(token)
.ConfigureAwait(false);
var operationsGroupedByInterval = operations.GroupBy(op => op.IntervalStart)
.Select(o => new TelemetryOperationInfoDto
{
IntervalBegin = DateTimeOffset.FromUnixTimeSeconds(o.Key),
Operations = o.Select(opr => new TelemetryOperationDetailsDto
{
OperationName = opr.OperationName,
DurationSec = opr.OperationsDuration
}).ToList()
})
.OrderBy(ops => ops.IntervalBegin);
return operationsGroupedByInterval;
var groupedOperationsList = new List<TelemetryOperationInfoDto>();
if (operations is not null && operations.Any())
{
var operations = ops.Select(o => (o.IntervalStart, o.OperationName, o.OperationDuration));
var splittedOperationsByInterval = DivideOperationsByIntervalLength(operations, intervalSeconds); // divides good
groupedOperationsList = UniteOperationsInDto(splittedOperationsByInterval, intervalSeconds).ToList(); // unites not good
}
return groupedOperationsList;
}
public void SaveAnalytics(DataSaubBaseDto dataSaubDto)
@ -251,6 +256,103 @@ namespace AsbCloudInfrastructure.Services
}
}
private static IEnumerable<(long IntervalStart, string OperationName, int OperationDuration)> DivideOperationsByIntervalLength(
IEnumerable<(long IntervalStart, string OperationName, int OperationDuration)> operations, int intervalSeconds)
{
var splittedOperationsByInterval = new List<(long IntervalStart, string OperationName, int OperationDuration)>();
var operationDurationTimeCounter = 0;
foreach (var op in operations)
{
if (op.OperationDuration < (intervalSeconds - operationDurationTimeCounter))
{
splittedOperationsByInterval.Add((op.IntervalStart, op.OperationName, op.OperationDuration));
operationDurationTimeCounter += op.OperationDuration;
}
else
{ // if operation duration overflows current interval it shoud be divided into 2 or more parts for this and next intervals
var remainingIntervalTime = intervalSeconds - operationDurationTimeCounter;
splittedOperationsByInterval.Add((op.IntervalStart, op.OperationName, remainingIntervalTime)); // first part of long operation
var operationDurationAfterDividing = op.OperationDuration - remainingIntervalTime; // second part of long operation. Can be less or more than interval
// If operation duration even after dividing is still more than interval,
// it should be divided several times to several intervals.
if (operationDurationAfterDividing > intervalSeconds)
{
var counter = 0;
var updatedIntervalStartTime = op.IntervalStart + remainingIntervalTime;
while (operationDurationAfterDividing > intervalSeconds)
{
splittedOperationsByInterval.Add((updatedIntervalStartTime + intervalSeconds * counter, op.OperationName, intervalSeconds));
operationDurationAfterDividing -= intervalSeconds;
counter++;
}
splittedOperationsByInterval.Add((updatedIntervalStartTime + operationDurationAfterDividing, op.OperationName, operationDurationAfterDividing));
operationDurationTimeCounter = operationDurationAfterDividing;
}
else
{
splittedOperationsByInterval.Add((op.IntervalStart, op.OperationName, operationDurationAfterDividing));
operationDurationTimeCounter = operationDurationAfterDividing;
}
}
}
return splittedOperationsByInterval;
}
private static IEnumerable<TelemetryOperationInfoDto> UniteOperationsInDto(
IEnumerable<(long IntervalStart, string OperationName, int OperationDuration)> operations, int intervalSeconds)
{
var groupedOperationsList = new List<TelemetryOperationInfoDto>();
var groupedOperationsObj = new TelemetryOperationInfoDto
{
IntervalBegin = DateTimeOffset.FromUnixTimeSeconds(operations.First().IntervalStart),
Operations = new List<TelemetryOperationDetailsDto>()
};
var intervalEndDate = operations.First().IntervalStart + intervalSeconds;
foreach (var op in operations)
{
if (op.IntervalStart < intervalEndDate)
{
groupedOperationsObj.Operations.Add(new TelemetryOperationDetailsDto
{
OperationName = op.OperationName,
DurationSec = op.OperationDuration
});
}
else
{
groupedOperationsList.Add(groupedOperationsObj);
intervalEndDate = op.IntervalStart + intervalSeconds;
groupedOperationsObj = new TelemetryOperationInfoDto
{
IntervalBegin = DateTimeOffset.FromUnixTimeSeconds(op.IntervalStart),
Operations = new List<TelemetryOperationDetailsDto>()
};
groupedOperationsObj.Operations.Add(new TelemetryOperationDetailsDto
{
OperationName = op.OperationName,
DurationSec = op.OperationDuration
});
}
}
groupedOperationsList.Add(groupedOperationsObj);
return groupedOperationsList;
}
private TelemetryAnalysisDto GetDrillingAnalysis(IEnumerable<DataSaubBaseDto> dataSaubBases)
{
var lastSaubDate = dataSaubBases.Last().Date;