All statisstic moved to WellOperationStatService.

Stats reorganized
This commit is contained in:
Фролов 2021-08-24 16:47:10 +05:00
parent 8ad8155224
commit 94b7dd3ef7
17 changed files with 257 additions and 513 deletions

View File

@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace AsbCloudApp.Data
{
public class ClusterStatDto : ClusterDto
{
public IEnumerable<WellStatDto> WellsStat { get; set; }
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace AsbCloudApp.Data
{
public class StatClusterDto : ClusterDto
{
public List<StatOperationDto> Sections { get; set; }
public List<StatOperationDto> WellsTotals { get; set; }
}
}

View File

@ -0,0 +1,57 @@
using System;
namespace AsbCloudApp.Data
{
public class StatOperationBase
{
/// <summary>
/// Дата и время начала
/// </summary>
public DateTime Start { get; set; }
/// <summary>
/// Дата и время окончания
/// </summary>
public DateTime End { get; set; }
/// <summary>
/// Глубина, м
/// </summary>
public double WellDepthStart { get; set; }
/// <summary>
/// Глубина, м
/// </summary>
public double WellDepthEnd { get; set; }
/// <summary>
/// Рейсовая скорость, м/час
/// </summary>
public double RouteSpeed { get; set; }
/// <summary>
/// Механическая скорость проходки, м/час
/// </summary>
public double Rop { get; set; }
/// <summary>
/// Скорость подъема КНБК
/// </summary>
public double BhaUpSpeed { get; set; }
/// <summary>
/// Скорость спуска КНБК
/// </summary>
public double BhaDownSpeed { get; set; }
/// <summary>
/// Скорость спуска обсадной колонны
/// </summary>
public double CasingDownSpeed { get; set; }
/// <summary>
/// Непроизводительное время
/// </summary>
public double NonProductiveHours { get; set; }
}
}

View File

@ -0,0 +1,10 @@
namespace AsbCloudApp.Data
{
public class StatOperationDto: IId
{
public int Id { get; set; }
public string Caption { get; set; }
public StatOperationBase Plan { get; set; }
public StatOperationBase Fact { get; set; }
}
}

View File

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace AsbCloudApp.Data
{
public class StatWellDto : WellDto
{
public IEnumerable<StatOperationDto> Sections { get; set; }
public StatOperationDto Total { get; set; }
public IEnumerable<CompanyDto> Companies { get; set; }
}
}

View File

@ -1,81 +0,0 @@
namespace AsbCloudApp.Data
{
public class WellSectionDto : IId
{
public int Id { get; set; }
/// <summary>
/// Конструкция секции
/// </summary>
public string SectionType { get; set; }
/// <summary>
/// Глубина план, м
/// </summary>
public double WellDepthPlan { get; set; }
/// <summary>
/// Глубина факт, м
/// </summary>
public double WellDepthFact { get; set; }
/// <summary>
/// Период план, д
/// </summary>
public double DurationPlan { get; set; }
/// <summary>
/// Период факт, д
/// </summary>
public double DurationFact { get; set; }
/// <summary>
/// Механическая скорость проходки план, м/час
/// </summary>
public double MechSpeedPlan { get; set; }
/// <summary>
/// Механическая скорость проходки факт, м/час
/// </summary>
public double MechSpeedFact { get; set; }
/// <summary>
/// Рейсовая скорость план, м/час
/// </summary>
public double RouteSpeedPlan { get; set; }
/// <summary>
/// Рейсовая скорость план, м/час
/// </summary>
public double RouteSpeedFact { get; set; }
/// <summary>
/// Скорость подъема КНБК план
/// </summary>
public double BhaUpSpeedPlan { get; set; }
/// <summary>
/// Скорость подъема КНБК факт
/// </summary>
public double BhaUpSpeedFact { get; set; }
/// <summary>
/// Скорость спуска КНБК план
/// </summary>
public double BhaDownSpeedPlan { get; set; }
/// <summary>
/// Скорость спуска КНБК факт
/// </summary>
public double BhaDownSpeedFact { get; set; }
/// <summary>
/// Скорость спуска обсадной колонны план
/// </summary>
public double CasingDownSpeedPlan { get; set; }
/// <summary>
/// Скорость спуска обсадной колонны факт
/// </summary>
public double CasingDownSpeedFact { get; set; }
}
}

View File

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
namespace AsbCloudApp.Data
{
public class WellStatDto : WellDto
{
public DateTime? PlanStart { get; set; }
public DateTime? PlanEnd { get; set; }
public DateTime? FactStart { get; set; }
public DateTime? FactEnd { get; set; }
public double? UnProductiveDays { get; set; }
public double? RateOfPenetrationPlan { get; set; }
public double? RateOfPenetrationFact { get; set; }
public double? RouteSpeedPlan { get; set; }
public double? RouteSpeedFact { get; set; }
public IEnumerable<WellSectionDto> Sections { get; set; }
public IEnumerable<CompanyDto> Companies { get; set; }
}
}

View File

@ -15,7 +15,5 @@ namespace AsbCloudApp.Services
CancellationToken token);
Task<IEnumerable<WellDto>> GetWellsAsync(int idCompany,
int clusterId, CancellationToken token);
Task<ClusterStatDto> GetStatAsync(int idCompany,
int clusterId, CancellationToken token);
}
}

View File

@ -0,0 +1,13 @@
using AsbCloudApp.Data;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
public interface IWellOperationsStatService
{
Task<StatClusterDto> GetOperationStatByClusterAsync(int idCluster, CancellationToken token = default);
Task<StatWellDto> GetOperationStatByWellAsync(int idWell, CancellationToken token = default);
}
}

View File

@ -1,14 +0,0 @@
using AsbCloudApp.Data;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
public interface IWellSectionService
{
Task<IEnumerable<WellSectionDto>> GetSectionsByWellIdAsync(int idWell,
CancellationToken token = default);
}
}

View File

@ -36,8 +36,8 @@ namespace AsbCloudInfrastructure
services.AddTransient<IReportService, ReportService>();
services.AddTransient<ITelemetryAnalyticsService, TelemetryAnalyticsService>();
services.AddTransient<IFileService, FileService>();
services.AddTransient<IWellSectionService, WellSectionService>();
services.AddTransient<IWellOperationService, WellOperationService>();
services.AddTransient<IWellOperationsStatService, WellOperationsStatService>();
services.AddTransient<ILastDataService<FluidDataDto>, LastDataService<FluidDataDto, FluidData>>();
services.AddTransient<ILastDataService<MudDiagramDataDto>, LastDataService<MudDiagramDataDto, MudDiagramData>>();

View File

@ -128,49 +128,5 @@ namespace AsbCloudInfrastructure.Services
return dtos;
}
public async Task<ClusterStatDto> GetStatAsync(int idCompany,
int idCluster, CancellationToken token = default)
{
var wellEntities = from w in db.Wells
where w.IdCluster == idCluster && w.RelationCompaniesWells.Any(c => c.IdCompany == idCompany)
select w;
var wellStatDtos = await wellEntities.Select(e => new WellStatDto
{
Id = e.Id,
Caption = e.Caption,
Cluster = e.Cluster.Caption,
Deposit = e.Cluster.Deposit.Caption,
Latitude = e.Latitude,
Longitude = e.Longitude,
//TODO: Fill data from operations service
Companies = e.RelationCompaniesWells.Select(c => new CompanyDto
{
Id = c.Company.Id,
Caption = c.Company.Caption,
CompanyType = c.Company.CompanyType.Caption,
}),
WellType = e.WellType.Caption,
}).AsNoTracking().ToListAsync(token)
.ConfigureAwait(false);
if (!wellStatDtos.Any())
return null;
var clusterById = await db.Clusters.AsNoTracking()
.FirstOrDefaultAsync(c => c.Id == idCluster, token)
.ConfigureAwait(false);
return new ClusterStatDto
{
Id = clusterById.Id,
Description = "",
Caption = clusterById.Caption,
Latitude = clusterById.Latitude,
Longitude = clusterById.Longitude,
WellsStat = wellStatDtos,
};
}
}
}

View File

@ -1,4 +1,5 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache;
using Microsoft.EntityFrameworkCore;
@ -21,19 +22,18 @@ namespace AsbCloudInfrastructure.Services
IdCategory = operation.IdCategory;
WellDepth = operation.WellDepth;
StartDate = operation.StartDate;
Start = operation.StartDate;
DurationHours = operation.DurationHours;
WellDepthReal = operation.WellDepth;
DeltaDepth = 0;
DurationToNextOperationHours = operation.DurationHours;
}
public int Id { get; }
public int IdWellSectionType { get; }
public int IdCategory { get; }
public int Id { get; }
public DateTime Start { get; }
public double WellDepth { get; }
public DateTime StartDate { get; }
public double DurationHours { get; }
public double WellDepthReal { get; set; }
public double DeltaDepth { get; set; }
@ -53,27 +53,12 @@ namespace AsbCloudInfrastructure.Services
public double Speed => DeltaDepth / (DeltaHoursTimeNoNpt + double.Epsilon);
}
class SectionStat
{
public DateTime StartDate { get; set; }
public double StartWellDepth { get; set; }
public DateTime EndDate { get; set; }
public double EndWellDepth { get; set; }
public double AvgRaceSpeed { get; set; }
public double Rop { get; set; }
public double BhaDownSpeed { get; set; }
public double BhaUpSpeed { get; set; }
public double CasingDownSpeed { get; set; }
public int IdSectionType { get; internal set; }
public double Hours => (EndDate - StartDate).TotalHours;
}
public class WellOperationsStatService
public class WellOperationsStatService : IWellOperationsStatService
{
private readonly IAsbCloudDbContext db;
private readonly CacheTable<WellSectionType> cachedSectionsTypes;
const int idOperationBhaAssembly = 1025;
const int idOperationBhaDisassembly = 1026;
private const int idOperationBhaAssembly = 1025;
private const int idOperationBhaDisassembly = 1026;
private const int idOperationNonProductiveTime = 1043;
private const int idOperationDrilling = 1001;
private const int idOperationBhaDown = 1046;
@ -86,92 +71,113 @@ namespace AsbCloudInfrastructure.Services
cachedSectionsTypes = cache.GetCachedTable<WellSectionType>((DbContext)db);
}
public async Task<IEnumerable<WellSectionDto>> GetSectionsByWellIdAsync(int idWell,
public async Task<StatClusterDto> GetOperationStatByClusterAsync(int idCluster, CancellationToken token = default)
{
var operations = await db.WellOperations
.Include(o => o.Well)
.Where(o => o.Well.IdCluster == idCluster)
.OrderBy(o => o.StartDate)
.AsNoTracking()
.ToListAsync(token);
var wellsIds = operations.Select(o => o.IdWell).Distinct();
var sectionsStats = new List<StatOperationDto>(wellsIds.Count() * 3);
var wellsTotals = new List<StatOperationDto>(wellsIds.Count());
foreach(var idWell in wellsIds)
{
var wellOperations = operations.Where(o => o.IdWell == idWell);
sectionsStats.AddRange(GetWellSectionsStats(wellOperations));
wellsTotals.Add(GetWellStats(wellOperations));
}
var statClusterDto = new StatClusterDto
{
Sections = sectionsStats,
WellsTotals = wellsTotals,
};
return statClusterDto;
}
public async Task<StatWellDto> GetOperationStatByWellAsync(int idWell,
CancellationToken token = default)
{
var operationsAll = await db.WellOperations
var operations = await db.WellOperations
.Where(o => o.IdWell == idWell)
.OrderBy(o => o.StartDate) // ускорит дальнейшие сортировки
.AsNoTracking()
.ToListAsync(token);
var operationsPlan = operationsAll
.Where(o => o.IdType == 0);
var statWellDto = new StatWellDto
{
Sections = GetWellSectionsStats(operations),
Total = GetWellStats(operations),
};
return statWellDto;
}
var sectionsPlan = CalcSectionsStats(operationsPlan);
private IEnumerable<StatOperationDto> GetWellSectionsStats(IEnumerable<WellOperation> operations)
{
var sectionTypesIds = operations.Select(o => o.IdWellSectionType).Distinct();
var sections = new List<StatOperationDto>(sectionTypesIds.Count());
var operationsPlan = MakeOperationsExt(operations.Where(o => o.IdType == 0));
var operationsFact = MakeOperationsExt(operations.Where(o => o.IdType == 0));
var operationsFact = operationsAll
.Where(o => o.IdType == 1);
var sectionsFact = CalcSectionsStats(operationsFact);
var sectionTypesIds = operationsAll.Select(o => o.IdWellSectionType).Distinct();
var sections = new List<WellSectionDto>(sectionTypesIds.Count());
foreach (var idSectionType in sectionTypesIds)
{
var statPlan = sectionsPlan.FirstOrDefault(s => s.IdSectionType == idSectionType);
var statFact = sectionsFact.FirstOrDefault(s => s.IdSectionType == idSectionType);
WellSectionDto section = MakeWellSectionDto(idSectionType, statPlan, statFact);
var statPlan = CalcSectionStat(operationsPlan, idSectionType);
var statFact = CalcSectionStat(operationsFact, idSectionType);
StatOperationDto section = MakeWellSectionDto(idSectionType, statPlan, statFact);
sections.Add(section);
}
return sections;
}
private WellSectionDto MakeWellSectionDto(int idSectionType, SectionStat statPlan, SectionStat statFact)
private static StatOperationDto GetWellStats(IEnumerable<WellOperation> operations)
{
return new WellSectionDto
var operationsPlan = MakeOperationsExt(operations.Where(o => o.IdType == 0));
var operationsFact = MakeOperationsExt(operations.Where(o => o.IdType == 0));
var section = new StatOperationDto
{
Plan = CalcStat(operationsPlan),
Fact = CalcStat(operationsFact),
};
return section;
}
private StatOperationDto MakeWellSectionDto(int idSectionType, StatOperationBase statPlan, StatOperationBase statFact)
{
return new StatOperationDto
{
Id = idSectionType,
SectionType = cachedSectionsTypes.FirstOrDefault(s => s.Id == idSectionType)?.Caption,
BhaDownSpeedPlan = statPlan?.BhaDownSpeed ?? double.NaN,
BhaUpSpeedPlan = statPlan?.BhaUpSpeed ?? double.NaN,
MechSpeedPlan = statPlan?.Rop ?? double.NaN,
CasingDownSpeedPlan = statPlan?.CasingDownSpeed ?? double.NaN,
RouteSpeedPlan = statPlan?.AvgRaceSpeed ?? double.NaN,
WellDepthPlan = statPlan?.EndWellDepth ?? double.NaN,
DurationPlan = statPlan?.Hours ?? double.NaN,
BhaDownSpeedFact = statFact?.BhaDownSpeed ?? double.NaN,
BhaUpSpeedFact = statFact?.BhaUpSpeed ?? double.NaN,
MechSpeedFact = statFact?.Rop ?? double.NaN,
CasingDownSpeedFact = statFact?.CasingDownSpeed ?? double.NaN,
RouteSpeedFact = statFact?.AvgRaceSpeed ?? double.NaN,
WellDepthFact = statFact?.EndWellDepth ?? double.NaN,
DurationFact = statFact?.Hours ?? double.NaN,
Caption = cachedSectionsTypes.FirstOrDefault(s => s.Id == idSectionType)?.Caption,
Plan = statPlan,
Fact = statFact,
};
}
private static IEnumerable<SectionStat> CalcSectionsStats(IEnumerable<WellOperation> wellOperations)
private static StatOperationBase CalcSectionStat(IEnumerable<OperationParams> operations, int idSectionType)
{
var operations = MakeOperationsExt(wellOperations);
var sectionTypesIds = operations.Select(o => o.IdWellSectionType).Distinct();
var sectionsStats = new List<SectionStat>(sectionTypesIds.Count());
foreach (var idSection in sectionTypesIds)
{
var section = CalcSectionStat(operations, idSection);
sectionsStats.Add(section);
}
return sectionsStats;
var sectionOperations = operations
.Where(o => o.IdWellSectionType == idSectionType)
.OrderBy(o => o.Start)
.ThenBy(o => o.WellDepth);
return CalcStat(sectionOperations);
}
private static SectionStat CalcSectionStat(IEnumerable<OperationParams> allOperations, int idSectionType)
private static StatOperationBase CalcStat(IEnumerable<OperationParams> operations)
{
var sectionOperations = allOperations
.Where(o => o.IdWellSectionType == idSectionType)
.OrderBy(o => o.StartDate)
.ThenBy(o => o.WellDepth);
var section = new SectionStat
var section = new StatOperationBase
{
IdSectionType = idSectionType,
StartDate = sectionOperations.First().StartDate,
EndDate = sectionOperations.Max(o => (o.StartDate.AddHours(o.DurationHours))),
StartWellDepth = sectionOperations.Min(o => o.WellDepthReal),
EndWellDepth = sectionOperations.Max(o => o.WellDepthReal),
AvgRaceSpeed = CalcAvgRaceSpeed(sectionOperations),
Rop = CalcROP(sectionOperations),
BhaDownSpeed = CalcSpeedByOperation(sectionOperations, idOperationBhaDown),
BhaUpSpeed = CalcSpeedByOperation(sectionOperations, idOperationBhaUp),
CasingDownSpeed = CalcSpeedByOperation(sectionOperations, IdOperationCasingDown),
Start = operations.First().Start,
End = operations.Max(o => (o.Start.AddHours(o.DurationHours))),
WellDepthStart = operations.Min(o => o.WellDepthReal),
WellDepthEnd = operations.Max(o => o.WellDepthReal),
RouteSpeed = CalcAvgRaceSpeed(operations),
Rop = CalcROP(operations),
BhaDownSpeed = CalcSpeedByOperation(operations, idOperationBhaDown),
BhaUpSpeed = CalcSpeedByOperation(operations, idOperationBhaUp),
CasingDownSpeed = CalcSpeedByOperation(operations, IdOperationCasingDown),
};
return section;
}
@ -203,7 +209,6 @@ namespace AsbCloudInfrastructure.Services
return dDepth / (dHours + double.Epsilon);
}
// Метры в час
private static double CalcAvgRaceSpeed(IEnumerable<OperationParams> operations)
{
var races = GetCompleteRaces(operations);
@ -233,7 +238,7 @@ namespace AsbCloudInfrastructure.Services
WellDepthReal = Helper.Max(wellDepth, item.WellDepth) // TODO: учесть операциии с уменьшение глубины ствола.
};
pre.DeltaDepth = current.WellDepthReal - wellDepth;
pre.DurationToNextOperationHours = (current.StartDate - pre.StartDate).TotalHours;
pre.DurationToNextOperationHours = (current.Start - pre.Start).TotalHours;
ops.Add(pre);
pre = current;
}
@ -243,7 +248,7 @@ namespace AsbCloudInfrastructure.Services
private static IEnumerable<Race> GetCompleteRaces(IEnumerable<OperationParams> operations)
{
var races = new List<Race>(4);
var races = new List<Race>();
var iterator = operations.GetEnumerator();
while (iterator.MoveNext())
{
@ -251,7 +256,7 @@ namespace AsbCloudInfrastructure.Services
{
var race = new Race
{
StartDate = iterator.Current.StartDate.AddHours(iterator.Current.DurationHours),
StartDate = iterator.Current.Start.AddHours(iterator.Current.DurationHours),
StartWellDepth = iterator.Current.WellDepthReal
};
while (iterator.MoveNext())
@ -262,7 +267,7 @@ namespace AsbCloudInfrastructure.Services
}
if (iterator.Current.IdCategory == idOperationBhaDisassembly)
{
race.EndDate = iterator.Current.StartDate.AddHours(iterator.Current.DurationHours);
race.EndDate = iterator.Current.Start.AddHours(iterator.Current.DurationHours);
race.EndWellDepth = iterator.Current.WellDepthReal;
races.Add(race);
}
@ -271,6 +276,5 @@ namespace AsbCloudInfrastructure.Services
}
return races;
}
}
}

View File

@ -1,187 +0,0 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services
{
public class WellSectionService : IWellSectionService
{
private readonly IAsbCloudDbContext db;
public WellSectionService(IAsbCloudDbContext db)
{
this.db = db;
}
public async Task<IEnumerable<WellSectionDto>> GetSectionsByWellIdAsync(int idWell,
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);
if (!wellOperations.Any())
return null;
var wellOperationsGroupedBySections = wellOperations
.GroupBy(op => op.IdWellSectionType).ToList();
var wellOperationsClone = wellOperations.Select(o => o.ShallowCopy()).ToList();
wellOperationsClone.ForEach(op =>
{
op.IdWellSectionType = 1;
op.WellSectionType = new WellSectionType { Caption = "Обобщенное по скважине" };
});
var groupedWellOperationsClone = wellOperationsClone.GroupBy(o => o.IdWell);
wellOperationsGroupedBySections.Add(groupedWellOperationsClone.First());
var depthsPlanList = GetWellDepthStats(wellOperationsGroupedBySections, 0).ToList();
var depthsFactList = GetWellDepthStats(wellOperationsGroupedBySections, 1).ToList();
var durationsPlanList = GetWellDurationStats(wellOperationsGroupedBySections, 0).ToList();
var durationsFactList = GetWellDurationStats(wellOperationsGroupedBySections, 1).ToList();
var mechSpeedsPlanList = GetWellStats(wellOperationsGroupedBySections, 1001, 0).ToList();
var mechSpeedsFactList = GetWellStats(wellOperationsGroupedBySections, 1001, 1).ToList();
var bhaUpSpeedPlanList = GetWellStats(wellOperationsGroupedBySections, 1046, 0).ToList();
var bhaUpSpeedFactList = GetWellStats(wellOperationsGroupedBySections, 1046, 1).ToList();
var bhaDownSpeedPlanList = GetWellStats(wellOperationsGroupedBySections, 1047, 0).ToList();
var bhaDownSpeedFactList = GetWellStats(wellOperationsGroupedBySections, 1047, 1).ToList();
var casingDownPlanList = GetWellStats(wellOperationsGroupedBySections, 1048, 0).ToList();
var casingDownFactList = GetWellStats(wellOperationsGroupedBySections, 1048, 1).ToList();
var routeSpeedsPlan = GetWellRouteSpeedStats(wellOperationsGroupedBySections, 0).ToList();
var routeSpeedsFact = GetWellRouteSpeedStats(wellOperationsGroupedBySections, 1).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 = depthsPlanList[i],
WellDepthFact = depthsFactList[i],
DurationPlan = durationsPlanList[i],
DurationFact = durationsFactList[i],
MechSpeedPlan = mechSpeedsPlanList[i],
MechSpeedFact = mechSpeedsFactList[i],
BhaUpSpeedPlan = bhaUpSpeedPlanList[i],
BhaUpSpeedFact = bhaUpSpeedFactList[i],
BhaDownSpeedPlan = bhaDownSpeedPlanList[i],
BhaDownSpeedFact = bhaDownSpeedFactList[i],
CasingDownSpeedPlan = casingDownPlanList[i],
CasingDownSpeedFact = casingDownFactList[i],
RouteSpeedPlan = routeSpeedsPlan[i],
RouteSpeedFact = routeSpeedsFact[i]
};
dtos.Add(dto);
}
return dtos.OrderBy(d => d.WellDepthPlan);
}
private static IEnumerable<double> GetWellDepthStats(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations, int type)
{
return groupedOperations.Select(group => group.Where(o => o.IdType == type)
.DefaultIfEmpty().Max(w => w?.WellDepth ?? 0.0));
}
private static IEnumerable<double> GetWellDurationStats(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations, int type)
{
var durationsPlanFactsBase = groupedOperations.Select(group => new
{
DurationMax = group.Where(o => o.IdType == type).DefaultIfEmpty()
.Max(op => op?.StartDate + TimeSpan.FromHours(op?.DurationHours ?? 0)) ?? default,
DurationMin = group.Where(o => o.IdType == type).DefaultIfEmpty()
.Min(op => op?.StartDate) ?? default
});
return durationsPlanFactsBase.Select(o =>
(o.DurationMax - o.DurationMin).TotalHours);
}
private static IEnumerable<double> GetWellStats(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations, int idCategory, int type)
{
var mechSpeedBase = groupedOperations.Select(g =>
(
DepthDifferenceSum: g.Where(o => o.IdType == type && o.IdCategory == idCategory)
.Select((el, i) => i > 0 ? el.WellDepth - g.ElementAt(i - 1).WellDepth : 0).Sum(),
DurationDifferenceSum: g.Where(o => o.IdType == type && o.IdCategory == idCategory)
.Select(el => el.DurationHours).Sum()
));
return CalculateResult(mechSpeedBase);
}
private static IEnumerable<double> GetWellRouteSpeedStats(
IEnumerable<IGrouping<int, WellOperation>> groupedOperations, int type)
{
var bhaRaiseDecreaseCollection = new List<(WellOperation FirstBhaPositionDecrease,
WellOperation LastBhaPositionIncrease)>();
foreach (var group in groupedOperations)
{
var firstBhaPositionDecrease = group.Any(o => o.IdCategory == 1046 && o.IdType == type)
? group.First(o => o.IdCategory == 1046 && o.IdType == type)
: null;
var lastBhaPositionIncrease = group.Any(o => o.IdCategory == 1047 && o.IdType == type)
? group.Last(o => o.IdCategory == 1047 && o.IdType == type)
: null;
bhaRaiseDecreaseCollection.Add((firstBhaPositionDecrease, lastBhaPositionIncrease));
}
var routeSpeedsBase = bhaRaiseDecreaseCollection.Select(el =>
(
RouteDepth: (el.LastBhaPositionIncrease?.WellDepth - el.FirstBhaPositionDecrease?.WellDepth) ?? 0,
RouteDuration: (el.LastBhaPositionIncrease?.StartDate +
TimeSpan.FromHours(el.LastBhaPositionIncrease?.DurationHours ?? 0) -
el.FirstBhaPositionDecrease?.StartDate)?.TotalHours ?? 0
));
return CalculateResult(routeSpeedsBase);
}
private static IEnumerable<double> CalculateResult(IEnumerable<(double,
double)> rawData)
{
return rawData.Select(el =>
(el.Item1 / el.Item2) is double.NaN
? 0
: (el.Item1 / el.Item2)
);
}
}
}

View File

@ -61,25 +61,5 @@ namespace AsbCloudWebApi.Controllers
idCluster, token).ConfigureAwait(false);
return Ok(result);
}
/// <summary>
/// Получение обопщенной статистики по кусту (лучшая/худшая скважина)
/// </summary>
/// <param name="idCluster"></param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns></returns>
[HttpGet("{idCluster}/Stat")]
[ProducesResponseType(typeof(ClusterStatDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetStatAsync(int idCluster, CancellationToken token)
{
int? idCompany = User.GetCompanyId();
if (idCompany is null)
return Forbid();
var result = await clusterService.GetStatAsync((int)idCompany,
idCluster, token).ConfigureAwait(false);
return Ok(result);
}
}
}

View File

@ -0,0 +1,64 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudWebApi.Controllers
{
/// <summary>
/// Контроллер секций скважины
/// </summary>
[ApiController]
[Authorize]
[Route("api")]
public class WellOperationStatController : ControllerBase
{
private readonly IWellOperationsStatService sectionsService;
private readonly IWellService wellService;
public WellOperationStatController(IWellOperationsStatService sectionsService, IWellService wellService)
{
this.sectionsService = sectionsService;
this.wellService = wellService;
}
[HttpGet]
[Route("well/{idWell}/stat")]
[ProducesResponseType(typeof(IEnumerable<StatOperationDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetOperationStatByWellAsync(int idWell,
CancellationToken token = default)
{
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
return Forbid();
var result = await sectionsService.GetOperationStatByWellAsync(idWell, token)
.ConfigureAwait(false);
return Ok(result);
}
[HttpGet]
[Route("cluster/{idCluster}/stat")]
[ProducesResponseType(typeof(StatClusterDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetOperationStatByClusterAsync(int idCluster,
CancellationToken token = default)
{
// TODO: Fix next commented lines
//if (!await CanUserAccessToWellAsync(idCluster, token).ConfigureAwait(false))
// return Forbid();
var result = await sectionsService.GetOperationStatByClusterAsync(idCluster, token)
.ConfigureAwait(false);
return Ok(result);
}
private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false);
}
}
}

View File

@ -1,48 +0,0 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudWebApi.Controllers
{
/// <summary>
/// Контроллер секций скважины
/// </summary>
[Route("api/well/{idWell}/sections")]
[ApiController]
[Authorize]
public class WellSectionController : ControllerBase
{
private readonly IWellSectionService sectionsService;
private readonly IWellService wellService;
public WellSectionController(IWellSectionService sectionsService, IWellService wellService)
{
this.sectionsService = sectionsService;
this.wellService = wellService;
}
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<WellSectionDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetSectionsByWellIdAsync(int idWell,
CancellationToken token = default)
{
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
return Forbid();
var result = await sectionsService.GetSectionsByWellIdAsync(idWell, token)
.ConfigureAwait(false);
return Ok(result);
}
private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false);
}
}
}