DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/WellSectionService.cs

346 lines
16 KiB
C#

using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
using System.Threading;
using AsbCloudInfrastructure.Services.Cache;
namespace AsbCloudInfrastructure.Services
{
public class WellSectionService: IWellSectionService
{
private readonly IAsbCloudDbContext db;
private readonly CacheTable<WellSectionType> cachedSectionsTypes;
public WellSectionService(IAsbCloudDbContext db, Cache.CacheDb cache)
{
this.db = db;
cachedSectionsTypes = cache.GetCachedTable<WellSectionType>((DbContext)db);
}
public Task<string[]> GetTypesAsync(CancellationToken token) =>
db.WellSectionTypes.Select(e => e.Caption).Distinct().AsNoTracking().ToArrayAsync(token);
public async Task<PaginationContainer<WellSectionDto>> GetSectionsByWellIdAsync(int idWell,
int skip, int take, CancellationToken token = default)
{
var wellOperations = await (from w in db.WellOperations
where w.IdWell == idWell
select w)
.Include(w => w.WellSectionType)
.ToListAsync(token)
.ConfigureAwait(false);
var wellOperationsGroupedBySections = wellOperations
.GroupBy(op => op.IdWellSectionType).ToList();
if (skip > 0)
wellOperationsGroupedBySections = wellOperationsGroupedBySections.Skip(skip).ToList();
wellOperationsGroupedBySections = wellOperationsGroupedBySections.Take(take).ToList();
var result = new PaginationContainer<WellSectionDto>
{
Skip = skip,
Take = take,
Count = wellOperationsGroupedBySections.Count
};
if (!wellOperationsGroupedBySections.Any())
return result;
var depthsPlanFactList = GetWellDepthPlanFact(wellOperationsGroupedBySections).ToList();
var durationsPlanFactList = GetWellDurationPlanFact(wellOperationsGroupedBySections).ToList();
var mechSpeedsList = GetWellMechSpeedPlanFact(wellOperationsGroupedBySections).ToList();
var bhaUpSpeedList = GetWellBhaUpSpeedPlanFact(wellOperationsGroupedBySections).ToList();
var bhaDownSpeedList = GetWellBhaDownSpeedPlanFact(wellOperationsGroupedBySections).ToList();
var casingDownList = GetWellCasingDownPlanFact(wellOperationsGroupedBySections).ToList();
var routeSpeeds = GetWellRouteSpeedsPlanFact(wellOperationsGroupedBySections).ToList();
var dtos = new List<WellSectionDto>();
for(int i = 0; i < wellOperationsGroupedBySections.Count; i++)
{
var dto = new WellSectionDto
{
SectionType = wellOperationsGroupedBySections[i]
.FirstOrDefault().WellSectionType.Caption,
WellDepthPlan = depthsPlanFactList[i].DepthPlan,
WellDepthFact = depthsPlanFactList[i].DepthFact,
DurationPlan = durationsPlanFactList[i].DurationPlan,
DurationFact = durationsPlanFactList[i].DurationFact,
MechSpeedPlan = mechSpeedsList[i].MechSpeedPlan,
MechSpeedFact = mechSpeedsList[i].MechSpeedFact,
BhaUpSpeedPlan = bhaUpSpeedList[i].BhaUpSpeedPlan,
BhaUpSpeedFact = bhaUpSpeedList[i].BhaUpSpeedFact,
BhaDownSpeedPlan = bhaDownSpeedList[i].BhaDownSpeedPlan,
BhaDownSpeedFact = bhaDownSpeedList[i].BhaDownSpeedFact,
CasingDownSpeedPlan = casingDownList[i].CasingDownSpeedPlan,
CasingDownSpeedFact = casingDownList[i].CasingDownSpeedFact,
RouteSpeedPlan = routeSpeeds[i].RouteSpeedPlan,
RouteSpeedFact = routeSpeeds[i].RouteSpeedFact
};
dtos.Add(dto);
}
result.Items = dtos;
return result;
}
public async Task<WellSectionDto> GetSectionByWellIdAsync(int id, CancellationToken token = default)
{
var entity = await db.WellSections
.Include(s => s.WellSectionType)
.FirstOrDefaultAsync(e => e.Id == id, token)
.ConfigureAwait(false);
if (entity is null)
return null;
var dto = entity.Adapt<WellSectionDto>();
dto.SectionType = entity.WellSectionType.Caption;
return dto;
}
//public async Task<WellSectionDto> InsertAsync(WellSectionDto item, int idWell, CancellationToken token = default)
//{
// var sectionType = await GetWellSectionTypeFromCacheAndAssertAsync(item.SectionType);
// var entity = item.Adapt<WellSection>();
// entity.Id = default;
// entity.IdWell = idWell;
// entity.IdWellSectionType = sectionType.Id;
// var dbEntity = dbSet.Add(entity);
// await context.SaveChangesAsync(token).ConfigureAwait(false);
// var dto = dbEntity.Entity.Adapt<WellSectionDto>();
// dto.SectionType = sectionType.Caption;
// return dto;
//}
//public async Task<IEnumerable<WellSectionDto>> InsertRangeAsync(int idWell, IEnumerable<WellSectionDto> items, CancellationToken token = default)
//{
// var dbEntities = new Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<WellSection>[items.Count()];
// for (int i = 0; i < dbEntities.Length; i++)
// {
// var sectionType = await GetWellSectionTypeFromCacheAndAssertAsync(items.ElementAt(i).SectionType, token);
// var item = items.ElementAt(i).Adapt<WellSection>();
// item.IdWell = idWell;
// item.IdWellSectionType = sectionType.Id;
// dbEntities[i] = dbSet.Add(item);
// }
// await context.SaveChangesAsync(token).ConfigureAwait(false);
// var dtos = dbEntities.Select((e) => {
// var dto = e.Entity.Adapt<WellSectionDto>();
// var sectionType = cachedSectionsTypes.FirstOrDefault(s => s.Id == e.Entity.IdWellSectionType);
// dto.SectionType = sectionType.Caption;
// return dto;
// });
// return dtos;
//}
//public async Task<WellSectionDto> UpdateAsync(int idWell, int idSection, WellSectionDto item, CancellationToken token = default)
//{
// var sectionType = await GetWellSectionTypeFromCacheAndAssertAsync(item.SectionType, token)
// .ConfigureAwait(false);
// var entity = item.Adapt<WellSection>();
// entity.Id = idSection;
// entity.IdWell = idWell;
// entity.IdWellSectionType = sectionType.Id;
// var dbEntity = dbSet.Update(entity);
// await context.SaveChangesAsync(token).ConfigureAwait(false);
// var dto = dbEntity.Entity.Adapt<WellSectionDto>();
// dto.SectionType = sectionType.Caption;
// return dto;
//}
//public Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token = default)
//{
// var entities = dbSet.Where(e => ids.Contains(e.Id));
// dbSet.RemoveRange(entities);
// return context.SaveChangesAsync(token);
//}
private static IEnumerable<(double DepthPlan, double DepthFact)> GetWellDepthPlanFact(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations)
{
return groupedOperations
.Select(group =>
(
DepthPlan: group.Where(o => o.IdType == 0).Max(w => w.WellDepth),
DepthFact: group.Where(o => o.IdType == 1).Max(w => w.WellDepth)
));
}
private static IEnumerable<(double DurationPlan, double DurationFact)> GetWellDurationPlanFact(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations)
{
var durationsPlanFactsBase = groupedOperations.Select(group => new
{
DurationMaxPlan = group.Where(o => o.IdType == 0).Select(op => op.StartDate +
TimeSpan.FromHours(op.DurationHours)).Max(),
DurationMinPlan = group.Where(o => o.IdType == 0).Min(i => i.StartDate),
DurationMaxFact = group.Where(o => o.IdType == 1).Select(op => op.StartDate +
TimeSpan.FromHours(op.DurationHours)).Max(),
DurationMinFact = group.Where(o => o.IdType == 1).Min(i => i.StartDate)
});
return durationsPlanFactsBase.Select(o =>
(
DurationPlan: (o.DurationMaxPlan - o.DurationMinPlan).TotalHours,
DurationFact: (o.DurationMaxFact - o.DurationMinFact).TotalHours
));
}
private static IEnumerable<(double MechSpeedPlan, double MechSpeedFact)> GetWellMechSpeedPlanFact(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations)
{
var mechSpeedBase = GetParams(groupedOperations, 1018);
return CalculateResult(mechSpeedBase);
}
private static IEnumerable<(double BhaUpSpeedPlan, double BhaUpSpeedFact)> GetWellBhaUpSpeedPlanFact(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations)
{
var bhaUpSpeedBase = GetParams(groupedOperations, 1072);
return CalculateResult(bhaUpSpeedBase);
}
private static IEnumerable<(double BhaDownSpeedPlan, double BhaDownSpeedFact)> GetWellBhaDownSpeedPlanFact(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations)
{
var bhaDownSpeedBase = GetParams(groupedOperations, 1071);
return CalculateResult(bhaDownSpeedBase);
}
private static IEnumerable<(double CasingDownSpeedPlan, double CasingDownSpeedFact)> GetWellCasingDownPlanFact(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations)
{
var casingDownBase = GetParams(groupedOperations, 1074);
return CalculateResult(casingDownBase);
}
private static IEnumerable<(double RouteSpeedPlan, double RouteSpeedFact)> GetWellRouteSpeedsPlanFact(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations)
{
var bhaRaiseDecreaseCollection = new List<(WellOperation FirstBhaPositionDecreasePlan,
WellOperation LastBhaPositionIncreasePlan,
WellOperation FirstBhaPositionDecreaseFact,
WellOperation LastBhaPositionIncreaseFact)>();
foreach (var group in groupedOperations)
{
var firstBhaPositionDecreasePlan = group.Any(o => o.IdCategory == 1071 && o.IdType == 0)
? group.First(o => o.IdCategory == 1071 && o.IdType == 0)
: null;
var lastBhaPositionIncreasePlan = group.Any(o => o.IdCategory == 1072 && o.IdType == 0)
? group.Last(o => o.IdCategory == 1072 && o.IdType == 0)
: null;
var firstBhaPositionDecreaseFact = group.Any(o => o.IdCategory == 1071 && o.IdType == 1)
? group.First(o => o.IdCategory == 1071 && o.IdType == 1)
: null;
var lastBhaPositionIncreaseFact = group.Any(o => o.IdCategory == 1072 && o.IdType == 1)
? group.Last(o => o.IdCategory == 1072 && o.IdType == 1)
: null;
bhaRaiseDecreaseCollection.Add((firstBhaPositionDecreasePlan,
lastBhaPositionIncreasePlan, firstBhaPositionDecreaseFact,
lastBhaPositionIncreaseFact));
}
var routeSpeedsBase = bhaRaiseDecreaseCollection.Select(el =>
(
RouteDepthPlan: (el.FirstBhaPositionDecreasePlan?.WellDepth - el.LastBhaPositionIncreasePlan?.WellDepth) ?? 0,
RouteDepthFact: (el.FirstBhaPositionDecreaseFact?.WellDepth - el.LastBhaPositionIncreaseFact?.WellDepth) ?? 0,
RouteDurationPlan: (el.LastBhaPositionIncreasePlan?.StartDate +
TimeSpan.FromHours(el.LastBhaPositionIncreasePlan?.DurationHours ?? 0) -
el.FirstBhaPositionDecreasePlan?.StartDate)?.TotalHours ?? 0,
RouteDurationFact: (el.LastBhaPositionIncreaseFact?.StartDate +
TimeSpan.FromHours(el.LastBhaPositionIncreaseFact?.DurationHours ?? 0) -
el.FirstBhaPositionDecreaseFact?.StartDate)?.TotalHours ?? 0
));
return CalculateResult(routeSpeedsBase);
}
private static IEnumerable<(double DepthDifferencePlanSum,
double DurationDifferencePlanSum, double DepthDifferenceFactSum,
double DurationDifferenceFactSum)> GetParams(IEnumerable<IGrouping<int, WellOperation>> items,
int IdCategory)
{
return items.Select(g =>
(
DepthDifferencePlanSum: g.Where(o => o.IdType == 0 && o.IdCategory == IdCategory)
.Select((el, i) => i > 0 ? el.WellDepth - g.ElementAt(i - 1).WellDepth : 0).Sum(),
DurationDifferencePlanSum: g.Where(o => o.IdType == 0 && o.IdCategory == IdCategory)
.Select(el => el.DurationHours).Sum(),
DepthDifferenceFactSum: g.Where(o => o.IdType == 1 && o.IdCategory == IdCategory)
.Select((el, i) => i > 0 ? el.WellDepth - g.ElementAt(i - 1).WellDepth : 0).Sum(),
DurationDifferenceFactSum: g.Where(o => o.IdType == 1 && o.IdCategory == IdCategory)
.Select(el => el.DurationHours).Sum()
));
}
private static IEnumerable<(double DataPlan, double DataFact)> CalculateResult(IEnumerable<(double Item1Plan,
double Item1Fact, double Item2Plan, double Item2Fact)> rawData)
{
return rawData.Select(el =>
(
RouteSpeedPlan: (el.Item1Plan / el.Item2Plan) is double.NaN
? 0
: (el.Item1Plan / el.Item2Plan),
RouteSpeedFact: (el.Item1Fact / el.Item2Fact) is double.NaN
? 0
: (el.Item1Fact / el.Item2Fact)
));
}
private async Task<WellSectionType> GetWellSectionTypeFromCacheAndAssertAsync(string wellSectionType, CancellationToken token = default)
{
if (string.IsNullOrEmpty(wellSectionType))
throw new ArgumentException("Тип секции должен быть указан", nameof(WellSectionDto.SectionType));
var sectionType = await cachedSectionsTypes
.FirstOrDefaultAsync(s => s.Caption.Equals(wellSectionType, StringComparison.OrdinalIgnoreCase), token)
.ConfigureAwait(false);
if (sectionType is null)
{
throw new ArgumentException($"Тип секции '{wellSectionType}' отсутствует в справочнике", nameof(WellSectionDto.SectionType));
//sectionType = await cachedSectionsTypes.InsertAsync(new WellSectionType { Caption = item.SectionType}, token);
}
return sectionType;
}
}
}