diff --git a/AsbCloudApp/Data/WellboreDto.cs b/AsbCloudApp/Data/WellboreDto.cs
index c153b14f..68c5695b 100644
--- a/AsbCloudApp/Data/WellboreDto.cs
+++ b/AsbCloudApp/Data/WellboreDto.cs
@@ -10,7 +10,7 @@ public class WellboreDto
///
/// Скважина
///
- public WellWithTimezoneDto Well { get; set; } = null!;
+ public WellDto Well { get; set; } = null!;
///
/// Идентификатор
diff --git a/AsbCloudApp/Requests/WellboreRequest.cs b/AsbCloudApp/Requests/WellboreRequest.cs
deleted file mode 100644
index 32b4cbe2..00000000
--- a/AsbCloudApp/Requests/WellboreRequest.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Collections.Generic;
-
-namespace AsbCloudApp.Requests;
-
-///
-/// Параметры запроса для ствола скважины
-///
-public class WellboreRequest : RequestBase
-{
- ///
- /// Пары идентификаторов скважины и секции
- ///
- public IEnumerable<(int idWell, int? idSection)> Ids { get; set; } = null!;
-}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/ITelemetryDataService.cs b/AsbCloudApp/Services/ITelemetryDataService.cs
index 58eeeb70..154986b4 100644
--- a/AsbCloudApp/Services/ITelemetryDataService.cs
+++ b/AsbCloudApp/Services/ITelemetryDataService.cs
@@ -42,7 +42,6 @@ namespace AsbCloudApp.Services
///
///
///
- ///
///
DatesRangeDto? GetRange(int idWell, DateTimeOffset start, DateTimeOffset end);
diff --git a/AsbCloudApp/Services/IWellboreService.cs b/AsbCloudApp/Services/IWellboreService.cs
index f42485ae..0b577ba5 100644
--- a/AsbCloudApp/Services/IWellboreService.cs
+++ b/AsbCloudApp/Services/IWellboreService.cs
@@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
-using AsbCloudApp.Requests;
namespace AsbCloudApp.Services;
@@ -11,20 +10,11 @@ namespace AsbCloudApp.Services;
///
public interface IWellboreService
{
- ///
- /// Получение ствола скважины
- ///
- ///
- ///
- ///
- ///
- Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken);
-
- ///
- /// Получение стволов скважин
- ///
- ///
- ///
- ///
- Task> GetWellboresAsync(WellboreRequest request, CancellationToken cancellationToken);
+ ///
+ /// Получение стволов скважин
+ ///
+ ///
+ ///
+ ///
+ Task> GetWellboresAsync(IEnumerable idsWells, CancellationToken cancellationToken);
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
index b579c876..531ab8d9 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
@@ -20,7 +20,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
{
class TelemetryDataCacheItem
{
- public TDto? FirstByDate { get; init; }
+ public TDto FirstByDate { get; init; } = default!;
public CyclycArray LastData { get; init; } = null!;
public double TimezoneHours { get; init; } = 5;
}
@@ -127,7 +127,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
return items;
}
- public TDto? GetLastOrDefault(int idTelemetry)
+ public virtual TDto? GetLastOrDefault(int idTelemetry)
{
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
return default;
@@ -150,6 +150,19 @@ namespace AsbCloudInfrastructure.Services.SAUB
return new DatesRangeDto { From = from.Value, To = to };
}
+ public (TDto First, TDto Last)? GetOrDefaultFirstLast(int idTelemetry)
+ {
+ if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
+ return null;
+
+ if (!cacheItem.LastData.Any())
+ return null;
+
+ var last = cacheItem.LastData[^1];
+ var first = cacheItem.FirstByDate;
+ return (first, last);
+ }
+
private async Task InitializeCacheFromDBAsync(IAsbCloudDbContext db, Action onProgress, CancellationToken token)
where TEntity : class, AsbCloudDb.Model.ITelemetryData
{
diff --git a/AsbCloudInfrastructure/Services/WellboreService.cs b/AsbCloudInfrastructure/Services/WellboreService.cs
index 396243d6..9fd4080d 100644
--- a/AsbCloudInfrastructure/Services/WellboreService.cs
+++ b/AsbCloudInfrastructure/Services/WellboreService.cs
@@ -1,91 +1,135 @@
-using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
+using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
-using AsbCloudDb.Model;
-using Mapster;
+using AsbCloudInfrastructure.Services.SAUB;
namespace AsbCloudInfrastructure.Services;
public class WellboreService : IWellboreService
{
+ const string WellboreNameFormat = " {0}";
private readonly IWellService wellService;
private readonly IWellOperationRepository wellOperationRepository;
+ private readonly TelemetryDataCache telemetryDataCache;
- public WellboreService(IWellService wellService, IWellOperationRepository wellOperationRepository)
+ public WellboreService(
+ IWellService wellService,
+ IWellOperationRepository wellOperationRepository,
+ TelemetryDataCache telemetryDataCache)
{
this.wellService = wellService;
this.wellOperationRepository = wellOperationRepository;
- }
-
- public async Task GetWellboreAsync(int idWell, int idSection, CancellationToken cancellationToken)
- {
- var request = new WellboreRequest
- {
- Ids = new (int, int?)[] { (idWell, idSection) },
- Take = 1,
- };
- var data = await GetWellboresAsync(request, cancellationToken);
- return data.FirstOrDefault();
+ this.telemetryDataCache = telemetryDataCache;
}
- public async Task> GetWellboresAsync(WellboreRequest request,
+ public async Task> GetWellboresAsync(IEnumerable idsWells,
CancellationToken token)
{
- var wellbores = new List(request.Ids.Count());
- var skip = request.Skip ?? 0;
- var take = request.Take ?? 10;
+ var wellRequest = new WellRequest { Ids = idsWells };
+ var wells = await wellService.GetAsync(wellRequest, token);
- var sections = wellOperationRepository.GetSectionTypes()
- .ToDictionary(w => w.Id, w => w);
+ var rowSections = await wellOperationRepository.GetSectionsAsync(idsWells, token);
+ var groupedSections = rowSections
+ .GroupBy(s => s.IdWell);
- var ids = request.Ids.GroupBy(i => i.idWell, i => i.idSection);
+ var wellbores = wells
+ .SelectMany(well => {
+ var wellSections = groupedSections.FirstOrDefault(group => group.Key == well.Id);
+ if (wellSections is not null)
+ return MakeWellboreBySections(wellSections, well);
+ else
+ return MakeWellboreDefault(well);
+ })
+ .OrderBy(w => w.Well.Id)
+ .ThenBy(w => w.Id);
- var idsWells = request.Ids.Select(i => i.idWell);
+ return wellbores;
+ }
- var allSections = await wellOperationRepository.GetSectionsAsync(idsWells, token);
+ private IEnumerable MakeWellboreDefault(WellDto well)
+ {
+ var wellbore = new WellboreDto {
+ Id = 1,
+ Name = string.Format(WellboreNameFormat, 1),
+ Well = well,
+ };
- foreach (var id in ids)
+ if(well.IdTelemetry is not null)
{
- var well = await wellService.GetOrDefaultAsync(id.Key, token);
+ var dataCache = telemetryDataCache.GetOrDefaultFirstLast(well.IdTelemetry.Value);
+ if (dataCache is not null)
+ {
+ wellbore.DateStart = dataCache.Value.First.DateTime;
+ wellbore.DepthStart = dataCache.Value.First.WellDepth!.Value;
- if (well is null)
- continue;
-
- var wellTimezoneOffset = TimeSpan.FromHours(well.Timezone.Hours);
-
- var wellFactSections = allSections
- .Where(section => section.IdWell == id.Key)
- .Where(section => section.IdType == WellOperation.IdOperationTypeFact);
-
- var idsSections = id
- .Where(i => i.HasValue)
- .Select(i => i!.Value);
-
- if (idsSections.Any())
- wellFactSections = wellFactSections
- .Where(section => idsSections.Contains(section.IdWellSectionType));
-
- var wellWellbores = wellFactSections.Select(section => new WellboreDto {
- Id = section.IdWellSectionType,
- Name = sections[section.IdWellSectionType].Caption,
- Well = well.Adapt(),
- DateStart = section.DateStart.ToOffset(wellTimezoneOffset),
- DateEnd = section.DateEnd.ToOffset(wellTimezoneOffset),
- DepthStart = section.DepthStart,
- DepthEnd = section.DepthEnd,
- });
-
- wellbores.AddRange(wellWellbores);
+ wellbore.DateEnd = dataCache.Value.Last.DateTime;
+ wellbore.DepthEnd = dataCache.Value.Last.WellDepth!.Value;
+ }
}
- return wellbores
- .OrderBy(w => w.Well.Id).ThenBy(w => w.Id)
- .Skip(skip).Take(take);
- }
+ return new[] { wellbore };
+ }
+
+ private IEnumerable MakeWellboreBySections(IEnumerable sections, WellDto well)
+ {
+ var orderedSections = sections.OrderBy(s => s.DateStart);
+ var wellbores = new List();
+ int wellboreId = 1;
+
+ SectionByOperationsDto? preSection = null;
+ WellboreDto? wellbore = null;
+
+ foreach (var section in orderedSections)
+ {
+ if (wellbore is null || wellbore.DepthEnd > section.DepthStart)
+ {
+ wellbore = new WellboreDto
+ {
+ Name = string.Format(WellboreNameFormat, wellboreId),
+ Id = wellboreId,
+ Well = well,
+
+ DateStart = section.DateStart,
+ DateEnd = section.DateEnd,
+ DepthStart = section.DepthStart,
+ DepthEnd = section.DepthEnd,
+ };
+
+ wellbores.Add(wellbore);
+ wellboreId++;
+
+ }
+ else
+ {
+ wellbore.DepthEnd = section.DepthEnd;
+ wellbore.DateEnd = section.DateEnd;
+ }
+
+ preSection = section;
+ }
+
+ if (wellbore is not null)
+ {
+ if (well.IdTelemetry is not null)
+ {
+ var dataCache = telemetryDataCache.GetOrDefaultFirstLast(well.IdTelemetry.Value);
+ if (dataCache is not null)
+ {
+ wellbore.DateStart = dataCache.Value.First.DateTime;
+ wellbore.DepthStart = dataCache.Value.First.WellDepth!.Value;
+
+ wellbore.DateEnd = dataCache.Value.Last.DateTime;
+ wellbore.DepthEnd = dataCache.Value.Last.WellDepth!.Value;
+ }
+ }
+ }
+
+ return wellbores;
+ }
}
\ No newline at end of file
diff --git a/AsbCloudWebApi/Controllers/WellboreController.cs b/AsbCloudWebApi/Controllers/WellboreController.cs
index ba3a27cb..8b0a94bf 100644
--- a/AsbCloudWebApi/Controllers/WellboreController.cs
+++ b/AsbCloudWebApi/Controllers/WellboreController.cs
@@ -9,6 +9,7 @@ using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Org.BouncyCastle.Asn1.Ocsp;
namespace AsbCloudWebApi.Controllers;
@@ -26,66 +27,20 @@ public class WellboreController : ControllerBase
{
this.wellboreService = wellboreService;
}
-
- ///
- /// Получение ствола скважины
- ///
- /// Id скважины
- /// Id типа секции скважины
- ///
- ///
- [HttpGet("{idWell:int}/{idSection:int}")]
- [ProducesResponseType(typeof(WellboreDto), StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status204NoContent)]
- public async Task GetAsync(int idWell, int idSection, CancellationToken cancellationToken)
- {
- var wellbore = await wellboreService.GetWellboreAsync(idWell, idSection, cancellationToken);
-
- if (wellbore is null)
- return NoContent();
-
- return Ok(wellbore);
- }
-
- ///
- /// Получение списка стволов скважин
- ///
- /// Пары идентификаторов скважины и секции
- /// Опциональный параметр. Количество пропускаемых записей
- /// Опциональный параметр. Количество получаемых записей
- ///
- ///
- [HttpGet]
+ ///
+ /// Получение списка стволов скважин
+ ///
+ /// Идентификаторы скважин
+ ///
+ ///
+ [HttpGet]
[ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
- public async Task GetAllAsync([FromQuery] IEnumerable ids,
- int? skip,
- int? take,
+ public async Task GetAllAsync([FromQuery] IEnumerable idsWells,
CancellationToken cancellationToken)
- {
- var request = new WellboreRequest
- {
- Ids = ids.Select(id => ParseId(id)),
- Skip = skip,
- Take = take
- };
+ {
+ var result = await wellboreService.GetWellboresAsync(idsWells, cancellationToken);
- return Ok(await wellboreService.GetWellboresAsync(request, cancellationToken));
+ return Ok(result);
}
-
- private static (int, int?) ParseId(string id)
- {
- var idPair = id.Split(',');
- if (!int.TryParse(idPair[0], out var idWell))
- throw new ArgumentInvalidException(nameof(id), $"Не удалось получить Id скважины \"{idPair[0]}\"");
-
- if (idPair.Length > 1)
- {
- if (int.TryParse(idPair[1], out int idWellSectionType))
- return (idWell, idWellSectionType);
- else
- throw new ArgumentInvalidException(nameof(id), $"Не удалось получить Id ствола \"{idPair[1]}\"");
- }
- return (idWell, null);
- }
}
\ No newline at end of file