using AsbCloudApp.Data.GTR; using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudDb.Model.GTR; using Mapster; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Repository { #nullable enable public class GtrWitsRepository : IGtrRepository { private readonly IAsbCloudDbContext db; private readonly ITelemetryService telemetryService; public GtrWitsRepository( IAsbCloudDbContext db, ITelemetryService telemetryService) { this.db = db; this.telemetryService = telemetryService; } public async Task> GetAsync(int idWell, DateTime dateBegin = default, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default) { var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); if (telemetry is null) return Enumerable.Empty(); var timezone = telemetryService.GetTimezone(telemetry.Id); var filterByDateEnd = dateBegin != default; DateTimeOffset dateBeginUtc; if (dateBegin == default) { dateBeginUtc = telemetryService.GetLastTelemetryDate(telemetry.Id) .ToUtcDateTimeOffset(timezone.Hours); if (dateBeginUtc != default) dateBeginUtc = dateBeginUtc.AddSeconds(-intervalSec); } else { dateBeginUtc = dateBegin.ToUtcDateTimeOffset(timezone.Hours); } if (dateBeginUtc == default) dateBeginUtc = DateTime.UtcNow.AddSeconds(-intervalSec); //var cacheData = telemetryDataCache.GetOrDefault(telemetry.Id, dateBeginUtc.ToRemoteDateTime(timezone.Hours), intervalSec, approxPointsCount); //if (cacheData is not null) // return cacheData; var dateEnd = dateBeginUtc.AddSeconds(intervalSec); var queryWitsInt = db.Set() .Where(d => d.IdTelemetry == telemetry.Id && d.DateTime >= dateBeginUtc); var queryWitsString = db.Set() .Where(d => d.IdTelemetry == telemetry.Id && d.DateTime >= dateBeginUtc); var queryWitsFloat = db.Set() .Where(d => d.IdTelemetry == telemetry.Id && d.DateTime >= dateBeginUtc); var recordAllInt = await GetEntityAsync(queryWitsInt, dateEnd, filterByDateEnd, approxPointsCount, token); var recordAllFloat = await GetEntityAsync(queryWitsFloat, dateEnd, filterByDateEnd, approxPointsCount, token); var recordAllString = await GetEntityAsync(queryWitsString, dateEnd, filterByDateEnd, approxPointsCount, token); var dtos = new List(); if (recordAllInt.Any()) { WriteItem(dtos, recordAllInt, timezone.Hours); } if (recordAllString.Any()) { WriteItem(dtos, recordAllString, timezone.Hours); } if (recordAllFloat.Any()) { WriteItem(dtos, recordAllFloat, timezone.Hours); } return dtos; } public async Task SaveDataAsync(int idTelemetry, WitsRecordDto dto, CancellationToken token) { if (dto is null) return; var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; foreach (var item in dto.Items) { var jsonValue = item.Value; if(jsonValue.Value is string valueString) { var entity = GetEntity(dto, valueString, item.Key, timezoneHours); db.WitsItemString.Add(entity.Adapt()); } if (jsonValue.Value is float valueFloat) { var entity = GetEntity(dto, valueFloat, item.Key, timezoneHours); db.WitsItemFloat.Add(entity.Adapt()); } if (jsonValue.Value is int valueInt) { var entity = GetEntity(dto, valueInt, item.Key, timezoneHours); db.WitsItemInt.Add(entity.Adapt()); } } await db.SaveChangesAsync(token); } private static async Task>> GetEntityAsync(IQueryable> query, DateTimeOffset dateEnd, bool filterByDateEnd, int approxPointsCount , CancellationToken token) { //if (filterByDateEnd) // query = query.Where(d => d.DateTime <= dateEnd); //var fullDataCount = await query.CountAsync(token) // .ConfigureAwait(false); //if (fullDataCount == 0) // return Enumerable.Empty(); //if (fullDataCount > 1.75 * approxPointsCount) //{ // var m = (int)Math.Round(1d * fullDataCount / approxPointsCount); // if (m > 1) // query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0); //} var entities = await query .OrderBy(d => d.DateTime) .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); return entities; } private static WitsItemBase GetEntity(WitsRecordDto record, Tvalue value, int idItems, double timezoneHours) { var entity = new WitsItemBase { IdTelemetry = record.IdTelemetry, DateTime = record.Date.ToUtcDateTimeOffset(timezoneHours), IdRecord = record.Id, IdItem = idItems, Value = value, }; return entity; } private static void WriteItem (List dtos, IEnumerable> recordAll, double timezoneHours) { foreach (var record in recordAll) { var existingDto = dtos.Where(r => r.Id == record.IdRecord) .Where(r => r.Date.ToUtcDateTimeOffset(timezoneHours) == record.DateTime) .FirstOrDefault(); if (existingDto is null) { var dto = new WitsRecordDto { IdTelemetry = record.IdTelemetry, Id = record.IdRecord, Date = record.DateTime.ToRemoteDateTime(timezoneHours), }; dto.Items.Add(record.IdItem, new JsonValue(record.Value!)); dtos.Add(dto); } else { existingDto.Items.Add(record.IdItem, new JsonValue(record.Value!)); } } } } #nullable disable }