CS2-24: Исправлены либо заменены заглушками данные для графиков аналитики.

This commit is contained in:
KharchenkoVV 2021-06-22 09:49:53 +05:00
parent 70dca51987
commit 5409f5a38f
7 changed files with 271 additions and 74 deletions

View File

@ -0,0 +1,11 @@
using System;
namespace AsbCloudApp.Data
{
public class OperationDetailsDto
{
public string OperationName { get; set; }
public DateTime OperationStartTime { get; set; }
public double DurationHours { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
namespace AsbCloudApp.Data
{
public class OperationInfoDto
{
public DateTime IntervalBegin { get; set; }
public DateTime IntervalEnd { get; set; }
public IEnumerable<OperationDetailsDto> OperationData { get; set; }
}
}

View File

@ -1,12 +1,17 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using AsbCloudApp.Data;
namespace AsbCloudApp.Services
{
public interface IAnalyticsService
{
IEnumerable<WellDepthToDayDto> GetWellDepthToDayData(int wellId);
IEnumerable<WellDepthToIntervalDto> GetWellDepthToIntervalData(int wellId,
double interval = 24, int beginHour = 8, int beginMinutes = 0);
IEnumerable<WellDepthToDayDto> GetWellDepthToDay(int wellId);
IEnumerable<WellDepthToIntervalDto> GetWellDepthToInterval(int wellId,
int intervalHours = 24, int intervalMinutes = 0, int beginHour = 8, int beginMinutes = 0);
IEnumerable<OperationPercentageDto> GetOperationsSummary(int wellId,
DateTime begin = default, DateTime end = default);
IEnumerable<OperationInfoDto> GetOperationsToTime(int wellId,
DateTime begin = default, DateTime end = default);
}
}

View File

@ -216,6 +216,33 @@ namespace AsbCloudDb.Model
return (datesRange.From, datesRange.To);
}
public IEnumerable<(double?, double?, DateTime)> GetDepthToInterval (int telemetryId,
int intervalHoursTimestamp, int workStartTimestamp, double timezoneOffset)
{
//TODO: Сменить на LINQ группирование
using var command = Database.GetDbConnection().CreateCommand();
command.CommandText = $@"SELECT Min(t.bit_depth) AS MinDepth, Max(t.bit_depth) AS MaxDepth, Min(t.Date) AS dateStart
FROM t_data_saub_base AS t
WHERE id_telemetry = {telemetryId} AND t.Id % 10 = 0
GROUP BY floor((extract(epoch from t.date) - {workStartTimestamp} + {timezoneOffset}) / {intervalHoursTimestamp});";
Database.OpenConnection();
using var reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
yield return
(
(double?)reader.GetValue(0),
(double?)reader.GetValue(1),
(DateTime)reader.GetValue(2)
);
}
}
}
public async Task<int> CreatePartitionAsync<TEntity>(string propertyName, int id, CancellationToken token = default)
where TEntity : class
{

View File

@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -28,6 +29,8 @@ 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,
int intervalHoursTimestamp, int workStartTimestamp, double timezoneOffset);
Task<int> CreatePartitionAsync<TEntity>(string propertyName, int id, CancellationToken token = default) where TEntity : class;
}
}

View File

@ -2,6 +2,7 @@
using System.Linq;
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services.Cache;
using AsbCloudDb.Model;
using System.Collections.Generic;
@ -11,14 +12,16 @@ namespace AsbCloudInfrastructure.Services
{
private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
private readonly CacheTable<Telemetry> cacheTelemetry;
public AnalyticsService(IAsbCloudDbContext db, ITelemetryService telemetryService)
public AnalyticsService(IAsbCloudDbContext db, ITelemetryService telemetryService, CacheDb cacheDb)
{
this.db = db;
this.telemetryService = telemetryService;
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
}
public IEnumerable<WellDepthToDayDto> GetWellDepthToDayData(int wellId)
public IEnumerable<WellDepthToDayDto> GetWellDepthToDay(int wellId)
{
var telemetry = telemetryService.GetTelemetryByWellId(wellId);
@ -27,76 +30,192 @@ namespace AsbCloudInfrastructure.Services
var depthToTimeData = (from d in db.DataSaubBases
where d.IdTelemetry == telemetry.Id
select new WellDepthToDayDto
select new
{
WellDepth = d.WellDepth,
BitDepth =d.BitDepth,
Date = d.Date
}).ToList();
d.Id,
d.WellDepth,
d.BitDepth,
d.Date
});
var m = (int)Math.Round(1d * depthToTimeData.Count / 2048);
var m = (int)Math.Round(1d * depthToTimeData.Count() / 2048);
if (m > 1)
depthToTimeData = depthToTimeData.Where((d, i) => i % m == 0).ToList();
depthToTimeData = depthToTimeData.Where(d => d.Id % m == 0);
return depthToTimeData;
return depthToTimeData.Select(d => new WellDepthToDayDto
{
WellDepth = d.WellDepth,
BitDepth = d.BitDepth,
Date = d.Date
}).ToList();
}
public IEnumerable<WellDepthToIntervalDto> GetWellDepthToIntervalData(int wellId,
double interval = 24.0, int beginHour = 8, int beginMinutes = 0)
public IEnumerable<WellDepthToIntervalDto> GetWellDepthToInterval(int wellId,
int intervalHours = 24, int intervalMinutes = 0, int workBeginHour = 8, int workBeginMinutes = 0)
{
var intervalHours = TimeSpan.FromHours(interval);
var parseResult = TimeSpan.TryParse($"{beginHour}:{beginMinutes}", out var workDayBeginTime);
if (!parseResult)
workDayBeginTime = TimeSpan.FromHours(8);
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); ;
var telemetry = telemetryService.GetTelemetryByWellId(wellId);
if (telemetry is null)
return null;
var drillingData = (from d in db.DataSaubBases
where d.IdTelemetry == telemetry.Id
select new
{
d.WellDepth,
d.Date
}).ToList();
var timezoneOffset = cacheTelemetry.FirstOrDefault(t => t.Id == telemetry.Id).Info.TimeZoneOffsetTotalHours;
if (!drillingData.Any())
return null;
var drillingPeriodsInfo = db.GetDepthToInterval(telemetry.Id, (int)intervalTime.TotalSeconds,
(int)workDayBeginTime.TotalSeconds, timezoneOffset);
var drillingStartDate = drillingData.First().Date;
var periodStart = drillingStartDate.Hour < 8
? new DateTime(drillingStartDate.Year, drillingStartDate.Month, drillingStartDate.Day).AddDays(-1) + workDayBeginTime
: new DateTime(drillingStartDate.Year, drillingStartDate.Month, drillingStartDate.Day) + workDayBeginTime;
var periodEnd = periodStart + intervalHours;
var onePeriodData = new List<(double?, DateTime)>();
var drillingPeriods = new List<IEnumerable<(double?, DateTime)>>();
foreach (var d in drillingData)
var wellDepthToIntervalData = drillingPeriodsInfo.Select(d => new WellDepthToIntervalDto
{
if (d.Date < periodEnd)
{
onePeriodData.Add((d.WellDepth, d.Date));
continue;
}
drillingPeriods.Add(onePeriodData);
onePeriodData.Clear();
periodStart = d.Date;
periodEnd = periodStart + intervalHours;
onePeriodData.Add((d.WellDepth, d.Date));
}
var wellDepthToIntervalData = drillingPeriods.Select(d => new WellDepthToIntervalDto
{
IntervalStartDate = d.FirstOrDefault().Item2,
IntervalDepthProgress = (d.Last().Item1 - d.FirstOrDefault().Item1) ?? 0.0 / interval
});
IntervalStartDate = d.Item3,
IntervalDepthProgress = (d.Item2 - d.Item1) ?? 0.0 / intervalHours
}).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
}
}
}
};
}
}
}

View File

@ -28,7 +28,7 @@ namespace AsbCloudWebApi.Controllers
/// <returns>Коллекцию данных по скважине "глубина-день"</returns>
[HttpGet]
[Route("{wellId}/wellDepthToDay")]
[ProducesResponseType(typeof(List<WellDepthToDayDto>), (int)System.Net.HttpStatusCode.OK)]
[ProducesResponseType(typeof(IEnumerable<WellDepthToDayDto>), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetWellDepthToDay(int wellId)
{
int? idCustomer = User.GetCustomerId();
@ -39,7 +39,7 @@ namespace AsbCloudWebApi.Controllers
if (!wellService.CheckWellOwnership((int)idCustomer, wellId))
return Forbid();
var wellDepthToDayData = analyticsService.GetWellDepthToDayData(wellId);
var wellDepthToDayData = analyticsService.GetWellDepthToDay(wellId);
return Ok(wellDepthToDayData);
}
@ -48,11 +48,15 @@ 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>
/// <returns>Коллекцию данных по глубине скважины за период</returns>
[HttpGet]
[Route("{wellId}/wellDepthToInterval")]
[ProducesResponseType(typeof(List<WellDepthToIntervalDto>), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetWellDepthToInterval(int wellId)
[ProducesResponseType(typeof(IEnumerable<WellDepthToIntervalDto>), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetWellDepthToInterval(int wellId, int intervalHours, int intervalMinutes, int workBeginHour, int workBeginMinutes)
{
int? idCustomer = User.GetCustomerId();
@ -62,18 +66,44 @@ namespace AsbCloudWebApi.Controllers
if (!wellService.CheckWellOwnership((int)idCustomer, wellId))
return Forbid();
var wellDepthToIntervalData = analyticsService.GetWellDepthToIntervalData(wellId);
var wellDepthToIntervalData = analyticsService.GetWellDepthToInterval(wellId, intervalHours, intervalMinutes, workBeginHour, workBeginMinutes);
return Ok(wellDepthToIntervalData);
}
/// <summary>
/// Возвращает данные по операциям на скважине за период
/// Возвращает данные по операциям на скважине "операции-время"
/// </summary>
/// <param name="wellId">id скважины</param>
/// <param name="begin">дата начала интервала</param>
/// <param name="end">дата окончания интервала</param>
/// <returns>Коллекцию операций на скважине</returns>
[HttpGet]
[Route("{wellId}/operationsSummary")]
[ProducesResponseType(typeof(List<OperationPercentageDto>), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetOperationsSummary(int wellId, DateTime begin = default, DateTime end = default)
{
int? idCustomer = User.GetCustomerId();
if (idCustomer is null)
return BadRequest();
if (!wellService.CheckWellOwnership((int)idCustomer, wellId))
return Forbid();
var analytics = analyticsService.GetOperationsSummary(wellId, begin, end);
return Ok(analytics);
}
/// <summary>
/// Возвращает детальные данные по операциям на скважине за период
/// </summary>
/// <param name="wellId">id скважины</param>
/// <param name="begin">дата начала интервала</param>
/// <param name="end">дата окончания интервала</param>
/// <returns>Коллекцию операций на скважине</returns>
[HttpGet]
[Route("{wellId}/operationsToTime")]
[ProducesResponseType(typeof(List<OperationPercentageDto>), (int)System.Net.HttpStatusCode.OK)]
@ -87,17 +117,7 @@ namespace AsbCloudWebApi.Controllers
if (!wellService.CheckWellOwnership((int)idCustomer, wellId))
return Forbid();
var analytics = 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 }
};
var analytics = GetOperationsToTime(wellId, begin, end);
return Ok(analytics);
}