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

210 lines
11 KiB
C#

using System;
using System.Linq;
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services.Cache;
using AsbCloudDb.Model;
using System.Collections.Generic;
namespace AsbCloudInfrastructure.Services
{
public class AnalyticsService : IAnalyticsService
{
private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
private readonly CacheTable<Operation> cacheOperations;
private readonly OperationDetectorService operationDetectorService;
private readonly IEnumerable<Operation> operations;
public AnalyticsService(IAsbCloudDbContext db, ITelemetryService telemetryService, CacheDb cacheDb)
{
this.db = db;
this.telemetryService = telemetryService;
cacheOperations = cacheDb.GetCachedTable<Operation>((AsbCloudDbContext)db);
operations = cacheOperations.Select(c => true);
operationDetectorService = new OperationDetectorService(operations);
}
public IEnumerable<WellDepthToDayDto> GetWellDepthToDay(int wellId)
{
var telemetry = telemetryService.GetTelemetryByWellId(wellId);
if (telemetry is null)
return null;
var depthToTimeData = (from d in db.DataSaubBases
where d.IdTelemetry == telemetry.Id
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();
}
public IEnumerable<WellDepthToIntervalDto> GetWellDepthToInterval(int wellId,
int intervalHoursTimestamp, int workBeginTimestamp)
{
intervalHoursTimestamp = intervalHoursTimestamp == 0 ? 86400 : intervalHoursTimestamp;
var telemetry = telemetryService.GetTelemetryByWellId(wellId);
if (telemetry is null)
return null;
var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId(telemetry.Id);
var drillingPeriodsInfo = db.GetDepthToInterval(telemetry.Id, intervalHoursTimestamp,
workBeginTimestamp, timezoneOffset);
var wellDepthToIntervalData = drillingPeriodsInfo.Select(d => new WellDepthToIntervalDto
{
IntervalStartDate = d.BeginPeriodDate,
IntervalDepthProgress = (d.MaxDepth - d.MinDepth) ?? 0.0 / intervalHoursTimestamp
}).OrderBy(d => d.IntervalStartDate).ToList();
return wellDepthToIntervalData;
}
public IEnumerable<OperationDurationDto> GetOperationsSummary(int wellId,
DateTime begin = default, DateTime end = default)
{
var telemetry = telemetryService.GetTelemetryByWellId(wellId);
if (telemetry is null)
return null;
var operations = (from a in db.DrillingAnalysis
where a.IdTelemetry == telemetry.Id &&
a.Date > begin && a.Date < end &&
a.IdOperation != null
join o in db.Operations on a.IdOperation equals o.Id
group a by new { a.IdOperation, o.Name } into g
select new OperationDurationDto
{
ProcessName = g.Key.Name,
Duration = g.Where(g => g.Duration > 0)
.Sum(a => a.Duration)
}).ToList();
return operations;
}
public IEnumerable<OperationInfoDto> GetOperationsToInterval(int wellId,
int intervalHoursTimestamp, int workBeginTimestamp)
{
intervalHoursTimestamp = intervalHoursTimestamp == 0 ? 86400 : intervalHoursTimestamp;
var telemetry = telemetryService.GetTelemetryByWellId(wellId);
if (telemetry is null)
return null;
var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId(telemetry.Id);
var operations = (from a in db.DrillingAnalysis
where a.IdTelemetry == telemetry.Id &&
a.IdOperation != null
join o in db.Operations on a.IdOperation equals o.Id
group a by new {
Interval = Math.Floor((a.UnixDate - workBeginTimestamp + timezoneOffset) / intervalHoursTimestamp),
OperationId = a.IdOperation,
o.Name } into g
select new
{
IntervalStart = g.Min(d => d.Date).Date,
OperationName = g.Key.Name,
OperationsDuration = g.Sum(an => an.Duration)
}).ToList();
var operationsGroupedByInterval = operations.GroupBy(op => op.IntervalStart)
.Select(o => new OperationInfoDto {
IntervalBegin = o.Key,
Operations = o.Select(opr => new OperationDetailsDto {
OperationName = opr.OperationName,
Duration = opr.OperationsDuration
}).ToList()
})
.OrderBy(ops => ops.IntervalBegin);
return operationsGroupedByInterval;
}
public DrillingAnalysis GetDrillingAnalysis(IEnumerable<DataSaubBase> dataSaubBases)
{
var lastSaubDate = dataSaubBases.Last().Date;
var saubWellDepths = dataSaubBases.Where(sw => sw.WellDepth is not null)
.Select(s => (Value: (double)s.WellDepth,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubBitDepths = dataSaubBases.Where(sw => sw.BitDepth is not null)
.Select(s => (Value: (double)s.BitDepth,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubBlockPositions = dataSaubBases.Where(sw => sw.BlockPosition is not null)
.Select(s => (Value: (double)s.BlockPosition,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubRotorSpeeds = dataSaubBases.Where(sw => sw.RotorSpeed is not null)
.Select(s => (Value: (double)s.RotorSpeed,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubPressures = dataSaubBases.Where(sw => sw.Pressure is not null)
.Select(s => (Value: (double)s.Pressure,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var saubHookWeights = dataSaubBases.Where(sw => sw.HookWeight is not null)
.Select(s => (Value: (double)s.HookWeight,
(s.Date - dataSaubBases.First().Date).TotalSeconds));
var wellDepthChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubWellDepths);
var bitPositionChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubBitDepths);
var blockPositionChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubBlockPositions);
var rotorSpeedChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubRotorSpeeds);
var pressureChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubPressures);
var hookWeightChangingIndex = LinearFunctionCalculator.GetAForLinearFormula(saubHookWeights);
var IsBlockRising = LinearFunctionCalculator.IsValueGoesDown(blockPositionChangingIndex, -0.0001);
var IsBlockGoesDown = LinearFunctionCalculator.IsValueGoesUp(blockPositionChangingIndex, 0.0001);
var IsBlockStandsStill = LinearFunctionCalculator.IsValueNotChanges(blockPositionChangingIndex, (0.0001, -0.0001));
var drillingAnalysis = new DrillingAnalysis
{
IdTelemetry = dataSaubBases.First().IdTelemetry,
Date = lastSaubDate,
UnixDate = (long)(lastSaubDate - new DateTime(1970,1,1,0,0,0)).TotalSeconds,
Duration = (int)(dataSaubBases.Last().Date - dataSaubBases.ElementAt(dataSaubBases.Count() - 2).Date).TotalSeconds,
IsDepthChanges = LinearFunctionCalculator.IsValueChanges(wellDepthChangingIndex, (0.0001, -0.0001)),
IsDepthNotChanges = LinearFunctionCalculator.IsValueNotChanges(wellDepthChangingIndex, (0.0001, -0.0001)),
IsBitRising = LinearFunctionCalculator.IsValueGoesDown(bitPositionChangingIndex, -0.0001),
IsBitGoesDown = LinearFunctionCalculator.IsValueGoesUp(bitPositionChangingIndex, 0.0001),
IsBitStandsStill = LinearFunctionCalculator.IsValueNotChanges(bitPositionChangingIndex, (0.0001, -0.0001)),
IsBitDepthLess20 = LinearFunctionCalculator.IsAverageLessThanBound(saubBitDepths, 20),
IsBlockRising = LinearFunctionCalculator.IsValueGoesDown(blockPositionChangingIndex, -0.0001),
IsBlockGoesDown = LinearFunctionCalculator.IsValueGoesUp(blockPositionChangingIndex, 0.0001),
IsBlockStandsStill = LinearFunctionCalculator.IsValueNotChanges(blockPositionChangingIndex, (0.0001, -0.0001)),
IsRotorSpeedLess3 = LinearFunctionCalculator.IsAverageLessThanBound(saubRotorSpeeds, 3),
IsRotorSpeedMore3 = LinearFunctionCalculator.IsAverageMoreThanBound(saubRotorSpeeds, 3),
IsPressureLess20 = LinearFunctionCalculator.IsAverageLessThanBound(saubPressures, 20),
IsPressureMore20 = LinearFunctionCalculator.IsAverageMoreThanBound(saubPressures, 20),
IsHookWeightNotChanges = LinearFunctionCalculator.IsValueNotChanges(hookWeightChangingIndex, (0.0001, -0.0001)),
IsHookWeightLess3 = LinearFunctionCalculator.IsAverageLessThanBound(saubHookWeights, 3),
IdOperation = 1
};
drillingAnalysis.IdOperation = operationDetectorService.DetectOperation(drillingAnalysis).Id;
return drillingAnalysis;
}
}
}