CS2-24: Правки к предыдущим 3 коммитам

This commit is contained in:
KharchenkoVV 2021-06-25 15:10:05 +05:00
parent 9aa78e9e2c
commit 5259a1c730
14 changed files with 121 additions and 99 deletions

View File

@ -4,8 +4,8 @@ namespace AsbCloudApp.Data
{
public class WellDepthToDayDto
{
public double? WellDepth { get; set; }
public double? BitDepth { get; set; }
public double WellDepth { get; set; }
public double BitDepth { get; set; }
public DateTime Date { get; set; }
}
}

View File

@ -9,7 +9,7 @@ namespace AsbCloudApp.Services
{
IEnumerable<WellDepthToDayDto> GetWellDepthToDay(int wellId);
IEnumerable<WellDepthToIntervalDto> GetWellDepthToInterval(int wellId,
int intervalHours = 24, int intervalMinutes = 0, int beginHour = 8, int beginMinutes = 0);
int intervalHoursTimestamp, int workBeginTimestamp);
IEnumerable<OperationPercentageDto> GetOperationsSummary(int wellId,
DateTime begin = default, DateTime end = default);
IEnumerable<OperationInfoDto> GetOperationsToTime(int wellId,

View File

@ -5,6 +5,7 @@ namespace AsbCloudApp.Services
{
public interface ISaubDataCache
{
Dictionary<int, List<DataSaubBase>> GetSaubData();
IEnumerable<DataSaubBase> GetOrCreateCache(int telemetryId);
void AddData(DataSaubBase data);
}
}

View File

@ -7,6 +7,7 @@ namespace AsbCloudApp.Services
{
int? GetWellIdByTelemetryUid(string uid);
int GetOrCreateTemetryIdByUid(string uid);
double GetTimezoneOffsetByTelemetryId(int idTelemetry);
void UpdateInfo(string uid, TelemetryInfoDto info);
Telemetry GetTelemetryByWellId(int wellId);
}

View File

@ -255,7 +255,7 @@ namespace AsbCloudDb.Model
return (datesRange.From, datesRange.To);
}
public IEnumerable<(double?, double?, DateTime)> GetDepthToInterval (int telemetryId,
public IEnumerable<(double? MinDepth, double? MaxDepth, DateTime BeginPeriodDate)> GetDepthToInterval (int telemetryId,
int intervalHoursTimestamp, int workStartTimestamp, double timezoneOffset)
{
//TODO: Сменить на LINQ группирование

View File

@ -31,7 +31,7 @@ namespace AsbCloudDb.Model
IQueryable<Well> GetWellsByCustomer(int idCustomer);
IQueryable<User> GetUsersByLogin(string login);
(DateTime From, DateTime To) GetDatesRange<T>(int idTelemetry) where T : class, IIdTelemetryDate;
IEnumerable<(double?, double?, DateTime)> GetDepthToInterval(int telemetryId,
IEnumerable<(double? MinDepth, double? MaxDepth, DateTime BeginPeriodDate)> GetDepthToInterval(int telemetryId,
int intervalHoursTimestamp, int workStartTimestamp, double timezoneOffset);
Task<int> CreatePartitionAsync<TEntity>(string propertyName, int id, CancellationToken token = default) where TEntity : class;
}

View File

@ -25,7 +25,7 @@ namespace AsbCloudInfrastructure
services.AddSingleton(new CacheDb());
services.AddSingleton<ITelemetryTracker, TelemetryTracker>();
services.AddSingleton<IBackgroundQueue, BackgroundQueue>();
services.AddSingleton<ISaubDataCache, SaubEventsCache>();
services.AddSingleton<ISaubDataCache, SaubDataCache>();
services.AddTransient<IAuthService, AuthService>();
services.AddTransient<IWellService, WellService>();

View File

@ -12,19 +12,17 @@ namespace AsbCloudInfrastructure.Services
{
private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
private readonly CacheTable<Telemetry> cacheTelemetry;
private readonly CacheTable<Operation> cacheOperations;
private readonly IEnumerable<OperationDetector> operationDetectors;
private readonly OperationDetectorService operationDetectorService;
private readonly IEnumerable<Operation> operations;
public AnalyticsService(IAsbCloudDbContext db, ITelemetryService telemetryService, CacheDb cacheDb)
{
this.db = db;
this.telemetryService = telemetryService;
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
cacheOperations = cacheDb.GetCachedTable<Operation>((AsbCloudDbContext)db);
operations = cacheOperations.Select(c => true);
operationDetectors = new OperationDetectorsContainer(operations).Detectors;
operationDetectorService = new OperationDetectorService(operations);
}
public IEnumerable<WellDepthToDayDto> GetWellDepthToDay(int wellId)
@ -51,36 +49,34 @@ namespace AsbCloudInfrastructure.Services
return depthToTimeData.Select(d => new WellDepthToDayDto
{
WellDepth = d.WellDepth,
BitDepth = d.BitDepth,
WellDepth = d.WellDepth ?? 0.0,
BitDepth = d.BitDepth ?? 0.0,
Date = d.Date
}).ToList();
}
public IEnumerable<WellDepthToIntervalDto> GetWellDepthToInterval(int wellId,
int intervalHours = 24, int intervalMinutes = 0, int workBeginHour = 8, int workBeginMinutes = 0)
int intervalHoursTimestamp, int workBeginTimestamp)
{
var intervalTime = new TimeSpan(intervalHours, intervalMinutes, 0) == default
? new TimeSpan(24, 0, 0)
: new TimeSpan(intervalHours, intervalMinutes, 0);
var workDayBeginTime = new TimeSpan(workBeginHour, workBeginMinutes, 0) == default
? new TimeSpan(8, 0, 0)
: new TimeSpan(intervalHours, intervalMinutes, 0); ;
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 = cacheTelemetry.FirstOrDefault(t => t.Id == telemetry.Id).Info.TimeZoneOffsetTotalHours;
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.Item3,
IntervalDepthProgress = (d.Item2 - d.Item1) ?? 0.0 / intervalHours
IntervalStartDate = d.BeginPeriodDate,
IntervalDepthProgress = (d.MaxDepth - d.MinDepth) ?? 0.0 / intervalHoursTimestamp
}).OrderBy(d => d.IntervalStartDate).ToList();
return wellDepthToIntervalData;
@ -226,12 +222,24 @@ namespace AsbCloudInfrastructure.Services
public DrillingAnalysis GetDrillingAnalysis(IEnumerable<DataSaubBase> dataSaubBases)
{
var saubWellDepths = dataSaubBases.Select(s => s.WellDepth);
var saubBitDepths = dataSaubBases.Select(s => s.BitDepth);
var saubBlockPositions = dataSaubBases.Select(s => s.BlockPosition);
var saubRotorSpeeds = dataSaubBases.Select(s => s.RotorSpeed);
var saubPressures = dataSaubBases.Select(s => s.Pressure);
var saubHookWeights = dataSaubBases.Select(s => s.HookWeight);
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);
@ -244,38 +252,30 @@ namespace AsbCloudInfrastructure.Services
{
IdTelemetry = dataSaubBases.First().IdTelemetry,
Date = dataSaubBases.Last().Date,
IsDepthChanges = wellDepthChangingIndex >= 1.0 || wellDepthChangingIndex <= -1.0,
IsDepthNotChanges = wellDepthChangingIndex < 1.0 && wellDepthChangingIndex > -1.0,
IsBitRising = bitPositionChangingIndex <= -1.0,
IsBitGoesDown = bitPositionChangingIndex >= 1.0,
IsBitStandsStill = bitPositionChangingIndex < 1.0 && bitPositionChangingIndex > -1.0,
IsBitDepthLess20 = (saubBitDepths.Sum() / saubBitDepths.Count()) < 20.0,
IsBlockRising = blockPositionChangingIndex <= -1.0,
IsBlockGoesDown = blockPositionChangingIndex >= 1.0,
IsBlockStandsStill = blockPositionChangingIndex < 1.0 && blockPositionChangingIndex > -1.0,
IsRotorSpeedLess3 = (saubRotorSpeeds.Sum() / saubRotorSpeeds.Count()) < 3.0,
IsRotorSpeedMore3 = (saubRotorSpeeds.Sum() / saubRotorSpeeds.Count()) >= 3.0,
IsPressureLess20 = (saubPressures.Sum() / saubPressures.Count()) < 20.0,
IsPressureMore20 = (saubPressures.Sum() / saubPressures.Count()) >= 20.0,
IsHookWeightNotChanges = hookWeightChangingIndex < 1.0 && hookWeightChangingIndex > 1.0,
IsHookWeightLess3 = (saubHookWeights.Sum() / saubHookWeights.Count()) < 3.0,
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 = GetOperation(drillingAnalysis).Id;
drillingAnalysis.IdOperation = operationDetectorService.DetectOperation(drillingAnalysis).Id;
return drillingAnalysis;
}
private Operation GetOperation(DrillingAnalysis data)
{
var operation = operationDetectors.OrderBy(d => d.Order).First(o => o.Detect(data)).Operation
?? new Operation { Id = 1, Name = "Невозможно определить операцию" };
return operations.FirstOrDefault(o => o.Name.Equals(operation.Name));
}
private static double GetAForLinearFormula(IEnumerable<double?> rawData)
private static double GetAForLinearFormula(IEnumerable<(double?, double)> rawData)
{
var (xSum, ySum, xySum, x2Sum) = GetFormulaVariables(rawData);
@ -283,13 +283,21 @@ namespace AsbCloudInfrastructure.Services
(xSum * xSum - rawData.Count() * x2Sum);
}
private static (int xSum, double ySum, double xySum, int x2Sum) GetFormulaVariables(
IEnumerable<double?> rawData)
private static double GetBForLinearFormula(IEnumerable<(double?, double)> rawData)
{
var data = rawData.Select((d, i) => new
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 = i,
Y = d ?? 0.0
X = d.timestamp,
Y = d.value ?? 0.0
});
var xSum = data.Sum(d => d.X);
var ySum = data.Sum(d => d.Y);

View File

@ -14,19 +14,19 @@ namespace AsbCloudInfrastructure.Services
private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
private readonly IAnalyticsService analyticsService;
private readonly ISaubDataCache saubEventsCache;
private readonly ISaubDataCache saubDataCache;
private readonly IMapper mapper;
private readonly CacheTable<Telemetry> cacheTelemetry;
private readonly CacheTable<Well> cacheWells;
public DataService(IAsbCloudDbContext db, ITelemetryService telemetryService,
IAnalyticsService analyticsService, ISaubDataCache saubEventsCache,
IAnalyticsService analyticsService, ISaubDataCache saubDataCache,
CacheDb cacheDb, MapperConfiguration mapperConfiguration)
{
this.db = db;
this.telemetryService = telemetryService;
this.analyticsService = analyticsService;
this.saubEventsCache = saubEventsCache;
this.saubDataCache = saubDataCache;
mapper = mapperConfiguration.CreateMapper();
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
cacheWells = cacheDb.GetCachedTable<Well>((AsbCloudDbContext)db);
@ -99,20 +99,12 @@ namespace AsbCloudInfrastructure.Services
dataSaub.IdTelemetry = telemetryId;
db.DataSaubBases.Add(dataSaub);
if (!saubEventsCache.GetSaubData().ContainsKey(dataSaub.IdTelemetry))
saubEventsCache.GetSaubData()[dataSaub.IdTelemetry] = new List<DataSaubBase>();
saubDataCache.AddData(dataSaub);
var cachedSaubData = saubEventsCache.GetSaubData()[dataSaub.IdTelemetry];
cachedSaubData.Add(dataSaub);
if (cachedSaubData.Count > 1)
if (saubDataCache.GetOrCreateCache(dataSaub.IdTelemetry).Count() > 1)
{
if (cachedSaubData.Count > 10)
cachedSaubData.RemoveAt(1);
var drillingAnalysis = analyticsService.GetDrillingAnalysis(
cachedSaubData);
saubDataCache.GetOrCreateCache(dataSaub.IdTelemetry));
db.DrillingAnalysis.Add(drillingAnalysis);
}

View File

@ -4,13 +4,13 @@ using AsbCloudDb.Model;
namespace AsbCloudInfrastructure.Services
{
public class OperationDetectorsContainer
public class OperationDetectorService
{
public IEnumerable<OperationDetector> Detectors;
private readonly IEnumerable<OperationDetector> detectors;
public OperationDetectorsContainer(IEnumerable<Operation> operations)
public OperationDetectorService(IEnumerable<Operation> operations)
{
Detectors = new List<OperationDetector>()
detectors = new List<OperationDetector>()
{
new OperationDetector
{
@ -159,5 +159,9 @@ namespace AsbCloudInfrastructure.Services
}
};
}
public Operation DetectOperation(DrillingAnalysis data) =>
detectors.OrderBy(d => d.Order).First(o => o.Detect(data)).Operation
?? new Operation { Id = 1, Name = "Невозможно определить операцию" };
}
}

View File

@ -0,0 +1,30 @@
using System.Collections.Generic;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
namespace AsbCloudInfrastructure.Services
{
public class SaubDataCache : ISaubDataCache
{
private readonly Dictionary<int, List<DataSaubBase>> saubData =
new Dictionary<int, List<DataSaubBase>>();
public IEnumerable<DataSaubBase> GetOrCreateCache(int telemetryId)
{
if (!saubData.ContainsKey(telemetryId))
saubData[telemetryId] = new List<DataSaubBase>();
return saubData[telemetryId];
}
public void AddData(DataSaubBase data)
{
GetOrCreateCache(data.IdTelemetry);
saubData[data.IdTelemetry].Add(data);
if (saubData[data.IdTelemetry].Count > 10)
saubData[data.IdTelemetry].RemoveAt(1);
}
}
}

View File

@ -1,15 +0,0 @@
using System.Collections.Generic;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
namespace AsbCloudInfrastructure.Services
{
public class SaubEventsCache : ISaubDataCache
{
private readonly Dictionary<int, List<DataSaubBase>> saubData =
new Dictionary<int, List<DataSaubBase>>();
public Dictionary<int, List<DataSaubBase>> GetSaubData() =>
saubData;
}
}

View File

@ -25,6 +25,9 @@ namespace AsbCloudInfrastructure.Services
public int? GetWellIdByTelemetryUid(string uid)
=> GetWellByTelemetryUid(uid)?.Id;
public double GetTimezoneOffsetByTelemetryId(int idTelemetry) =>
cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry).Info.TimeZoneOffsetTotalHours;
public void UpdateInfo(string uid, TelemetryInfoDto info)
{
var telemetry = GetOrCreateTelemetryByUid(uid);

View File

@ -48,15 +48,13 @@ namespace AsbCloudWebApi.Controllers
/// Возвращает данные по глубине скважины за период
/// </summary>
/// <param name="wellId">id скважины</param>
/// <param name="intervalHours">количество часов в интервале выборки</param>
/// <param name="intervalMinutes">количество минут в интервале выборки</param>
/// <param name="workBeginHour">время начала рабочей смены (в часах)</param>
/// <param name="workBeginMinutes">время начала рабочей смены (в минутах)</param>
/// <param name="intervalHoursTimestamp">количество секунд в необходимом интервале времени</param>
/// <param name="workBeginTimestamp">количество секунд в времени начала смены</param>
/// <returns>Коллекцию данных по глубине скважины за период</returns>
[HttpGet]
[Route("{wellId}/wellDepthToInterval")]
[ProducesResponseType(typeof(IEnumerable<WellDepthToIntervalDto>), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetWellDepthToInterval(int wellId, int intervalHours, int intervalMinutes, int workBeginHour, int workBeginMinutes)
public IActionResult GetWellDepthToInterval(int wellId, int intervalHoursTimestamp, int workBeginTimestamp)
{
int? idCustomer = User.GetCustomerId();
@ -66,7 +64,7 @@ namespace AsbCloudWebApi.Controllers
if (!wellService.CheckWellOwnership((int)idCustomer, wellId))
return Forbid();
var wellDepthToIntervalData = analyticsService.GetWellDepthToInterval(wellId, intervalHours, intervalMinutes, workBeginHour, workBeginMinutes);
var wellDepthToIntervalData = analyticsService.GetWellDepthToInterval(wellId, intervalHoursTimestamp, workBeginTimestamp);
return Ok(wellDepthToIntervalData);
}
@ -117,7 +115,7 @@ namespace AsbCloudWebApi.Controllers
if (!wellService.CheckWellOwnership((int)idCustomer, wellId))
return Forbid();
var analytics = GetOperationsToTime(wellId, begin, end);
var analytics = analyticsService.GetOperationsToTime(wellId, begin, end);
return Ok(analytics);
}