DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/AnalyticsService.cs
2021-07-16 09:15:10 +05:00

311 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 intervalTime = new TimeSpan(0, 0, intervalHoursTimestamp);
var workDayBeginTime = new TimeSpan(0, 0, workBeginTimestamp);
var telemetry = telemetryService.GetTelemetryByWellId(wellId);
if (telemetry is null)
return null;
var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId(telemetry.Id);
var drillingPeriodsInfo = db.GetDepthToInterval(telemetry.Id, (int)intervalTime.TotalSeconds,
(int)workDayBeginTime.TotalSeconds, 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<OperationPercentageDto> GetOperationsSummary(int wellId,
DateTime begin = default, DateTime end = default)
{
return new List<OperationPercentageDto>
{
new OperationPercentageDto { ProcessName = "Роторное бурение", Percentage = 19.7 },
new OperationPercentageDto { ProcessName = "Подъем с проработкой", Percentage = 6.2 },
new OperationPercentageDto { ProcessName = "Спуск с проработкой", Percentage = 9.4 },
new OperationPercentageDto { ProcessName = "Подъем с промывкой", Percentage = 18.4 },
new OperationPercentageDto { ProcessName = "Неподвижное состояние", Percentage = 12.1 },
new OperationPercentageDto { ProcessName = "Вращение без циркуляции", Percentage = 7.4 },
new OperationPercentageDto { ProcessName = "Спуск в скважину", Percentage = 16.7 },
new OperationPercentageDto { ProcessName = "На поверхности", Percentage = 10.1 }
};
}
public IEnumerable<OperationInfoDto> GetOperationsToTime(int wellId,
DateTime begin = default, DateTime end = default)
{
return new List<OperationInfoDto>
{
new OperationInfoDto
{
IntervalBegin = new DateTime(2021, 06, 01, 08, 00, 00),
IntervalEnd = new DateTime(2021, 06, 02, 08, 00, 00),
OperationData = new List<OperationDetailsDto>
{
new OperationDetailsDto
{
OperationName = "Роторное бурение",
OperationStartTime = new DateTime(2021, 06, 01, 10, 00, 00),
DurationHours = 1.2
},
new OperationDetailsDto
{
OperationName = "Подъем с проработкой",
OperationStartTime = new DateTime(2021, 06, 01, 11, 00, 00),
DurationHours = 3.2
},
new OperationDetailsDto
{
OperationName = "Роторное бурение",
OperationStartTime = new DateTime(2021, 06, 01, 12, 00, 00),
DurationHours = 1.5
},
new OperationDetailsDto
{
OperationName = "Неподвижное состояние",
OperationStartTime = new DateTime(2021, 06, 01, 13, 00, 00),
DurationHours = 0.2
},
new OperationDetailsDto
{
OperationName = "Роторное бурение",
OperationStartTime = new DateTime(2021, 06, 01, 14, 00, 00),
DurationHours = 3.2
}
}
},
new OperationInfoDto
{
IntervalBegin = new DateTime(2021, 06, 02, 08, 00, 00),
IntervalEnd = new DateTime(2021, 06, 03, 08, 00, 00),
OperationData = new List<OperationDetailsDto>
{
new OperationDetailsDto
{
OperationName = "На поверхности",
OperationStartTime = new DateTime(2021, 06, 13, 10, 01, 00),
DurationHours = 2.2
},
new OperationDetailsDto
{
OperationName = "Спуск в скважину",
OperationStartTime = new DateTime(2021, 06, 13, 11, 10, 00),
DurationHours = 0.4
},
new OperationDetailsDto
{
OperationName = "На поверхности",
OperationStartTime = new DateTime(2021, 06, 13, 12, 20, 00),
DurationHours = 2.5
},
new OperationDetailsDto
{
OperationName = "Вращение без циркуляции",
OperationStartTime = new DateTime(2021, 06, 13, 13, 00, 00),
DurationHours = 1.2
},
new OperationDetailsDto
{
OperationName = "Роторное бурение",
OperationStartTime = new DateTime(2021, 06, 13, 14, 00, 00),
DurationHours = 5.2
}
}
},
new OperationInfoDto
{
IntervalBegin = new DateTime(2021, 06, 03, 08, 00, 00),
IntervalEnd = new DateTime(2021, 06, 04, 08, 00, 00),
OperationData = new List<OperationDetailsDto>
{
new OperationDetailsDto
{
OperationName = "Подъем с проработкой",
OperationStartTime = new DateTime(2021, 06, 12, 10, 00, 00),
DurationHours = 3.2
},
new OperationDetailsDto
{
OperationName = "Спуск с проработкой",
OperationStartTime = new DateTime(2021, 06, 12, 11, 00, 00),
DurationHours = 1.4
},
new OperationDetailsDto
{
OperationName = "Подъем с проработкой",
OperationStartTime = new DateTime(2021, 06, 12, 12, 00, 00),
DurationHours = 0.5
},
new OperationDetailsDto
{
OperationName = "На поверхности",
OperationStartTime = new DateTime(2021, 06, 12, 13, 00, 00),
DurationHours = 3.2
},
new OperationDetailsDto
{
OperationName = "Роторное бурение",
OperationStartTime = new DateTime(2021, 06, 13, 14, 00, 00),
DurationHours = 1.2
}
}
}
};
}
public DrillingAnalysis GetDrillingAnalysis(IEnumerable<DataSaubBase> dataSaubBases)
{
var saubWellDepths = dataSaubBases.Select(s => (s.WellDepth,
TotalSeconds: (s.Date -
new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds - 1530000000));
var saubBitDepths = dataSaubBases.Select(s => (s.BitDepth,
TotalSeconds: (s.Date -
new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds - 1530000000));
var saubBlockPositions = dataSaubBases.Select(s => (s.BlockPosition,
TotalSeconds: (s.Date -
new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds - 1530000000));
var saubRotorSpeeds = dataSaubBases.Select(s => (s.RotorSpeed,
TotalSeconds: (s.Date -
new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds - 1530000000));
var saubPressures = dataSaubBases.Select(s => (s.Pressure,
TotalSeconds: (s.Date -
new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds - 1530000000));
var saubHookWeights = dataSaubBases.Select(s => (s.HookWeight,
TotalSeconds: (s.Date -
new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds - 1530000000));
var wellDepthChangingIndex = GetAForLinearFormula(saubWellDepths);
var bitPositionChangingIndex = GetAForLinearFormula(saubBitDepths);
var blockPositionChangingIndex = GetAForLinearFormula(saubBlockPositions);
var rotorSpeedChangingIndex = GetAForLinearFormula(saubRotorSpeeds);
var pressureChangingIndex = GetAForLinearFormula(saubPressures);
var hookWeightChangingIndex = GetAForLinearFormula(saubHookWeights);
var drillingAnalysis = new DrillingAnalysis
{
IdTelemetry = dataSaubBases.First().IdTelemetry,
Date = dataSaubBases.Last().Date,
IsDepthChanges = wellDepthChangingIndex >= 0.0001 || wellDepthChangingIndex <= -0.0001,
IsDepthNotChanges = wellDepthChangingIndex < 0.0001 && wellDepthChangingIndex > -0.0001,
IsBitRising = bitPositionChangingIndex >= 0.0001,
IsBitGoesDown = bitPositionChangingIndex <= -0.0001,
IsBitStandsStill = bitPositionChangingIndex < 0.0001 && bitPositionChangingIndex > -0.0001,
IsBitDepthLess20 = (saubBitDepths.Sum(s => s.BitDepth) / saubBitDepths.Count()) < 20.0,
IsBlockRising = blockPositionChangingIndex >= 0.0001,
IsBlockGoesDown = blockPositionChangingIndex <= -0.0001,
IsBlockStandsStill = blockPositionChangingIndex < 0.001 && blockPositionChangingIndex > -0.0001,
IsRotorSpeedLess3 = (saubRotorSpeeds.Sum(s => s.RotorSpeed) / saubRotorSpeeds.Count()) < 3,
IsRotorSpeedMore3 = (saubRotorSpeeds.Sum(s => s.RotorSpeed) / saubRotorSpeeds.Count()) >= 3,
IsPressureLess20 = (saubPressures.Sum(s => s.Pressure) / saubPressures.Count()) < 20.0,
IsPressureMore20 = (saubPressures.Sum(s => s.Pressure) / saubPressures.Count()) >= 20.0,
IsHookWeightNotChanges = hookWeightChangingIndex < 0.0001 && hookWeightChangingIndex > 0.0001,
IsHookWeightLess3 = (saubHookWeights.Sum(s => s.HookWeight) / saubHookWeights.Count()) < 3.0,
IdOperation = 1
};
drillingAnalysis.IdOperation = operationDetectorService.DetectOperation(drillingAnalysis).Id;
return drillingAnalysis;
}
private static double GetAForLinearFormula(IEnumerable<(double? x, double y)> rawData)
{
var (xSum, ySum, xySum, x2Sum) = GetFormulaVariables(rawData);
return (xSum * ySum - rawData.Count() * xySum) /
(xSum * xSum - rawData.Count() * x2Sum);
}
private static double GetBForLinearFormula(IEnumerable<(double?, double)> rawData)
{
var (xSum, ySum, xySum, x2Sum) = GetFormulaVariables(rawData);
return (xSum * xySum - x2Sum * ySum) /
(xSum * xSum - rawData.Count() * x2Sum);
}
private static (double xSum, double ySum, double xySum, double x2Sum) GetFormulaVariables(
IEnumerable<(double? value, double timestamp)> rawData)
{
var data = rawData.Select((d) => new
{
X = d.timestamp,
Y = d.value ?? 0.0
});
var xSum = data.Sum(d => d.X);
var ySum = data.Sum(d => d.Y);
var xySum = data.Sum(d => d.X * d.Y);
var x2Sum = data.Sum(d => d.X * d.X);
return (xSum, ySum, xySum, x2Sum);
}
}
}