using AsbCloudApp.Data.Subsystems; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudApp.Services.Subsystems; using AsbCloudDb; using AsbCloudDb.Model; using AsbCloudDb.Model.Subsystems; using Mapster; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.Subsystems { internal class SubsystemOperationTimeService : ISubsystemOperationTimeService { private readonly IAsbCloudDbContext db; private readonly IWellService wellService; private readonly SubsystemService subsystemService; public SubsystemOperationTimeService(IAsbCloudDbContext db, IWellService wellService, SubsystemService subsystemService) { this.db = db; this.wellService = wellService; this.subsystemService = subsystemService; } public async Task > GetSubsystemAsync(int idWell, CancellationToken token) { var well = await wellService.GetOrDefaultAsync(idWell, token); if (well?.IdTelemetry is null || well.Timezone is null) return null; var wellSubsystem = db.SubsystemOperationTimes .Include(e=>e.Subsystem) .AsNoTracking() .Where(o => o.IdTelemetry == well.IdTelemetry) .DistinctBy(o => o.IdSubsystem) .Select(d => new SubsystemDto { Id = d.Subsystem.Id, Name = d.Subsystem.Name, Description = d.Subsystem.Description, }); return wellSubsystem; } public async Task DeleteAsync(SubsystemOperationTimeRequest request, CancellationToken token) { var well = await wellService.GetOrDefaultAsync(request.IdWell, token); if (well?.IdTelemetry is null || well.Timezone is null) return 0; var query = BuildQuery(request); db.SubsystemOperationTimes.RemoveRange(query); return await db.SaveChangesAsync(token); } public async Task> GetOperationTimeAsync(SubsystemOperationTimeRequest request, CancellationToken token) { var query = BuildQuery(request) .AsNoTracking(); if (query is null) return null; var data = await query.ToListAsync(token); var dtos = data.Select(o => Convert(o)); return dtos; } public async Task?> GetStatAsync(SubsystemOperationTimeRequest request, CancellationToken token) { var query = BuildQuery(request) ?.AsNoTracking(); if (query is null) return null; var groupedData = await query .GroupBy(o => o.IdSubsystem) .ToListAsync(token); var statList = CalcStat(groupedData,request); return statList; } private IEnumerable CalcStat(List> groupedData, SubsystemOperationTimeRequest request) { var result = new List(); var periodGroupTotal = groupedData.Sum(g => g.Sum(o=> o.DateEnd.ToUnixTimeSeconds()-o.DateStart.ToUnixTimeSeconds())); foreach (IEnumerable item in groupedData) { var periodGroup = item.Sum(g => g.DateEnd.ToUnixTimeSeconds() - g.DateStart.ToUnixTimeSeconds()); var periodRequest = item.Where(o => o.DateStart==request.GtDate & o.DateEnd == request.LtDate) .Sum(o => o.DateEnd.ToUnixTimeSeconds() - o.DateStart.ToUnixTimeSeconds()); int idSubsystem = item.First().IdSubsystem; var subsystemStat = new SubsystemStatisticsDto() { IdSubsystem = idSubsystem, Subsystem = subsystemService.GetOrDefault(idSubsystem)?.Name ?? "unknown", UsedTime = ConvertToTimeSpan(periodGroup), KUsage = ConvertToTimeSpan(periodGroup / periodRequest), K2 = ConvertToTimeSpan(periodGroup / periodGroupTotal), }; result.Add(subsystemStat); } return result; } private TimeSpan ConvertToTimeSpan(long sec) { TimeSpan ts = TimeSpan.FromSeconds(sec); return ts; } private IQueryable? BuildQuery(SubsystemOperationTimeRequest request) { var idTelemetry = wellService.GetOrDefault(request.IdWell)?.IdTelemetry; if (idTelemetry is null) return null; var query = db.SubsystemOperationTimes .Include(o => o.Subsystem) .Where(o => o.IdTelemetry == idTelemetry); if(request.IdsSubsystems?.Any() == true) query = query.Where(o => request.IdsSubsystems.Contains(o.IdSubsystem)); switch(request.SelectMode) { case 0: case 2: if (request.GtDate is not null) query = query.Where(o => o.DateStart >= request.GtDate.Value||o.DateEnd >= request.GtDate.Value); if (request.LtDate is not null) query = query.Where(o => o.DateEnd <= request.LtDate.Value||o.DateStart <= request.LtDate.Value); break; case 1: if (request.GtDate is not null) query = query.Where(o => o.DateStart >= request.GtDate.Value); if (request.LtDate is not null) query = query.Where(o => o.DateEnd <= request.LtDate.Value); break; } if (request.GtDepth is not null) query = query.Where(o => o.DepthStart >= request.GtDepth.Value); if (request.LtDepth is not null) query = query.Where(o => o.DepthEnd <= request.LtDepth.Value); if (request?.SortFields?.Any() == true) { query = query.SortBy(request.SortFields); } else query = query .OrderBy(o => o.DateStart) .ThenBy(o => o.DepthStart); if (request?.Skip > 0) query = query.Skip((int)request.Skip); if (request?.Take > 0) query = query.Take((int)request.Take); else query = query.Take(3000); return query; } private SubsystemOperationTimeDto Convert(SubsystemOperationTime operationTime) { var dto = operationTime.Adapt(); return dto; } } }