DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/AnalyticsService.cs

312 lines
15 KiB
C#
Raw Normal View History

2021-07-21 15:29:19 +05:00
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
2021-07-21 15:29:19 +05:00
using AsbCloudInfrastructure.Services.Cache;
using Mapster;
using Microsoft.EntityFrameworkCore;
2021-07-21 15:29:19 +05:00
using System;
using System.Collections.Generic;
2021-07-21 15:29:19 +05:00
using System.Linq;
namespace AsbCloudInfrastructure.Services
{
public class AnalyticsService : IAnalyticsService
{
private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
2021-07-20 11:24:57 +05:00
private readonly ISaubDataCache saubDataCache;
2021-07-27 13:32:00 +05:00
private readonly CacheTable<TelemetryOperation> cacheOperations;
private readonly TelemetryOperationDetectorService operationDetectorService;
private readonly IEnumerable<TelemetryOperation> operations;
2021-07-21 15:29:19 +05:00
public AnalyticsService(IAsbCloudDbContext db, ITelemetryService telemetryService,
2021-07-20 11:24:57 +05:00
ISaubDataCache saubDataCache, CacheDb cacheDb)
{
this.db = db;
this.telemetryService = telemetryService;
2021-07-20 11:24:57 +05:00
this.saubDataCache = saubDataCache;
2021-07-27 13:32:00 +05:00
cacheOperations = cacheDb.GetCachedTable<TelemetryOperation>((AsbCloudDbContext)db);
operations = cacheOperations.Select(c => true);
2021-07-27 13:32:00 +05:00
operationDetectorService = new TelemetryOperationDetectorService(operations);
}
2021-07-27 14:43:30 +05:00
public IEnumerable<WellDepthToDayDto> GetWellDepthToDay(int idWell)
{
var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
return null;
var depthToTimeData = (from d in db.DataSaubBases
where d.IdTelemetry == telemetryId
select new
{
d.Id,
d.WellDepth,
d.BitDepth,
d.Date
});
var m = (int)Math.Round(1d * depthToTimeData.Count() / 2048);
if (m > 1)
depthToTimeData = depthToTimeData.Where(d => d.Id % m == 0);
return depthToTimeData.Select(d => new WellDepthToDayDto
{
WellDepth = d.WellDepth ?? 0.0,
BitDepth = d.BitDepth ?? 0.0,
Date = d.Date
}).ToList();
}
2021-07-27 14:43:30 +05:00
public IEnumerable<WellDepthToIntervalDto> GetWellDepthToInterval(int idWell,
int intervalSeconds, int workBeginSeconds)
{
intervalSeconds = intervalSeconds == 0 ? 86400 : intervalSeconds;
var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
return null;
var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId((int)telemetryId);
var drillingPeriodsInfo = db.GetDepthToInterval((int)telemetryId, intervalSeconds,
workBeginSeconds, timezoneOffset);
var wellDepthToIntervalData = drillingPeriodsInfo.Select(d => new WellDepthToIntervalDto
{
IntervalStartDate = d.BeginPeriodDate,
IntervalDepthProgress = (d.MaxDepth - d.MinDepth) ?? 0.0 / intervalSeconds
}).OrderBy(d => d.IntervalStartDate).ToList();
return wellDepthToIntervalData;
}
public PaginationContainer<TelemetryOperationDto> GetOperationsByWell(int idWell,
IEnumerable<int> categoryIds = default, DateTime begin = default,
DateTime end = default, int skip = 0, int take = 32)
{
var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
return null;
var operations = from a in db.TelemetryAnalysis.Include(t => t.Operation)
where a.IdTelemetry == telemetryId
select a;
if ((categoryIds != default) && (categoryIds.Any()))
operations = operations.Where(o => categoryIds.Contains(o.IdOperation));
2021-07-27 13:32:00 +05:00
var result = new PaginationContainer<TelemetryOperationDto>
{
Skip = skip,
Take = take
};
operations = operations.OrderBy(o => o.UnixDate);
if (begin != default)
{
var unixBegin = (begin - new DateTime(1970, 1, 1)).TotalSeconds;
operations = operations.Where(o => o.UnixDate >= unixBegin);
}
if (end != default)
{
var unixEnd = (end - new DateTime(1970, 1, 1)).TotalSeconds;
operations = operations.Where(m => (m.UnixDate + m.DurationSec) <= unixEnd);
}
result.Count = operations.Count();
if (skip > 0)
operations = operations.Skip(skip);
var operationsList = operations.Take(take).ToList();
if (operationsList.Count == 0)
return result;
foreach (var operation in operations)
{
2021-07-27 13:32:00 +05:00
var operationDto = new TelemetryOperationDto
{
Id = operation.Id,
Name = operation.Operation.Name,
BeginDate = DateTimeOffset.FromUnixTimeSeconds(operation.UnixDate).DateTime,
EndDate = DateTimeOffset.FromUnixTimeSeconds(operation.UnixDate + operation.DurationSec).DateTime,
StartWellDepth = operation.OperationStartDepth ?? 0.0,
EndWellDepth = operation.OperationEndDepth ?? 0.0
};
result.Items.Add(operationDto);
}
return result;
}
2021-07-27 14:43:30 +05:00
public IEnumerable<TelemetryOperationDurationDto> GetOperationsSummary(int idWell,
DateTime begin = default, DateTime end = default)
{
var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
return null;
var unixBegin = (begin - new DateTime(1970, 1, 1)).TotalSeconds;
var unixEnd = (end - new DateTime(1970, 1, 1)).TotalSeconds;
var operations = (from a in db.TelemetryAnalysis
where a.IdTelemetry == telemetryId &&
a.UnixDate > unixBegin && a.UnixDate < unixEnd
join o in db.Operations on a.IdOperation equals o.Id
group a by new { a.IdOperation, o.Name } into g
2021-07-27 13:32:00 +05:00
select new TelemetryOperationDurationDto
{
OperationName = g.Key.Name,
Duration = g.Where(g => g.DurationSec > 0)
.Sum(a => a.DurationSec)
}).ToList();
return operations;
}
2021-07-27 14:43:30 +05:00
public IEnumerable<TelemetryOperationInfoDto> GetOperationsToInterval(int idWell,
int intervalSeconds, int workBeginSeconds)
{
intervalSeconds = intervalSeconds == 0 ? 86400 : intervalSeconds;
var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell);
if (telemetryId is null)
return null;
var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId((int)telemetryId);
var operations = (from a in db.TelemetryAnalysis
where a.IdTelemetry == telemetryId
join o in db.Operations on a.IdOperation equals o.Id
2021-07-21 15:29:19 +05:00
group a by new
{
Interval = Math.Floor((a.UnixDate - workBeginSeconds + timezoneOffset) / intervalSeconds),
2021-07-21 15:29:19 +05:00
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)
}).ToList();
var operationsGroupedByInterval = operations.GroupBy(op => op.IntervalStart)
2021-07-27 13:32:00 +05:00
.Select(o => new TelemetryOperationInfoDto
2021-07-21 15:29:19 +05:00
{
IntervalBegin = DateTimeOffset.FromUnixTimeSeconds(o.Key),
2021-07-27 13:32:00 +05:00
Operations = o.Select(opr => new TelemetryOperationDetailsDto
2021-07-21 15:29:19 +05:00
{
OperationName = opr.OperationName,
DurationSec = opr.OperationsDuration
}).ToList()
})
2021-07-21 15:29:19 +05:00
.OrderBy(ops => ops.IntervalBegin);
return operationsGroupedByInterval;
}
public void SaveAnalytics(DataSaubBaseDto dataSaubDto)
2021-07-20 11:24:57 +05:00
{
saubDataCache.AddData(dataSaubDto);
2021-07-20 11:24:57 +05:00
if (saubDataCache.GetOrCreateCache(dataSaubDto.IdTelemetry).Count() > 1)
2021-07-20 11:24:57 +05:00
{
var dataSaubs = saubDataCache.GetOrCreateCache(dataSaubDto.IdTelemetry)
2021-07-20 11:24:57 +05:00
.OrderBy(d => d.Date);
var telemetryAnalysisDto = GetDrillingAnalysis(dataSaubs);
2021-07-20 11:24:57 +05:00
if (saubDataCache.CurrentAnalysis is null)
saubDataCache.CurrentAnalysis = telemetryAnalysisDto;
2021-07-20 11:24:57 +05:00
if (saubDataCache.CurrentAnalysis.IdOperation == telemetryAnalysisDto.IdOperation)
2021-07-20 11:24:57 +05:00
{
saubDataCache.CurrentAnalysis.DurationSec +=
telemetryAnalysisDto.DurationSec;
saubDataCache.CurrentAnalysis.OperationEndDepth = dataSaubDto.WellDepth;
2021-07-20 11:24:57 +05:00
}
else
{
db.TelemetryAnalysis.Add(saubDataCache.CurrentAnalysis.Adapt<TelemetryAnalysis>());
saubDataCache.CurrentAnalysis = telemetryAnalysisDto;
saubDataCache.CurrentAnalysis.OperationStartDepth = dataSaubDto.WellDepth;
2021-07-20 11:24:57 +05:00
}
}
}
private TelemetryAnalysisDto GetDrillingAnalysis(IEnumerable<DataSaubBaseDto> dataSaubBases)
{
var lastSaubDate = dataSaubBases.Last().Date;
var saubWellDepths = dataSaubBases.Where(sw => sw.WellDepth is not null)
2021-07-21 15:29:19 +05:00
.Select(s => (Value: (double)s.WellDepth,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubBitDepths = dataSaubBases.Where(sw => sw.BitDepth is not null)
2021-07-21 15:29:19 +05:00
.Select(s => (Value: (double)s.BitDepth,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubBlockPositions = dataSaubBases.Where(sw => sw.BlockPosition is not null)
2021-07-21 15:29:19 +05:00
.Select(s => (Value: (double)s.BlockPosition,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubRotorSpeeds = dataSaubBases.Where(sw => sw.RotorSpeed is not null)
2021-07-21 15:29:19 +05:00
.Select(s => (Value: (double)s.RotorSpeed,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubPressures = dataSaubBases.Where(sw => sw.Pressure is not null)
2021-07-21 15:29:19 +05:00
.Select(s => (Value: (double)s.Pressure,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubHookWeights = dataSaubBases.Where(sw => sw.HookWeight is not null)
2021-07-21 15:29:19 +05:00
.Select(s => (Value: (double)s.HookWeight,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
2021-07-20 11:24:57 +05:00
var wellDepthChangingIndex = new InterpolationLine(saubWellDepths).GetAForLinearFormula();
var bitPositionChangingIndex = new InterpolationLine(saubBitDepths).GetAForLinearFormula();
var blockPositionChangingIndex = new InterpolationLine(saubBlockPositions).GetAForLinearFormula();
var rotorSpeedChangingIndex = new InterpolationLine(saubRotorSpeeds).GetAForLinearFormula();
var pressureChangingIndex = new InterpolationLine(saubPressures).GetAForLinearFormula();
var hookWeightChangingIndex = new InterpolationLine(saubHookWeights).GetAForLinearFormula();
2021-07-20 11:24:57 +05:00
var IsBlockRising = InterpolationLine.IsValueDecreases(blockPositionChangingIndex, -0.0001);
var IsBlockGoesDown = InterpolationLine.IsValueIncreases(blockPositionChangingIndex, 0.0001);
var IsBlockStandsStill = InterpolationLine.IsValueNotChanges(blockPositionChangingIndex, (0.0001, -0.0001));
var drillingAnalysis = new TelemetryAnalysisDto
{
IdTelemetry = dataSaubBases.First().IdTelemetry,
UnixDate = (long)(lastSaubDate - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds,
DurationSec = (int)(dataSaubBases.Last().Date - dataSaubBases.ElementAt(dataSaubBases.Count() - 2).Date).TotalSeconds,
OperationStartDepth = null,
OperationEndDepth = null,
2021-07-20 11:24:57 +05:00
IsWellDepthDecreasing = InterpolationLine.IsValueDecreases(wellDepthChangingIndex, -0.0001),
IsWellDepthIncreasing = InterpolationLine.IsValueIncreases(wellDepthChangingIndex, 0.0001),
IsBitPositionDecreasing = InterpolationLine.IsValueDecreases(bitPositionChangingIndex, -0.0001),
IsBitPositionIncreasing = InterpolationLine.IsValueIncreases(bitPositionChangingIndex, 0.0001),
IsBitPositionLt20 = InterpolationLine.IsAverageLessThanBound(saubBitDepths, 20),
2021-07-20 11:24:57 +05:00
IsBlockPositionDecreasing = InterpolationLine.IsValueDecreases(blockPositionChangingIndex, -0.0001),
IsBlockPositionIncreasing = InterpolationLine.IsValueIncreases(blockPositionChangingIndex, 0.0001),
IsRotorSpeedLt3 = InterpolationLine.IsAverageLessThanBound(saubRotorSpeeds, 3),
IsRotorSpeedGt3 = InterpolationLine.IsAverageMoreThanBound(saubRotorSpeeds, 3),
IsPressureLt20 = InterpolationLine.IsAverageLessThanBound(saubPressures, 20),
IsPressureGt20 = InterpolationLine.IsAverageMoreThanBound(saubPressures, 20),
IsHookWeightNotChanges = InterpolationLine.IsValueNotChanges(hookWeightChangingIndex, (0.0001, -0.0001)),
IsHookWeightLt3 = InterpolationLine.IsAverageLessThanBound(saubHookWeights, 3),
IdOperation = 1
};
drillingAnalysis.IdOperation = operationDetectorService.DetectOperation(drillingAnalysis).Id;
return drillingAnalysis;
}
}
}