using AsbCloudApp.Data; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.DetectOperations { public class DetectedOperationService: IDetectedOperationService { private readonly IAsbCloudDbContext db; private readonly IWellService wellService; private readonly IOperationValueService operationValueService; private readonly IScheduleService scheduleService; public DetectedOperationService(IAsbCloudDbContext db, IWellService wellService, IOperationValueService operationValueService, IScheduleService scheduleService) { this.db = db; this.wellService = wellService; this.operationValueService = operationValueService; this.scheduleService = scheduleService; } public async Task GetAsync(int idWell, DetectedOperationRequest request, CancellationToken token) { var well = await wellService.GetAsync(idWell, token); if (well?.IdTelemetry is null || well.Timezone is null) return null; var res = new DetectedOperationListDto(); var query = BuildQuery(well, request) .AsNoTracking(); var data = await query.ToListAsync(token); var operationValues = await operationValueService.GetAllAsync(token); operationValues = operationValues.Where(o => o.IdWell == idWell); var dtos = data.Select(o => Convert(o, well, operationValues)); foreach (var item in dtos) { item.Driller = await scheduleService.GetDrillerAsync(idWell, item.DateStart); } var group = dtos.GroupBy(o => o.Driller == null ? 0 : o.Driller.Id, p => p, (key, gr) => (key, gr.ToList())).ToDictionary(e => e.key, e => e.Item2); res.List = dtos; res.Stats = new List(); foreach (var item in group) { var obj = new DetectedOperationStatDto(); obj.Driller = item.Value.FirstOrDefault()?.Driller; obj.Count = item.Value.Count(); obj.Average = item.Value.Sum(e=>e.OperationValue?.TargetValue ?? 0)/obj.Count; obj.Efficiency = 100d * item.Value.Count(e => PredicateTarget(e)(e.Value)) / obj.Count; obj.AverageByParam = item.Value.Sum(e => e.Value) / obj.Count; obj.Loss = item.Value .Where(e => !PredicateTarget(e)(e.Value)) .Sum(p => Math.Abs(p.Value - p.OperationValue?.TargetValue ?? 0)); res.Stats.Add(obj); } return res; } public async Task DeleteAsync(int idWell, DetectedOperationRequest request, CancellationToken token) { var well = await wellService.GetAsync(idWell, token); if (well?.IdTelemetry is null || well.Timezone is null) return 0; var query = BuildQuery(well, request); db.DetectedOperations.RemoveRange(query); return await db.SaveChangesAsync(token); } /// /// Определение применяемого предикат по типц операции /// /// Предикат для использования private static Predicate PredicateTarget(DetectedOperationDto op) { return op.OperationValue.IdOperationCategory switch { 1 => (x) => false, 11 => (x) => x > op.OperationValue.TargetValue, _ => (x) => true }; } private IQueryable BuildQuery(WellDto well, DetectedOperationRequest request) { if (well?.IdTelemetry is null || well.Timezone is null) return null; var query = db.Set() .Include(o => o.OperationCategory) .Where(o => o.IdTelemetry == well.IdTelemetry); if (request is not null) { if (request.CategoryIds is not null) query = query.Where(o => request.CategoryIds.Contains(o.IdCategory)); if (request.GtDate is not null) query = query.Where(o => o.DateStart >= request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours)); if (request.LtDate is not null) query = query.Where(o => o.DateEnd <= request.LtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours)); if (request.GtDepth is not null) query = query.Where(o => o.DepthStart >= request.GtDepth); if (request.LtDepth is not null) query = query.Where(o => o.DepthEnd <= request.LtDepth); if (request.EqIdTelemetryUser is not null) query = query.Where(o => o.IdUsersAtStart == request.EqIdTelemetryUser); } 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); return query; } private static DetectedOperationDto Convert(DetectedOperation operation, WellDto well, IEnumerable operationValues) { var dto = operation.Adapt(); dto.IdWell = well.Id; dto.DateStart = operation.DateStart.ToRemoteDateTime(well.Timezone.Hours); dto.DateEnd = operation.DateEnd.ToRemoteDateTime(well.Timezone.Hours); dto.OperationValue = operationValues.FirstOrDefault(e => e.IdOperationCategory == dto.IdCategory && e.DepthStart <= dto.DepthStart); return dto; } public async Task> GetCategoriesAsync(CancellationToken token) { var result = await db.WellOperationCategories .Where(c => c.Id < 1000) .Select(c => c.Adapt()) .ToArrayAsync(token); return result; } } }