using AsbCloudApp.Data.GTR; using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudDb.Model.GTR; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Repository { #nullable enable public class GtrWitsRepository : IGtrRepository where TEntity : WitsItemBase { private readonly IAsbCloudDbContext db; private readonly ITelemetryService telemetryService; private readonly DbSet dbset; private static Random random = new Random((int)(DateTime.Now.Ticks % 0xFFFFFFFF)); public GtrWitsRepository( IAsbCloudDbContext db, ITelemetryService telemetryService) { dbset = db.Set(); 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 dbSet = db.Set(); var query = dbSet .Where(d => d.IdTelemetry == telemetry.Id && d.DateTime >= dateBeginUtc); 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); var groupRecord = entities .GroupBy(g => g.IdRecord) .ToList(); var dtos = new List(); foreach(var group in groupRecord) { var dto = GetDto(group, telemetry.Id, timezone.Hours); dtos.Add(dto); } return dtos; } public async Task SaveDataAsync(int idTelemetry, WitsRecordDto dto, CancellationToken token) { if (dto is null) return; var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; var entities = GetEntities(dto,idTelemetry,timezoneHours); var dateMin = entities.Min(e => e.DateTime); var dateMax = entities.Max(e => e.DateTime); var existingEntities = await dbset .Where(e => e.IdTelemetry == idTelemetry) .Where(e => e.DateTime >= dateMin && e.DateTime <= dateMax) .Select(e => e.DateTime) .OrderBy(d => d) .ToArrayAsync(token); foreach (var entity in entities) { if (!existingEntities.Any(e => e == entity.DateTime)) { dbset.Add((TEntity)entity); } else { var dt = entity.DateTime; entity.DateTime = new DateTimeOffset( dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (dt.Millisecond + random.Next(1, 283)) % 1000, dt.Offset); dbset.Add((TEntity)entity); } } await db.SaveChangesAsync(token); } private static IEnumerable> GetEntities(WitsRecordDto recordItems, int idTelemetry, double timezoneHours) { var itemsCount = recordItems.Items.Count; var entities = new List>(itemsCount); foreach (var dtoItems in recordItems.Items) { var entityItems = new WitsItemBase { IdTelemetry = idTelemetry, DateTime = recordItems.Date.ToUtcDateTimeOffset(timezoneHours), IdRecord = recordItems.Id, IdItem = dtoItems.Key, Value = System.Text.Json.JsonSerializer.Deserialize(dtoItems.Value.ToString()) }; entities.Add(entityItems); } return entities; } private static WitsRecordDto GetDto(IEnumerable> entities, int idTelemetry, double timezoneHours) { var entity = entities.First(); var dto = new WitsRecordDto { Id = entity.IdRecord, Date = entity.DateTime.ToRemoteDateTime(timezoneHours), IdTelemetry = idTelemetry }; foreach (var entityItems in entities) { var valueItem = new JsonValue(entityItems.Value!); dto.Items.Add(entityItems.IdItem, valueItem); } return dto; } } #nullable disable }