diff --git a/AsbCloudApp/Data/OperationDetailsDto.cs b/AsbCloudApp/Data/OperationDetailsDto.cs index a487df4e..2868357f 100644 --- a/AsbCloudApp/Data/OperationDetailsDto.cs +++ b/AsbCloudApp/Data/OperationDetailsDto.cs @@ -1,11 +1,8 @@ -using System; - -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data { public class OperationDetailsDto { public string OperationName { get; set; } - public DateTime OperationStartTime { get; set; } - public double DurationHours { get; set; } + public int Duration { get; set; } } } diff --git a/AsbCloudApp/Data/OperationPercentageDto.cs b/AsbCloudApp/Data/OperationDurationDto.cs similarity index 51% rename from AsbCloudApp/Data/OperationPercentageDto.cs rename to AsbCloudApp/Data/OperationDurationDto.cs index 90c455b7..199f5634 100644 --- a/AsbCloudApp/Data/OperationPercentageDto.cs +++ b/AsbCloudApp/Data/OperationDurationDto.cs @@ -1,8 +1,8 @@ namespace AsbCloudApp.Data { - public class OperationPercentageDto + public class OperationDurationDto { public string ProcessName { get; set; } - public double Percentage { get; set; } + public double Duration { get; set; } } } diff --git a/AsbCloudApp/Data/OperationInfoDto.cs b/AsbCloudApp/Data/OperationInfoDto.cs index 0cfcb53e..fcc3bc08 100644 --- a/AsbCloudApp/Data/OperationInfoDto.cs +++ b/AsbCloudApp/Data/OperationInfoDto.cs @@ -6,7 +6,6 @@ namespace AsbCloudApp.Data public class OperationInfoDto { public DateTime IntervalBegin { get; set; } - public DateTime IntervalEnd { get; set; } - public IEnumerable OperationData { get; set; } + public IEnumerable Operations { get; set; } } } diff --git a/AsbCloudApp/Services/IAnalyticsService.cs b/AsbCloudApp/Services/IAnalyticsService.cs index 735c545f..9a8aea55 100644 --- a/AsbCloudApp/Services/IAnalyticsService.cs +++ b/AsbCloudApp/Services/IAnalyticsService.cs @@ -10,10 +10,10 @@ namespace AsbCloudApp.Services IEnumerable GetWellDepthToDay(int wellId); IEnumerable GetWellDepthToInterval(int wellId, int intervalHoursTimestamp, int workBeginTimestamp); - IEnumerable GetOperationsSummary(int wellId, - DateTime begin = default, DateTime end = default); - IEnumerable GetOperationsToTime(int wellId, + IEnumerable GetOperationsSummary(int wellId, DateTime begin = default, DateTime end = default); + IEnumerable GetOperationsToInterval(int wellId, + int intervalHoursTimestamp, int workBeginTimestamp); DrillingAnalysis GetDrillingAnalysis(IEnumerable dataSaubBases); } } diff --git a/AsbCloudDb/Model/DrillingAnalysis.cs b/AsbCloudDb/Model/DrillingAnalysis.cs index 8e171981..1b4ca234 100644 --- a/AsbCloudDb/Model/DrillingAnalysis.cs +++ b/AsbCloudDb/Model/DrillingAnalysis.cs @@ -20,6 +20,12 @@ namespace AsbCloudDb.Model [Column("date", TypeName = "timestamp with time zone"), Comment("'2021-10-19 18:23:54+05'")] public DateTime Date { get; set; } + [Column("unix_date", TypeName = "bigint"), Comment("Unix timestamp для Linq запросов с вычислением дат")] + public long UnixDate { get; set; } + + [Column("duration"), Comment("Кол-во секунд после предыдущей операции")] + public int Duration { get; set; } + [Column("id_operation")] public int? IdOperation { get; set; } diff --git a/AsbCloudInfrastructure/Services/AnalyticsService.cs b/AsbCloudInfrastructure/Services/AnalyticsService.cs index 8f4899f3..fb285600 100644 --- a/AsbCloudInfrastructure/Services/AnalyticsService.cs +++ b/AsbCloudInfrastructure/Services/AnalyticsService.cs @@ -60,9 +60,6 @@ namespace AsbCloudInfrastructure.Services { 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) @@ -70,8 +67,8 @@ namespace AsbCloudInfrastructure.Services var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId(telemetry.Id); - var drillingPeriodsInfo = db.GetDepthToInterval(telemetry.Id, (int)intervalTime.TotalSeconds, - (int)workDayBeginTime.TotalSeconds, timezoneOffset); + var drillingPeriodsInfo = db.GetDepthToInterval(telemetry.Id, intervalHoursTimestamp, + workBeginTimestamp, timezoneOffset); var wellDepthToIntervalData = drillingPeriodsInfo.Select(d => new WellDepthToIntervalDto { @@ -82,142 +79,68 @@ namespace AsbCloudInfrastructure.Services return wellDepthToIntervalData; } - public IEnumerable GetOperationsSummary(int wellId, + public IEnumerable GetOperationsSummary(int wellId, DateTime begin = default, DateTime end = default) { - return new List - { - 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 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 GetOperationsToTime(int wellId, - DateTime begin = default, DateTime end = default) + public IEnumerable GetOperationsToInterval(int wellId, + int intervalHoursTimestamp, int workBeginTimestamp) { - return new List - { - new OperationInfoDto - { - IntervalBegin = new DateTime(2021, 06, 01, 08, 00, 00), - IntervalEnd = new DateTime(2021, 06, 02, 08, 00, 00), - OperationData = new List - { - 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 - { - 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 - { - 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 - } - } - } - }; + 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 dataSaubBases) @@ -258,6 +181,8 @@ namespace AsbCloudInfrastructure.Services { 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), diff --git a/AsbCloudInfrastructure/Services/DataService.cs b/AsbCloudInfrastructure/Services/DataService.cs index a1d472f1..43c0c52b 100644 --- a/AsbCloudInfrastructure/Services/DataService.cs +++ b/AsbCloudInfrastructure/Services/DataService.cs @@ -103,8 +103,10 @@ namespace AsbCloudInfrastructure.Services if (saubDataCache.GetOrCreateCache(dataSaub.IdTelemetry).Count() > 1) { - var drillingAnalysis = analyticsService.GetDrillingAnalysis( - saubDataCache.GetOrCreateCache(dataSaub.IdTelemetry)); + var dataSaubs = saubDataCache.GetOrCreateCache(dataSaub.IdTelemetry) + .OrderBy(d => d.Date); + + var drillingAnalysis = analyticsService.GetDrillingAnalysis(dataSaubs); db.DrillingAnalysis.Add(drillingAnalysis); } diff --git a/AsbCloudWebApi/Controllers/AnalyticsController.cs b/AsbCloudWebApi/Controllers/AnalyticsController.cs index 85414b65..9a2fce2a 100644 --- a/AsbCloudWebApi/Controllers/AnalyticsController.cs +++ b/AsbCloudWebApi/Controllers/AnalyticsController.cs @@ -33,10 +33,7 @@ namespace AsbCloudWebApi.Controllers { int? idCustomer = User.GetCustomerId(); - if (idCustomer is null) - return Forbid(); - - if (!wellService.CheckWellOwnership((int)idCustomer, wellId)) + if (idCustomer is null || !wellService.CheckWellOwnership((int)idCustomer, wellId)) return Forbid(); var wellDepthToDayData = analyticsService.GetWellDepthToDay(wellId); @@ -54,17 +51,16 @@ namespace AsbCloudWebApi.Controllers [HttpGet] [Route("{wellId}/wellDepthToInterval")] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetWellDepthToInterval(int wellId, int intervalHoursTimestamp, int workBeginTimestamp) + public IActionResult GetWellDepthToInterval(int wellId, + int intervalHoursTimestamp, int workBeginTimestamp) { int? idCustomer = User.GetCustomerId(); - if (idCustomer is null) + if (idCustomer is null || !wellService.CheckWellOwnership((int)idCustomer, wellId)) return Forbid(); - if (!wellService.CheckWellOwnership((int)idCustomer, wellId)) - return Forbid(); - - var wellDepthToIntervalData = analyticsService.GetWellDepthToInterval(wellId, intervalHoursTimestamp, workBeginTimestamp); + var wellDepthToIntervalData = analyticsService.GetWellDepthToInterval(wellId, + intervalHoursTimestamp, workBeginTimestamp); return Ok(wellDepthToIntervalData); } @@ -78,15 +74,12 @@ namespace AsbCloudWebApi.Controllers /// Коллекцию операций на скважине [HttpGet] [Route("{wellId}/operationsSummary")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(IEnumerable), (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 Forbid(); - - if (!wellService.CheckWellOwnership((int)idCustomer, wellId)) + if (idCustomer is null || !wellService.CheckWellOwnership((int)idCustomer, wellId)) return Forbid(); var analytics = analyticsService.GetOperationsSummary(wellId, begin, end); @@ -98,24 +91,22 @@ namespace AsbCloudWebApi.Controllers /// Возвращает детальные данные по операциям на скважине за период /// /// id скважины - /// дата начала интервала - /// дата окончания интервала + /// количество секунд в необходимом интервале времени + /// количество секунд в времени начала смены /// Коллекцию операций на скважине [HttpGet] - [Route("{wellId}/operationsToTime")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetOperationsToTime(int wellId, DateTime begin = default, DateTime end = default) + [Route("{wellId}/operationsToInterval")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetOperationsToInterval(int wellId, + int intervalHoursTimestamp, int workBeginTimestamp) { int? idCustomer = User.GetCustomerId(); - if (idCustomer is null) + if (idCustomer is null || !wellService.CheckWellOwnership((int)idCustomer, wellId)) return Forbid(); - if (!wellService.CheckWellOwnership((int)idCustomer, wellId)) - return Forbid(); - - var analytics = analyticsService.GetOperationsToTime(wellId, begin, end); + var analytics = analyticsService.GetOperationsToInterval(wellId, intervalHoursTimestamp, workBeginTimestamp); return Ok(analytics); }