using AsbCloudApp.Exceptions; using AsbCloudDb.Model; using AsbSaubReport.Model; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; namespace AsbCloudInfrastructure { #nullable enable public class ReportDataSourcePgCloud : IReportDataSource { private readonly IAsbCloudDbContext context; private readonly int? idTelemetry; private readonly WellInfoReport info; private readonly Dictionary events; private readonly Dictionary users; private readonly double timezoneOffset; private readonly Dictionary categories = new Dictionary { {1, "Авария"}, {2, "Предупреждение"}, {3, "Информация"}, }; public ReportDataSourcePgCloud(IAsbCloudDbContext context, int idWell) { this.context = context; var well = context.Wells .Include(w => w.Cluster) .ThenInclude(c => c.Deposit) .Include(w => w.RelationCompaniesWells) .ThenInclude(r => r.Company) .Include(w => w.Telemetry) .FirstOrDefault(w => w.Id == idWell); if(well is null) throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell)); idTelemetry = well?.IdTelemetry; if (idTelemetry is null) throw new ArgumentInvalidException($"Well {idWell} doesn't contain telemetry", nameof(idWell)); events = context.TelemetryEvents .Where(e => e.IdTelemetry == idTelemetry) .ToDictionary(e => e.IdEvent, e => e); users = context.TelemetryUsers .Where(u => u.IdTelemetry == idTelemetry) .ToDictionary(u => u.IdUser, u => u); timezoneOffset = well!.Telemetry?.Info?.TimeZoneOffsetTotalHours ?? well.Timezone?.Hours ?? 5.0; info = new WellInfoReport { Deposit = well.Cluster?.Deposit?.Caption, Cluster = well.Cluster?.Caption, Well = well.Caption, Customer = well.RelationCompaniesWells.FirstOrDefault(c => c.Company.IdCompanyType == 1)?.Company.Caption, DrillingStartDate = well.Telemetry?.Info?.DrillingStartDate.ToRemoteDateTime(timezoneOffset) ?? default, TimeZoneId = well.Telemetry?.Info?.TimeZoneId ?? well.Timezone?.TimezoneId ?? default, TimeZoneOffsetTotalHours = timezoneOffset, }; } public AnalyzeResult Analyze() { // TODO: Replace by linq methods. var messagesStat = (from item in context.TelemetryMessages where item.IdTelemetry == idTelemetry group item.DateTime by item.IdTelemetry into g select new { min = g.Min(), max = g.Max(), count = g.Count() }) .FirstOrDefault(); var dataStat = (from item in context.TelemetryDataSaub where item.IdTelemetry == idTelemetry group item.DateTime by item.IdTelemetry into g select new { min = g.Min(), max = g.Max(), count = g.Count() }) .FirstOrDefault(); var result = new AnalyzeResult { MinDate = dataStat?.min.UtcDateTime ?? messagesStat?.min.UtcDateTime ?? default, MaxDate = dataStat?.max.UtcDateTime ?? messagesStat?.max.UtcDateTime ?? default, MessagesCount = messagesStat?.count ?? 0, }; return result; } public IQueryable GetDataSaubItems(DateTime begin, DateTime end) { var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); var query = context.TelemetryDataSaub .Where(d => d.IdTelemetry == idTelemetry && d.DateTime >= beginUtc && d.DateTime <= endUtc) .OrderBy(d => d.DateTime) .Select(d => new DataSaubReport { Date = d.DateTime.DateTime.AddHours(timezoneOffset), Mode = d.Mode, WellDepth = d.WellDepth, BitDepth = d.BitDepth, BlockPosition = d.BlockPosition, BlockSpeed = d.BlockSpeed, BlockSpeedSp = d.BlockSpeedSp, BlockSpeedSpDevelop = d.BlockSpeedSpDevelop, Pressure = d.Pressure, PressureSp = d.PressureSp, AxialLoad = d.AxialLoad, AxialLoadSp = d.AxialLoadSp, AxialLoadLimitMax = d.AxialLoadLimitMax, HookWeight = d.HookWeight, RotorTorque = d.RotorTorque, RotorTorqueSp = d.RotorTorqueSp, RotorSpeed = d.RotorSpeed, Flow = d.Flow, PressureSpDevelop = d.PressureSpDevelop, }); return query; } public IQueryable GetMessages(DateTime begin, DateTime end) { var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); var query = from item in context.TelemetryMessages where item.IdTelemetry == idTelemetry && item.DateTime >= beginUtc && item.DateTime <= endUtc orderby item.DateTime select new MessageReport { Id = item.Id, Date = item.DateTime.DateTime, Category = events.GetValueOrDefault(item.IdEvent) == null ? $"" : categories[events[item.IdEvent].IdCategory], User = item.IdTelemetryUser == null ? "" : users.GetValueOrDefault((int)item.IdTelemetryUser) == null ? $"User id{item.IdTelemetryUser}" : users[(int)item.IdTelemetryUser].MakeDisplayName(), Text = events.GetValueOrDefault(item.IdEvent) == null ? $"Событие {item.IdEvent} {item.Arg0} {item.Arg1} {item.Arg2} {item.Arg3}" : events[item.IdEvent].MakeMessageText(item) }; return query; } public WellInfoReport GetWellInfo() => info; } #nullable disable }