forked from ddrilling/AsbCloudServer
346 lines
16 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|