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 { private readonly IAsbCloudDbContext db; private readonly ITelemetryService telemetryService; private static Random random = new Random((int)(DateTime.Now.Ticks % 0xFFFFFFFF)); 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.WitsItemInt .Where(d => d.IdTelemetry == telemetry.Id && d.DateTime >= dateBeginUtc); var queryWitsStr = db.WitsItemString .Where(d => d.IdTelemetry == telemetry.Id && d.DateTime >= dateBeginUtc); var queryWitsFloat = db.WitsItemFloat .Where(d => d.IdTelemetry == telemetry.Id && d.DateTime >= dateBeginUtc); var recordAllInt = GetEntityIntAsync(queryWitsInt, dateEnd, filterByDateEnd, approxPointsCount, token).Result; var recordAllFloat = GetEntityFloatAsync(queryWitsFloat, dateEnd, filterByDateEnd, approxPointsCount, token).Result; var recordAllStr = GetEntityStrAsync(queryWitsStr, dateEnd, filterByDateEnd, approxPointsCount, token).Result; var dtos = new List(); if (recordAllInt.Any()) { foreach (var record in recordAllInt) { var existingDto = dtos.Where(r => r.Id == record.IdRecord) .Where(r => r.Date.ToUtcDateTimeOffset(timezone.Hours) == record.DateTime) .FirstOrDefault(); if (existingDto is null) { var dto = new WitsRecordDto { IdTelemetry = record.IdTelemetry, Id = record.IdRecord, Date = record.DateTime.ToRemoteDateTime(timezone.Hours), }; dto.Items.Add(record.IdItem, new JsonValue(record.Value!)); dtos.Add(dto); } else { existingDto.Items.Add(record.IdItem, new JsonValue(record.Value!)); } } } if (recordAllStr.Any()) { foreach (var record in recordAllStr) { var existingDto = dtos.Where(r => r.Id == record.IdRecord) .Where(r => r.Date.ToUtcDateTimeOffset(timezone.Hours) == record.DateTime) .FirstOrDefault(); if (existingDto is null) { var dto = new WitsRecordDto { IdTelemetry = record.IdTelemetry, Id = record.IdRecord, Date = record.DateTime.ToRemoteDateTime(timezone.Hours), }; dto.Items.Add(record.IdItem, new JsonValue(record.Value!)); dtos.Add(dto); } else { existingDto.Items.Add(record.IdItem, new JsonValue(record.Value!)); } } } if (recordAllFloat.Any()) { foreach (var record in recordAllStr) { var existingDto = dtos .Where(r => r.Id == record.IdRecord) .Where(r => r.Date.ToUtcDateTimeOffset(timezone.Hours) == record.DateTime) .FirstOrDefault(); if (existingDto is null) { var dto = new WitsRecordDto { IdTelemetry = record.IdTelemetry, Id = record.IdRecord, Date = record.DateTime.ToRemoteDateTime(timezone.Hours), }; dto.Items.Add(record.IdItem, new JsonValue(record.Value!)); dtos.Add(dto); } else { existingDto.Items.Add(record.IdItem, new JsonValue(record.Value!)); } } } 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 async Task> GetEntityIntAsync(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 async Task> GetEntityFloatAsync(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 async Task> GetEntityStrAsync(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 void 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; //} } #nullable disable }