forked from ddrilling/AsbCloudServer
Merge branch 'dev' into fix/process_map
This commit is contained in:
commit
11662ff2c0
@ -1,4 +1,5 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -9,7 +10,7 @@ namespace AsbCloudApp.Repositories
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Репозиторий работы с данными из таблицы t_data_daub_stat
|
/// Репозиторий работы с данными из таблицы t_data_daub_stat
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDataSaubStatRepository
|
public interface IDataSaubStatRepository : ITelemetryDataEditorService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение записей по ключу телеметрии
|
/// Получение записей по ключу телеметрии
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
using System;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.DetectedOperation;
|
using AsbCloudApp.Data.DetectedOperation;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using AsbCloudApp.Data;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data.WellOperation;
|
using AsbCloudApp.Services;
|
||||||
|
|
||||||
namespace AsbCloudApp.Repositories;
|
namespace AsbCloudApp.Repositories;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Таблица автоматически определенных операций
|
/// Таблица автоматически определенных операций
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDetectedOperationRepository
|
public interface IDetectedOperationRepository : ITelemetryDataEditorService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавление нескольких записей
|
/// Добавление нескольких записей
|
||||||
@ -55,11 +54,11 @@ public interface IDetectedOperationRepository
|
|||||||
Task<PaginationContainer<DetectedOperationDto>> GetPageAsync(DetectedOperationByTelemetryRequest request, CancellationToken token);
|
Task<PaginationContainer<DetectedOperationDto>> GetPageAsync(DetectedOperationByTelemetryRequest request, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение дат последних определённых операций
|
/// Получение последних авто определённых операций
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IDictionary<int, DateTimeOffset>> GetLastDetectedDatesAsync(CancellationToken token);
|
Task<IDictionary<int, DetectedOperationDto>> GetLastDetectedOperationsAsync(CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить операции
|
/// Удалить операции
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using AsbCloudApp.Data.SAUB;
|
using AsbCloudApp.Data.SAUB;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -9,7 +10,7 @@ namespace AsbCloudApp.Repositories
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// репозиторий по работе с данными drill_test
|
/// репозиторий по работе с данными drill_test
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDrillTestRepository
|
public interface IDrillTestRepository : ITelemetryDataEditorService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить данные drill_test в соответствии с параметрами запроса
|
/// Получить данные drill_test в соответствии с параметрами запроса
|
||||||
|
@ -5,13 +5,14 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
|
||||||
namespace AsbCloudApp.Repositories
|
namespace AsbCloudApp.Repositories
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// данные ГТИ
|
/// данные ГТИ
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IGtrRepository
|
public interface IGtrRepository : ITelemetryDataEditorService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// добавить данные (для панели бурильщика)
|
/// добавить данные (для панели бурильщика)
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudApp.Repositories
|
namespace AsbCloudApp.Repositories
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Репозиторий по ограничивающим параметрам с фильтрацией
|
/// Репозиторий по ограничивающим параметрам с фильтрацией
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ILimitingParameterRepository
|
public interface ILimitingParameterRepository : ITelemetryDataEditorService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение списка ограничивающих параметров по идентификатору скважины
|
/// Получение списка ограничивающих параметров по идентификатору скважины
|
||||||
|
39
AsbCloudApp/Requests/TelemetryPartDeleteRequest.cs
Normal file
39
AsbCloudApp/Requests/TelemetryPartDeleteRequest.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Requests;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Параметры запроса на удаление куска телеметрии
|
||||||
|
/// </summary>
|
||||||
|
public class TelemetryPartDeleteRequest : IValidatableObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ключ телеметрии
|
||||||
|
/// </summary>
|
||||||
|
public int IdTelemetry { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// greater or equal then Date. Must be set one of GeDate or LeDate
|
||||||
|
/// </summary>
|
||||||
|
public DateTimeOffset? GeDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// less or equal then Date. Must be set one of GeDate or LeDate
|
||||||
|
/// </summary>
|
||||||
|
public DateTimeOffset? LeDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Валидация входящих данных
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="validationContext"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||||
|
{
|
||||||
|
if (IdTelemetry == 0)
|
||||||
|
yield return new ValidationResult($"IdTelemetry must be defined");
|
||||||
|
if (!GeDate.HasValue && !LeDate.HasValue)
|
||||||
|
yield return new ValidationResult($"GeDate or LeDate must be defined");
|
||||||
|
}
|
||||||
|
}
|
@ -55,5 +55,4 @@ public class TelemetryDataRequest
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Range(1, MaxTake)]
|
[Range(1, MaxTake)]
|
||||||
public int Take { get; set; } = 1024;
|
public int Take { get; set; } = 1024;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,82 +6,85 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data.WellOperation;
|
using AsbCloudApp.Data.WellOperation;
|
||||||
|
|
||||||
namespace AsbCloudApp.Services
|
namespace AsbCloudApp.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Сервис автоматически определенных по телеметрии операций
|
||||||
|
/// </summary>
|
||||||
|
public interface IDetectedOperationService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Сервис автоматически определенных по телеметрии операций
|
/// Добавление операций
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDetectedOperationService
|
/// <param name="idEditor"></param>
|
||||||
{
|
/// <param name="idWell"></param>
|
||||||
/// <summary>
|
/// <param name="dtos"></param>
|
||||||
/// Добавление операций
|
/// <param name="token"></param>
|
||||||
/// </summary>
|
/// <returns></returns>
|
||||||
/// <param name="idEditor"></param>
|
Task<int> InsertRangeManualAsync(int idEditor, int idWell, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
|
||||||
/// <param name="idWell"></param>
|
|
||||||
/// <param name="dtos"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<int> InsertRangeManualAsync(int idEditor, int idWell, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Редактирование операций
|
/// Редактирование операций
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idEditor"></param>
|
/// <param name="idEditor"></param>
|
||||||
/// <param name="idWell"></param>
|
/// <param name="idWell"></param>
|
||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> UpdateRangeManualAsync(int idEditor, int idWell, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
|
Task<int> UpdateRangeManualAsync(int idEditor, int idWell, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Список названий операций.
|
/// Список названий операций.
|
||||||
/// Если указан idWell, то возвращается список названий операций найденных на указанной скважине.
|
/// Если указан idWell, то возвращается список названий операций найденных на указанной скважине.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell"></param>
|
/// <param name="idWell"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token);
|
Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить автоматически определенные по телеметрии операции с анализом по бурильщикам
|
/// Получить автоматически определенные по телеметрии операции с анализом по бурильщикам
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<DetectedOperationListDto> GetAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
Task<DetectedOperationListDto> GetAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить автоматически определенные по телеметрии операции
|
/// Получить автоматически определенные по телеметрии операции
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<DetectedOperationWithDrillerDto>> GetOperationsAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
Task<IEnumerable<DetectedOperationWithDrillerDto>> GetOperationsAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить операции
|
/// Удалить операции
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
Task<int> DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Статистика по операциям
|
/// Статистика по операциям
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
Task<IEnumerable<DetectedOperationStatDto>> GetOperationsStatAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
Task<IEnumerable<DetectedOperationStatDto>> GetOperationsStatAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Определение операций
|
/// Определение операций
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idTelemetry"></param>
|
/// <param name="idTelemetry"></param>
|
||||||
/// <param name="beginDate"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="lastDetectedOperation"></param>
|
||||||
/// <returns></returns>
|
/// <param name="token"></param>
|
||||||
Task<IEnumerable<DetectedOperationDto>> DetectOperationsAsync(int idTelemetry, DateTimeOffset? beginDate, CancellationToken token);
|
/// <returns></returns>
|
||||||
}
|
Task<(DateTimeOffset LastDate, IEnumerable<DetectedOperationDto> Items)> DetectOperationsAsync(int idTelemetry,
|
||||||
|
TelemetryDataRequest request,
|
||||||
|
DetectedOperationDto? lastDetectedOperation,
|
||||||
|
CancellationToken token);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Сервис сообщений панели оператора
|
/// Сервис сообщений панели оператора
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMessageService
|
public interface IMessageService : ITelemetryDataEditorService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить сообщения по параметрам
|
/// Получить сообщения по параметрам
|
||||||
|
19
AsbCloudApp/Services/ITelemetryDataEditorService.cs
Normal file
19
AsbCloudApp/Services/ITelemetryDataEditorService.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Сервис по работе с данными телеметрии
|
||||||
|
/// </summary>
|
||||||
|
public interface ITelemetryDataEditorService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Удаление части телеметрии по запросу
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token);
|
||||||
|
}
|
@ -5,44 +5,43 @@ using System.IO;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudApp.Services
|
namespace AsbCloudApp.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Телеметрия САУБ
|
||||||
|
/// </summary>
|
||||||
|
public interface ITelemetryDataSaubService : ITelemetryDataService<TelemetryDataSaubDto>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Телеметрия САУБ
|
/// Получение телеметрии для РТК статистики
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITelemetryDataSaubService : ITelemetryDataService<TelemetryDataSaubDto>
|
/// <param name="idTelemetry"></param>
|
||||||
{
|
/// <param name="isBitOnBottom"></param>
|
||||||
/// <summary>
|
/// <param name="geDate"></param>
|
||||||
/// Получение телеметрии для РТК статистики
|
/// <param name="leDate"></param>
|
||||||
/// </summary>
|
/// <param name="take"></param>
|
||||||
/// <param name="idTelemetry"></param>
|
/// <param name="token"></param>
|
||||||
/// <param name="isBitOnBottom"></param>
|
/// <returns></returns>
|
||||||
/// <param name="geDate"></param>
|
Task<IEnumerable<TelemetryDataSaubDto>> Get(int idTelemetry, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token);
|
||||||
/// <param name="leDate"></param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<IEnumerable<TelemetryDataSaubDto>> Get(int idTelemetry, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// усредненная статистика по 1м за весь период
|
/// усредненная статистика по 1м за весь период
|
||||||
/// <para>
|
/// <para>
|
||||||
/// МЕДЛЕННЫЙ ЗАПРОС
|
/// МЕДЛЕННЫЙ ЗАПРОС
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idTelemetry"></param>
|
/// <param name="idTelemetry"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<TelemetryDataSaubStatDto>> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token);
|
Task<IEnumerable<TelemetryDataSaubStatDto>> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить упакованый csv файл
|
/// Получить упакованный csv файл
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell"></param>
|
/// <param name="idWell"></param>
|
||||||
/// <param name="beginDate"></param>
|
/// <param name="beginDate"></param>
|
||||||
/// <param name="endDate"></param>
|
/// <param name="endDate"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Stream> GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token);
|
Task<Stream> GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token);
|
||||||
}
|
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// сервис данных тех. процесса
|
/// сервис данных тех. процесса
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TDto"></typeparam>
|
/// <typeparam name="TDto"></typeparam>
|
||||||
public interface ITelemetryDataService<TDto> where TDto : ITelemetryData
|
public interface ITelemetryDataService<TDto> : ITelemetryDataEditorService where TDto : ITelemetryData
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -60,5 +60,15 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> DeleteAsync(int idWell, int id, CancellationToken token);
|
Task<int> DeleteAsync(int idWell, int id, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Скопировать контакты в другую скважину
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">ключ скважины, откуда копировать контакты</param>
|
||||||
|
/// <param name="idWellTarget">ключ скважины, куда копировать контакты</param>
|
||||||
|
/// <param name="contactIds"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<int> CopyAsync(int idWell, int idWellTarget, IEnumerable<int> contactIds, CancellationToken token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -9,7 +10,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The wits record repository.
|
/// The wits record repository.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWitsRecordRepository<TDto>
|
public interface IWitsRecordRepository<TDto> : ITelemetryDataEditorService
|
||||||
where TDto : ITelemetryData
|
where TDto : ITelemetryData
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
12236
AsbCloudDb/Migrations/20240724070443_Update_WellSectionType_Order.Designer.cs
generated
Normal file
12236
AsbCloudDb/Migrations/20240724070443_Update_WellSectionType_Order.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,158 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Update_WellSectionType_Order : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 1,
|
||||||
|
column: "order",
|
||||||
|
value: 5f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 5,
|
||||||
|
column: "order",
|
||||||
|
value: 4f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 7,
|
||||||
|
column: "order",
|
||||||
|
value: 5.1f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 11,
|
||||||
|
column: "order",
|
||||||
|
value: 4.1f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 13,
|
||||||
|
column: "order",
|
||||||
|
value: 5.2f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 17,
|
||||||
|
column: "order",
|
||||||
|
value: 4.2f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 19,
|
||||||
|
column: "order",
|
||||||
|
value: 5.3f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 23,
|
||||||
|
column: "order",
|
||||||
|
value: 4.3f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 25,
|
||||||
|
column: "order",
|
||||||
|
value: 5.4f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 29,
|
||||||
|
column: "order",
|
||||||
|
value: 4.4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 1,
|
||||||
|
column: "order",
|
||||||
|
value: 4f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 5,
|
||||||
|
column: "order",
|
||||||
|
value: 5f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 7,
|
||||||
|
column: "order",
|
||||||
|
value: 4.1f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 11,
|
||||||
|
column: "order",
|
||||||
|
value: 5.1f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 13,
|
||||||
|
column: "order",
|
||||||
|
value: 4.2f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 17,
|
||||||
|
column: "order",
|
||||||
|
value: 5.2f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 19,
|
||||||
|
column: "order",
|
||||||
|
value: 4.3f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 23,
|
||||||
|
column: "order",
|
||||||
|
value: 5.3f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 25,
|
||||||
|
column: "order",
|
||||||
|
value: 4.4f);
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 29,
|
||||||
|
column: "order",
|
||||||
|
value: 5.4f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12236
AsbCloudDb/Migrations/20240729063346_Update_WellSectionType_Caption.Designer.cs
generated
Normal file
12236
AsbCloudDb/Migrations/20240729063346_Update_WellSectionType_Caption.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,116 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Update_WellSectionType_Caption : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 1,
|
||||||
|
column: "caption",
|
||||||
|
value: "Пилотный ствол 1");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 2,
|
||||||
|
column: "caption",
|
||||||
|
value: "Направление 1");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 3,
|
||||||
|
column: "caption",
|
||||||
|
value: "Кондуктор 1");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 4,
|
||||||
|
column: "caption",
|
||||||
|
value: "Эксплуатационная колонна 1");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 5,
|
||||||
|
column: "caption",
|
||||||
|
value: "Транспортный ствол 1");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 6,
|
||||||
|
column: "caption",
|
||||||
|
value: "Хвостовик 1");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 31,
|
||||||
|
column: "caption",
|
||||||
|
value: "Техническая колонна 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 1,
|
||||||
|
column: "caption",
|
||||||
|
value: "Пилотный ствол");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 2,
|
||||||
|
column: "caption",
|
||||||
|
value: "Направление");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 3,
|
||||||
|
column: "caption",
|
||||||
|
value: "Кондуктор");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 4,
|
||||||
|
column: "caption",
|
||||||
|
value: "Эксплуатационная колонна");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 5,
|
||||||
|
column: "caption",
|
||||||
|
value: "Транспортный ствол");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 6,
|
||||||
|
column: "caption",
|
||||||
|
value: "Хвостовик");
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "t_well_section_type",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 31,
|
||||||
|
column: "caption",
|
||||||
|
value: "Техническая колонна");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.UseCollation("Russian_Russia.1251")
|
.UseCollation("Russian_Russia.1251")
|
||||||
.HasAnnotation("ProductVersion", "8.0.2")
|
.HasAnnotation("ProductVersion", "8.0.4")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
||||||
@ -9544,44 +9544,44 @@ namespace AsbCloudDb.Migrations
|
|||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Caption = "Пилотный ствол",
|
Caption = "Пилотный ствол 1",
|
||||||
Order = 4f
|
Order = 5f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 2,
|
Id = 2,
|
||||||
Caption = "Направление",
|
Caption = "Направление 1",
|
||||||
Order = 0f
|
Order = 0f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Caption = "Кондуктор",
|
Caption = "Кондуктор 1",
|
||||||
Order = 1f
|
Order = 1f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 4,
|
Id = 4,
|
||||||
Caption = "Эксплуатационная колонна",
|
Caption = "Эксплуатационная колонна 1",
|
||||||
Order = 3f
|
Order = 3f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 5,
|
Id = 5,
|
||||||
Caption = "Транспортный ствол",
|
Caption = "Транспортный ствол 1",
|
||||||
Order = 5f
|
Order = 4f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 6,
|
Id = 6,
|
||||||
Caption = "Хвостовик",
|
Caption = "Хвостовик 1",
|
||||||
Order = 6f
|
Order = 6f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 7,
|
Id = 7,
|
||||||
Caption = "Пилотный ствол 2",
|
Caption = "Пилотный ствол 2",
|
||||||
Order = 4.1f
|
Order = 5.1f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
@ -9605,7 +9605,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 11,
|
Id = 11,
|
||||||
Caption = "Транспортный ствол 2",
|
Caption = "Транспортный ствол 2",
|
||||||
Order = 5.1f
|
Order = 4.1f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
@ -9617,7 +9617,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 13,
|
Id = 13,
|
||||||
Caption = "Пилотный ствол 3",
|
Caption = "Пилотный ствол 3",
|
||||||
Order = 4.2f
|
Order = 5.2f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
@ -9641,7 +9641,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 17,
|
Id = 17,
|
||||||
Caption = "Транспортный ствол 3",
|
Caption = "Транспортный ствол 3",
|
||||||
Order = 5.2f
|
Order = 4.2f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
@ -9653,7 +9653,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 19,
|
Id = 19,
|
||||||
Caption = "Пилотный ствол 4",
|
Caption = "Пилотный ствол 4",
|
||||||
Order = 4.3f
|
Order = 5.3f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
@ -9677,7 +9677,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 23,
|
Id = 23,
|
||||||
Caption = "Транспортный ствол 4",
|
Caption = "Транспортный ствол 4",
|
||||||
Order = 5.3f
|
Order = 4.3f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
@ -9689,7 +9689,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 25,
|
Id = 25,
|
||||||
Caption = "Пилотный ствол 5",
|
Caption = "Пилотный ствол 5",
|
||||||
Order = 4.4f
|
Order = 5.4f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
@ -9713,7 +9713,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 29,
|
Id = 29,
|
||||||
Caption = "Транспортный ствол 5",
|
Caption = "Транспортный ствол 5",
|
||||||
Order = 5.4f
|
Order = 4.4f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
@ -9724,7 +9724,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 31,
|
Id = 31,
|
||||||
Caption = "Техническая колонна",
|
Caption = "Техническая колонна 1",
|
||||||
Order = 2f
|
Order = 2f
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
|
@ -4,42 +4,42 @@ namespace AsbCloudDb.Model.DefaultData
|
|||||||
{
|
{
|
||||||
public override WellSectionType[] GetData() => new WellSectionType[]
|
public override WellSectionType[] GetData() => new WellSectionType[]
|
||||||
{
|
{
|
||||||
new (){ Id = 1, Caption = "Пилотный ствол", Order = 4},
|
new (){ Id = 1, Caption = "Пилотный ствол 1", Order = 5},
|
||||||
new (){ Id = 2, Caption = "Направление", Order = 0},
|
new (){ Id = 2, Caption = "Направление 1", Order = 0},
|
||||||
new (){ Id = 3, Caption = "Кондуктор", Order = 1},
|
new (){ Id = 3, Caption = "Кондуктор 1", Order = 1},
|
||||||
new (){ Id = 4, Caption = "Эксплуатационная колонна", Order = 3},
|
new (){ Id = 4, Caption = "Эксплуатационная колонна 1", Order = 3},
|
||||||
new (){ Id = 5, Caption = "Транспортный ствол", Order = 5},
|
new (){ Id = 5, Caption = "Транспортный ствол 1", Order = 4},
|
||||||
new (){ Id = 6, Caption = "Хвостовик", Order = 6},
|
new (){ Id = 6, Caption = "Хвостовик 1", Order = 6},
|
||||||
|
|
||||||
new (){ Id = 7, Caption = "Пилотный ствол 2", Order = 4.1f},
|
new (){ Id = 7, Caption = "Пилотный ствол 2", Order = 5.1f},
|
||||||
new (){ Id = 8, Caption = "Направление 2", Order = 0.1f},
|
new (){ Id = 8, Caption = "Направление 2", Order = 0.1f},
|
||||||
new (){ Id = 9, Caption = "Кондуктор 2", Order = 1.1f},
|
new (){ Id = 9, Caption = "Кондуктор 2", Order = 1.1f},
|
||||||
new (){ Id = 10, Caption = "Эксплуатационная колонна 2", Order = 3.1f},
|
new (){ Id = 10, Caption = "Эксплуатационная колонна 2", Order = 3.1f},
|
||||||
new (){ Id = 11, Caption = "Транспортный ствол 2", Order = 5.1f},
|
new (){ Id = 11, Caption = "Транспортный ствол 2", Order = 4.1f},
|
||||||
new (){ Id = 12, Caption = "Хвостовик 2", Order = 6.1f},
|
new (){ Id = 12, Caption = "Хвостовик 2", Order = 6.1f},
|
||||||
|
|
||||||
new (){ Id = 13, Caption = "Пилотный ствол 3", Order = 4.2f},
|
new (){ Id = 13, Caption = "Пилотный ствол 3", Order = 5.2f},
|
||||||
new (){ Id = 14, Caption = "Направление 3", Order = 0.2f},
|
new (){ Id = 14, Caption = "Направление 3", Order = 0.2f},
|
||||||
new (){ Id = 15, Caption = "Кондуктор 3", Order = 1.2f},
|
new (){ Id = 15, Caption = "Кондуктор 3", Order = 1.2f},
|
||||||
new (){ Id = 16, Caption = "Эксплуатационная колонна 3", Order = 3.2f},
|
new (){ Id = 16, Caption = "Эксплуатационная колонна 3", Order = 3.2f},
|
||||||
new (){ Id = 17, Caption = "Транспортный ствол 3", Order = 5.2f},
|
new (){ Id = 17, Caption = "Транспортный ствол 3", Order = 4.2f},
|
||||||
new (){ Id = 18, Caption = "Хвостовик 3", Order = 6.2f},
|
new (){ Id = 18, Caption = "Хвостовик 3", Order = 6.2f},
|
||||||
|
|
||||||
new (){ Id = 19, Caption = "Пилотный ствол 4", Order = 4.3f},
|
new (){ Id = 19, Caption = "Пилотный ствол 4", Order = 5.3f},
|
||||||
new (){ Id = 20, Caption = "Направление 4", Order = 0.3f},
|
new (){ Id = 20, Caption = "Направление 4", Order = 0.3f},
|
||||||
new (){ Id = 21, Caption = "Кондуктор 4", Order = 1.3f},
|
new (){ Id = 21, Caption = "Кондуктор 4", Order = 1.3f},
|
||||||
new (){ Id = 22, Caption = "Эксплуатационная колонна 4", Order = 3.3f},
|
new (){ Id = 22, Caption = "Эксплуатационная колонна 4", Order = 3.3f},
|
||||||
new (){ Id = 23, Caption = "Транспортный ствол 4", Order = 5.3f},
|
new (){ Id = 23, Caption = "Транспортный ствол 4", Order = 4.3f},
|
||||||
new (){ Id = 24, Caption = "Хвостовик 4", Order = 6.3f},
|
new (){ Id = 24, Caption = "Хвостовик 4", Order = 6.3f},
|
||||||
|
|
||||||
new (){ Id = 25, Caption = "Пилотный ствол 5", Order = 4.4f},
|
new (){ Id = 25, Caption = "Пилотный ствол 5", Order = 5.4f},
|
||||||
new (){ Id = 26, Caption = "Направление 5", Order = 0.4f},
|
new (){ Id = 26, Caption = "Направление 5", Order = 0.4f},
|
||||||
new (){ Id = 27, Caption = "Кондуктор 5", Order = 1.4f},
|
new (){ Id = 27, Caption = "Кондуктор 5", Order = 1.4f},
|
||||||
new (){ Id = 28, Caption = "Эксплуатационная колонна 5", Order = 3.4f},
|
new (){ Id = 28, Caption = "Эксплуатационная колонна 5", Order = 3.4f},
|
||||||
new (){ Id = 29, Caption = "Транспортный ствол 5", Order = 5.4f},
|
new (){ Id = 29, Caption = "Транспортный ствол 5", Order = 4.4f},
|
||||||
new (){ Id = 30, Caption = "Хвостовик 5", Order = 6.4f},
|
new (){ Id = 30, Caption = "Хвостовик 5", Order = 6.4f},
|
||||||
|
|
||||||
new (){ Id = 31, Caption = "Техническая колонна", Order = 2},
|
new (){ Id = 31, Caption = "Техническая колонна 1", Order = 2},
|
||||||
new (){ Id = 32, Caption = "Техническая колонна 2", Order = 2.1f},
|
new (){ Id = 32, Caption = "Техническая колонна 2", Order = 2.1f},
|
||||||
new (){ Id = 33, Caption = "Техническая колонна 3", Order = 2.2f},
|
new (){ Id = 33, Caption = "Техническая колонна 3", Order = 2.2f},
|
||||||
|
|
||||||
|
@ -493,6 +493,8 @@ namespace AsbCloudInfrastructure
|
|||||||
|
|
||||||
services.AddTransient<IWellboreService, WellboreService>();
|
services.AddTransient<IWellboreService, WellboreService>();
|
||||||
|
|
||||||
|
services.AddTransient<ITelemetryDataEditorService, TelemetryDataEditorService>();
|
||||||
|
|
||||||
services.AddTransient<DetectedOperationExportService>();
|
services.AddTransient<DetectedOperationExportService>();
|
||||||
|
|
||||||
services.AddTransient<IDailyReportService, DailyReportService>();
|
services.AddTransient<IDailyReportService, DailyReportService>();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
@ -81,5 +82,32 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IQueryable<DataSaubStat> BuildQuery(TelemetryPartDeleteRequest request)
|
||||||
|
{
|
||||||
|
var query = db.Set<DataSaubStat>()
|
||||||
|
.Where(o => o.IdTelemetry == request.IdTelemetry);
|
||||||
|
|
||||||
|
if (request.LeDate is not null)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateStart <= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.GeDate is not null)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateEnd >= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = BuildQuery(request);
|
||||||
|
db.Set<DataSaubStat>().RemoveRange(query);
|
||||||
|
return await db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@ using AsbCloudApp.Data;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Repository;
|
namespace AsbCloudInfrastructure.Repository;
|
||||||
|
|
||||||
public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationDto, DetectedOperation>, IDetectedOperationRepository
|
public class DetectedOperationRepository
|
||||||
|
: CrudRepositoryBase<DetectedOperationDto, DetectedOperation>, IDetectedOperationRepository
|
||||||
{
|
{
|
||||||
private readonly ITelemetryService telemetryService;
|
private readonly ITelemetryService telemetryService;
|
||||||
|
|
||||||
@ -26,6 +27,23 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
|
|||||||
this.telemetryService = telemetryService;
|
this.telemetryService = telemetryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IDictionary<int, DetectedOperationDto>> GetLastDetectedOperationsAsync(CancellationToken token)
|
||||||
|
{
|
||||||
|
var entities = await dbContext.Set<DetectedOperation>()
|
||||||
|
.GroupBy(o => o.IdTelemetry)
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
IdTelemetry = g.Key,
|
||||||
|
LastDetectedOperation = g.OrderBy(o => o.DateEnd).Last()
|
||||||
|
})
|
||||||
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
|
var dtos = entities.ToDictionary(x => x.IdTelemetry,
|
||||||
|
x => Convert(x.LastDetectedOperation));
|
||||||
|
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<int> DeleteAsync(DetectedOperationByTelemetryRequest request, CancellationToken token)
|
public async Task<int> DeleteAsync(DetectedOperationByTelemetryRequest request, CancellationToken token)
|
||||||
{
|
{
|
||||||
var query = BuildQuery(request);
|
var query = BuildQuery(request);
|
||||||
@ -33,6 +51,13 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
|
|||||||
return await dbContext.SaveChangesAsync(token);
|
return await dbContext.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = BuildQuery(request);
|
||||||
|
dbContext.Set<DetectedOperation>().RemoveRange(query);
|
||||||
|
return await dbContext.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<PaginationContainer<DetectedOperationDto>> GetPageAsync(DetectedOperationByTelemetryRequest request, CancellationToken token)
|
public async Task<PaginationContainer<DetectedOperationDto>> GetPageAsync(DetectedOperationByTelemetryRequest request, CancellationToken token)
|
||||||
{
|
{
|
||||||
var skip = request.Skip ?? 0;
|
var skip = request.Skip ?? 0;
|
||||||
@ -58,16 +83,6 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
|
|||||||
return paginationContainer;
|
return paginationContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IDictionary<int, DateTimeOffset>> GetLastDetectedDatesAsync(CancellationToken token) =>
|
|
||||||
await dbContext.Set<DetectedOperation>()
|
|
||||||
.GroupBy(o => o.IdTelemetry)
|
|
||||||
.Select(g => new
|
|
||||||
{
|
|
||||||
IdTelemetry = g.Key,
|
|
||||||
LastDate = g.Max(o => o.DateEnd)
|
|
||||||
})
|
|
||||||
.ToDictionaryAsync(x => x.IdTelemetry, x => x.LastDate, token);
|
|
||||||
|
|
||||||
public async Task<IEnumerable<DetectedOperationDto>> Get(DetectedOperationByTelemetryRequest request, CancellationToken token)
|
public async Task<IEnumerable<DetectedOperationDto>> Get(DetectedOperationByTelemetryRequest request, CancellationToken token)
|
||||||
{
|
{
|
||||||
var query = BuildQuery(request)
|
var query = BuildQuery(request)
|
||||||
@ -113,6 +128,26 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
|
|||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IQueryable<DetectedOperation> BuildQuery(TelemetryPartDeleteRequest request)
|
||||||
|
{
|
||||||
|
var query = dbContext.Set<DetectedOperation>()
|
||||||
|
.Where(o => o.IdTelemetry == request.IdTelemetry);
|
||||||
|
|
||||||
|
if (request.LeDate is not null)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateStart <= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.GeDate is not null)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateEnd >= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
private static DetectedOperationDto Convert(DetectedOperation src, TimeSpan offset)
|
private static DetectedOperationDto Convert(DetectedOperation src, TimeSpan offset)
|
||||||
{
|
{
|
||||||
var dto = src.Adapt<DetectedOperationDto>();
|
var dto = src.Adapt<DetectedOperationDto>();
|
||||||
|
@ -84,5 +84,33 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
dto.TimeStampStart = dto.TimeStampStart.ToRemoteDateTime(dto.Telemetry?.TimeZone?.Hours ?? 0);
|
dto.TimeStampStart = dto.TimeStampStart.ToRemoteDateTime(dto.Telemetry?.TimeZone?.Hours ?? 0);
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: Унифицировать модели данных телеметрии.Чтобы в будущем унифицировать репозитории данных телеметрии.
|
||||||
|
private IQueryable<DrillTest> BuildQuery(TelemetryPartDeleteRequest request)
|
||||||
|
{
|
||||||
|
var query = db.Set<DrillTest>()
|
||||||
|
.Where(o => o.IdTelemetry == request.IdTelemetry);
|
||||||
|
|
||||||
|
if (request.LeDate is not null)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.TimeStampStart <= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.GeDate is not null)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.TimeStampStart >= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = BuildQuery(request);
|
||||||
|
db.Set<DrillTest>().RemoveRange(query);
|
||||||
|
return await db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.GTR;
|
using AsbCloudApp.Data.GTR;
|
||||||
|
using AsbCloudApp.Exceptions;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb;
|
using AsbCloudDb;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using AsbCloudDb.Model.GTR;
|
using AsbCloudDb.Model.GTR;
|
||||||
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -12,11 +16,6 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Exceptions;
|
|
||||||
using AsbCloudApp.Requests;
|
|
||||||
using Mapster;
|
|
||||||
using AsbCloudApp.Data;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Repository
|
namespace AsbCloudInfrastructure.Repository
|
||||||
{
|
{
|
||||||
@ -130,7 +129,7 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
return Enumerable.Empty<GtrWitsDto>();
|
return Enumerable.Empty<GtrWitsDto>();
|
||||||
|
|
||||||
if (telemetry.TimeZone is null)
|
if (telemetry.TimeZone is null)
|
||||||
throw new ArgumentInvalidException(nameof(idWell),$"Telemetry id: {telemetry.Id} can't find timezone");
|
throw new ArgumentInvalidException(nameof(idWell), $"Telemetry id: {telemetry.Id} can't find timezone");
|
||||||
|
|
||||||
var query = BuildQuery<TEntity, TType>(telemetry.Id, request);
|
var query = BuildQuery<TEntity, TType>(telemetry.Id, request);
|
||||||
|
|
||||||
@ -183,7 +182,7 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var lastDate = query
|
var lastDate = query
|
||||||
.OrderBy(e=>e.DateTime)
|
.OrderBy(e => e.DateTime)
|
||||||
.LastOrDefault()
|
.LastOrDefault()
|
||||||
?.DateTime
|
?.DateTime
|
||||||
?? DateTimeOffset.UtcNow;
|
?? DateTimeOffset.UtcNow;
|
||||||
@ -362,14 +361,15 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
if (ints.Any())
|
if (ints.Any())
|
||||||
await db.Database.ExecInsertOrIgnoreAsync(db.Set<WitsItemInt>(), ints, token);
|
await db.Database.ExecInsertOrIgnoreAsync(db.Set<WitsItemInt>(), ints, token);
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Trace.TraceError("Exception while saving GTR Wits data", ex);
|
Trace.TraceError("Exception while saving GTR Wits data", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.AddOrUpdate(idTelemetry,
|
cache.AddOrUpdate(idTelemetry,
|
||||||
(_) => MakeNewCache(dtos),
|
(_) => MakeNewCache(dtos),
|
||||||
(_, oldItemsDictionary) => {
|
(_, oldItemsDictionary) =>
|
||||||
|
{
|
||||||
foreach (var record in dtos)
|
foreach (var record in dtos)
|
||||||
foreach (var item in record.Items)
|
foreach (var item in record.Items)
|
||||||
{
|
{
|
||||||
@ -398,7 +398,8 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
{
|
{
|
||||||
var items = dtos.SelectMany(record =>
|
var items = dtos.SelectMany(record =>
|
||||||
record.Items.Select(
|
record.Items.Select(
|
||||||
item => new WitsItemRecordDto {
|
item => new WitsItemRecordDto
|
||||||
|
{
|
||||||
IdItem = item.Key,
|
IdItem = item.Key,
|
||||||
IdRecord = record.Id,
|
IdRecord = record.Id,
|
||||||
Date = record.Date,
|
Date = record.Date,
|
||||||
@ -439,6 +440,47 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
Value = (TValue)dto.Value.Value,
|
Value = (TValue)dto.Value.Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private IQueryable<TEntity> BuildQuery<TEntity, TValue>(TelemetryPartDeleteRequest request)
|
||||||
|
where TEntity : WitsItemBase<TValue>
|
||||||
|
where TValue : notnull
|
||||||
|
{
|
||||||
|
var query = db.Set<TEntity>().Where(i => i.IdTelemetry == request.IdTelemetry);
|
||||||
|
|
||||||
|
if (request.LeDate is not null)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateTime <= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.GeDate is not null)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateTime >= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = 0;
|
||||||
|
result += await DeleteAsync<WitsItemFloat, float>(request, token);
|
||||||
|
result += await DeleteAsync<WitsItemInt, int>(request, token);
|
||||||
|
result += await DeleteAsync<WitsItemString, string>(request, token);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> DeleteAsync<TEntity, TType>(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
where TEntity : WitsItemBase<TType>
|
||||||
|
where TType : notnull
|
||||||
|
{
|
||||||
|
var query = BuildQuery<TEntity, TType>(request);
|
||||||
|
db.Set<TEntity>().RemoveRange(query);
|
||||||
|
return await db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private class WitsRequest
|
private class WitsRequest
|
||||||
{
|
{
|
||||||
public int IdTelemetry { get; set; }
|
public int IdTelemetry { get; set; }
|
||||||
|
@ -21,6 +21,13 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = BuildQuery(request);
|
||||||
|
context.Set<LimitingParameter>().RemoveRange(query);
|
||||||
|
return await context.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<LimitingParameterDataDto>> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token)
|
public async Task<IEnumerable<LimitingParameterDataDto>> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token)
|
||||||
{
|
{
|
||||||
var timezoneOffset = wellDto.Timezone.Hours;
|
var timezoneOffset = wellDto.Timezone.Hours;
|
||||||
@ -74,6 +81,26 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IQueryable<LimitingParameter> BuildQuery(TelemetryPartDeleteRequest request)
|
||||||
|
{
|
||||||
|
var query = context.Set<LimitingParameter>()
|
||||||
|
.Where(o => o.IdTelemetry == request.IdTelemetry);
|
||||||
|
|
||||||
|
if (request.LeDate is not null)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateStart <= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.GeDate is not null)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateEnd >= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
@ -20,7 +21,7 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
private readonly IAsbCloudDbContext db;
|
private readonly IAsbCloudDbContext db;
|
||||||
private readonly ITelemetryService telemetryService;
|
private readonly ITelemetryService telemetryService;
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<int, TDto> cache = new ();
|
private static readonly ConcurrentDictionary<int, TDto> cache = new();
|
||||||
|
|
||||||
public WitsRecordRepository(IAsbCloudDbContext db, ITelemetryService telemetryService)
|
public WitsRecordRepository(IAsbCloudDbContext db, ITelemetryService telemetryService)
|
||||||
{
|
{
|
||||||
@ -58,6 +59,33 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
return data.Select(d => Convert(d, timezoneHours));
|
return data.Select(d => Convert(d, timezoneHours));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IQueryable<TEntity> BuildQuery(TelemetryPartDeleteRequest request)
|
||||||
|
{
|
||||||
|
var query = db.Set<TEntity>()
|
||||||
|
.Where(o => o.IdTelemetry == request.IdTelemetry);
|
||||||
|
|
||||||
|
if (request.LeDate is not null)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateTime <= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.GeDate is not null)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateTime >= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = BuildQuery(request);
|
||||||
|
dbset.RemoveRange(query);
|
||||||
|
return await db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
public TDto? GetLastOrDefault(int idTelemetry)
|
public TDto? GetLastOrDefault(int idTelemetry)
|
||||||
=> cache.GetValueOrDefault(idTelemetry);
|
=> cache.GetValueOrDefault(idTelemetry);
|
||||||
|
|
||||||
@ -66,7 +94,7 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
if (!dtos.Any())
|
if (!dtos.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cache.AddOrUpdate(idTelemetry, dtos.Last(), (_,_) => dtos.OrderBy(r => r.DateTime).Last());
|
cache.AddOrUpdate(idTelemetry, dtos.Last(), (_, _) => dtos.OrderBy(r => r.DateTime).Last());
|
||||||
|
|
||||||
var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours;
|
var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours;
|
||||||
var entities = dtos
|
var entities = dtos
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -14,210 +13,219 @@ using AsbCloudApp.Exceptions;
|
|||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.WellOperation;
|
using AsbCloudApp.Data.WellOperation;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
||||||
|
|
||||||
public class DetectedOperationExportService
|
public class DetectedOperationExportService
|
||||||
{
|
{
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
|
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
|
||||||
private readonly IDetectedOperationService detectedOperationService;
|
private readonly IDetectedOperationRepository detectedOperationRepository;
|
||||||
private const int headerRowsCount = 1;
|
private const int headerRowsCount = 1;
|
||||||
|
|
||||||
private const string cellDepositName = "B1";
|
private const string cellDepositName = "B1";
|
||||||
private const string cellClusterName = "B2";
|
private const string cellClusterName = "B2";
|
||||||
private const string cellWellName = "B3";
|
private const string cellWellName = "B3";
|
||||||
private const string cellDeltaDate = "H2";
|
private const string cellDeltaDate = "H2";
|
||||||
|
|
||||||
private const int columnOperationName = 1;
|
private const int columnOperationName = 1;
|
||||||
private const int columnDateStart = 2;
|
private const int columnDateStart = 2;
|
||||||
private const int columnDateEnd = 3;
|
private const int columnDateEnd = 3;
|
||||||
private const int columnDuration = 4;
|
private const int columnDuration = 4;
|
||||||
private const int columnDepthStart = 5;
|
private const int columnDepthStart = 5;
|
||||||
private const int columnDepthEnd = 6;
|
private const int columnDepthEnd = 6;
|
||||||
private const int columnDeltaDepth = 7;
|
private const int columnDeltaDepth = 7;
|
||||||
private const int columnDepth = 8;
|
private const int columnDepth = 8;
|
||||||
private const int columnIdReasonOfEnd = 9;
|
private const int columnIdReasonOfEnd = 9;
|
||||||
private const int columnComment = 10;
|
private const int columnComment = 10;
|
||||||
|
|
||||||
public DetectedOperationExportService(IWellService wellService,
|
public DetectedOperationExportService(IWellService wellService,
|
||||||
IWellOperationCategoryRepository wellOperationCategoryRepository,
|
IWellOperationCategoryRepository wellOperationCategoryRepository,
|
||||||
IDetectedOperationService detectedOperationService)
|
IDetectedOperationRepository detectedOperationRepository)
|
||||||
{
|
{
|
||||||
this.wellService = wellService;
|
this.wellService = wellService;
|
||||||
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
|
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
|
||||||
this.detectedOperationService = detectedOperationService;
|
this.detectedOperationRepository = detectedOperationRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Экспорт excel файла с операциями по скважине
|
/// Экспорт excel файла с операциями по скважине
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell">ключ скважины</param>
|
/// <param name="idWell">ключ скважины</param>
|
||||||
/// <param name="host">хост</param>
|
/// <param name="host">хост</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="ArgumentInvalidException"></exception>
|
/// <exception cref="ArgumentInvalidException"></exception>
|
||||||
public async Task<Stream> ExportAsync(int idWell, string host, CancellationToken token)
|
public async Task<Stream> ExportAsync(int idWell, string host, CancellationToken token)
|
||||||
{
|
{
|
||||||
var well = await wellService.GetOrDefaultAsync(idWell, token);
|
var well = await wellService.GetOrDefaultAsync(idWell, token);
|
||||||
|
|
||||||
if (well is null)
|
if (well is null)
|
||||||
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} does not exist");
|
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} does not exist");
|
||||||
|
|
||||||
if (!well.IdTelemetry.HasValue)
|
if (!well.IdTelemetry.HasValue)
|
||||||
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} has no telemetry");
|
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} has no telemetry");
|
||||||
|
|
||||||
var operations = await detectedOperationService.DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, token);
|
var request = new DetectedOperationByTelemetryRequest
|
||||||
|
{
|
||||||
|
IdTelemetry = well.IdTelemetry.Value
|
||||||
|
};
|
||||||
|
|
||||||
return await GenerateExcelFileStreamAsync(well, host, operations, token);
|
var operations = await detectedOperationRepository.Get(request, token);
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Stream> GenerateExcelFileStreamAsync(WellDto well, string host, IEnumerable<DetectedOperationDto> operationDetectorResults,
|
return await GenerateExcelFileStreamAsync(well, host, operations, token);
|
||||||
CancellationToken cancellationToken)
|
}
|
||||||
{
|
|
||||||
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
|
||||||
|
|
||||||
using var workbook = new XLWorkbook(excelTemplateStream);
|
private async Task<Stream> GenerateExcelFileStreamAsync(WellDto well,
|
||||||
|
string host,
|
||||||
|
IEnumerable<DetectedOperationDto> operationDetectorResults,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
||||||
|
|
||||||
AddToWorkbook(workbook, well, host, operationDetectorResults);
|
using var workbook = new XLWorkbook(excelTemplateStream);
|
||||||
|
|
||||||
MemoryStream memoryStream = new MemoryStream();
|
AddToWorkbook(workbook, well, host, operationDetectorResults);
|
||||||
workbook.SaveAs(memoryStream, new SaveOptions { });
|
|
||||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
return memoryStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddToWorkbook(XLWorkbook workbook, WellDto well, string host, IEnumerable<DetectedOperationDto> operations)
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
{
|
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||||
const string sheetName = "Операции";
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
return memoryStream;
|
||||||
|
}
|
||||||
|
|
||||||
if (!operations.Any())
|
private void AddToWorkbook(XLWorkbook workbook, WellDto well, string host, IEnumerable<DetectedOperationDto> operations)
|
||||||
return;
|
{
|
||||||
|
const string sheetName = "Операции";
|
||||||
|
|
||||||
var sheet = workbook.GetWorksheet(sheetName);
|
if (!operations.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
var orderedOperations = operations
|
var sheet = workbook.GetWorksheet(sheetName);
|
||||||
.OrderBy(x => x.DateStart)
|
|
||||||
.ThenBy(x => x.DepthStart).ToArray();
|
|
||||||
|
|
||||||
AddToSheet(sheet, well, host, orderedOperations);
|
var orderedOperations = operations
|
||||||
}
|
.OrderBy(x => x.DateStart)
|
||||||
|
.ThenBy(x => x.DepthStart).ToArray();
|
||||||
|
|
||||||
private void AddToSheet(IXLWorksheet sheet, WellDto well, string host, IList<DetectedOperationDto> operations)
|
AddToSheet(sheet, well, host, orderedOperations);
|
||||||
{
|
}
|
||||||
var wellOperationCategories = wellOperationCategoryRepository.Get(true);
|
|
||||||
|
|
||||||
sheet.Cell(cellDepositName).SetCellValue(well.Deposit);
|
private void AddToSheet(IXLWorksheet sheet, WellDto well, string host, IList<DetectedOperationDto> operations)
|
||||||
sheet.Cell(cellClusterName).SetCellValue(well.Cluster);
|
{
|
||||||
sheet.Cell(cellWellName).SetCellValue(well.Caption);
|
var wellOperationCategories = wellOperationCategoryRepository.Get(true);
|
||||||
|
|
||||||
var deltaDate = operations.Max(o => o.DateEnd - o.DateStart);
|
sheet.Cell(cellDepositName).SetCellValue(well.Deposit);
|
||||||
|
sheet.Cell(cellClusterName).SetCellValue(well.Cluster);
|
||||||
|
sheet.Cell(cellWellName).SetCellValue(well.Caption);
|
||||||
|
|
||||||
sheet.Cell(cellDeltaDate).SetCellValue(deltaDate);
|
var deltaDate = operations.Max(o => o.DateEnd - o.DateStart);
|
||||||
|
|
||||||
for (int i = 0; i < operations.Count; i++)
|
sheet.Cell(cellDeltaDate).SetCellValue(deltaDate);
|
||||||
{
|
|
||||||
var current = operations[i];
|
|
||||||
var dateStart = current.DateStart.DateTime;
|
|
||||||
var dateEnd = current.DateEnd.DateTime;
|
|
||||||
|
|
||||||
var row = sheet.Row(5 + i + headerRowsCount);
|
for (int i = 0; i < operations.Count; i++)
|
||||||
|
{
|
||||||
|
var current = operations[i];
|
||||||
|
var dateStart = current.DateStart.DateTime;
|
||||||
|
var dateEnd = current.DateEnd.DateTime;
|
||||||
|
|
||||||
var categoryName = GetCategoryName(wellOperationCategories, current);
|
var row = sheet.Row(5 + i + headerRowsCount);
|
||||||
|
|
||||||
row.Cell(columnDateStart).SetCellValue(dateStart);
|
var categoryName = GetCategoryName(wellOperationCategories, current);
|
||||||
row.Cell(columnOperationName).SetCellValue(categoryName);
|
|
||||||
row.Cell(columnDateEnd).SetCellValue(dateEnd);
|
|
||||||
row.Cell(columnDuration).SetCellValue((dateEnd - dateStart).TotalMinutes);
|
|
||||||
row.Cell(columnDepthStart).SetCellValue(current.DepthStart);
|
|
||||||
row.Cell(columnDepthEnd).SetCellValue(current.DepthEnd);
|
|
||||||
row.Cell(columnDepth).SetCellValue(current.DepthEnd - current.DepthStart);
|
|
||||||
|
|
||||||
if (current.ExtraData.TryGetValue("IdReasonOfEnd", out object? idReasonOfEndObject)
|
row.Cell(columnDateStart).SetCellValue(dateStart);
|
||||||
&& idReasonOfEndObject is int idReasonOfEnd)
|
row.Cell(columnOperationName).SetCellValue(categoryName);
|
||||||
{
|
row.Cell(columnDateEnd).SetCellValue(dateEnd);
|
||||||
var reasonOfEnd = GetIdReasonOfEnd(idReasonOfEnd);
|
row.Cell(columnDuration).SetCellValue((dateEnd - dateStart).TotalMinutes);
|
||||||
row.Cell(columnIdReasonOfEnd).SetCellValue(reasonOfEnd);
|
row.Cell(columnDepthStart).SetCellValue(current.DepthStart);
|
||||||
}
|
row.Cell(columnDepthEnd).SetCellValue(current.DepthEnd);
|
||||||
|
row.Cell(columnDepth).SetCellValue(current.DepthEnd - current.DepthStart);
|
||||||
|
|
||||||
var query = new QueryBuilder();
|
if (current.ExtraData.TryGetValue("IdReasonOfEnd", out object? idReasonOfEndObject)
|
||||||
query.Add("end", dateStart.AddSeconds(1800 * 0.9).ToString("yyyy-MM-ddTHH:mm:ss.fff"));
|
&& idReasonOfEndObject is int idReasonOfEnd)
|
||||||
query.Add("range", "1800");
|
{
|
||||||
|
var reasonOfEnd = GetIdReasonOfEnd(idReasonOfEnd);
|
||||||
|
row.Cell(columnIdReasonOfEnd).SetCellValue(reasonOfEnd);
|
||||||
|
}
|
||||||
|
|
||||||
var link = $"{host}/well/{well.Id}/telemetry/monitoring{query}";
|
var query = new QueryBuilder();
|
||||||
row.Cell(columnDateStart).SetHyperlink(link);
|
query.Add("end", dateStart.AddSeconds(1800 * 0.9).ToString("yyyy-MM-ddTHH:mm:ss.fff"));
|
||||||
|
query.Add("range", "1800");
|
||||||
|
|
||||||
var deltaDepth = i > 0 && i + 1 < operations.Count
|
var link = $"{host}/well/{well.Id}/telemetry/monitoring{query}";
|
||||||
? current.DepthStart - operations[i - 1].DepthEnd
|
row.Cell(columnDateStart).SetHyperlink(link);
|
||||||
: 0;
|
|
||||||
|
|
||||||
row.Cell(columnDeltaDepth).SetCellValue(deltaDepth);
|
var deltaDepth = i > 0 && i + 1 < operations.Count
|
||||||
|
? current.DepthStart - operations[i - 1].DepthEnd
|
||||||
|
: 0;
|
||||||
|
|
||||||
var comment = CreateComment(operations[i]);
|
row.Cell(columnDeltaDepth).SetCellValue(deltaDepth);
|
||||||
row.Cell(columnComment).SetCellValue(comment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetCategoryName(IEnumerable<WellOperationCategoryDto> wellOperationCategories, DetectedOperationDto current)
|
var comment = CreateComment(operations[i]);
|
||||||
{
|
row.Cell(columnComment).SetCellValue(comment);
|
||||||
var idCategory = current.IdCategory;
|
}
|
||||||
if (idCategory == WellOperationCategory.IdSlide && current.EnabledSubsystems.IsAutoOscillation)
|
}
|
||||||
return "Бурение в слайде с осцилляцией";
|
|
||||||
|
|
||||||
var category = wellOperationCategories.FirstOrDefault(o => o.Id == current.IdCategory);
|
private static string GetCategoryName(IEnumerable<WellOperationCategoryDto> wellOperationCategories, DetectedOperationDto current)
|
||||||
|
{
|
||||||
|
var idCategory = current.IdCategory;
|
||||||
|
if (idCategory == WellOperationCategory.IdSlide && current.EnabledSubsystems.IsAutoOscillation)
|
||||||
|
return "Бурение в слайде с осцилляцией";
|
||||||
|
|
||||||
if(category is not null)
|
var category = wellOperationCategories.FirstOrDefault(o => o.Id == current.IdCategory);
|
||||||
return category.Name;
|
|
||||||
|
|
||||||
return $"Операция №{idCategory}";
|
if (category is not null)
|
||||||
}
|
return category.Name;
|
||||||
|
|
||||||
private static string GetIdReasonOfEnd(int idReasonOfEnd)
|
return $"Операция №{idCategory}";
|
||||||
=> idReasonOfEnd switch {
|
}
|
||||||
0 => "Не определена",
|
|
||||||
1 => "Не определено начало операции",
|
|
||||||
101 => "Разница глубин забоя и положением долота",
|
|
||||||
300 => "Низкое давление",
|
|
||||||
301 => "Высокое давление",
|
|
||||||
700 => "Изменение глубины долота и осевая нагрузка < веса на крюке",
|
|
||||||
_ => idReasonOfEnd.ToString($"Причина № {idReasonOfEnd}"),
|
|
||||||
|
|
||||||
};
|
private static string GetIdReasonOfEnd(int idReasonOfEnd)
|
||||||
|
=> idReasonOfEnd switch
|
||||||
|
{
|
||||||
|
0 => "Не определена",
|
||||||
|
1 => "Не определено начало операции",
|
||||||
|
101 => "Разница глубин забоя и положением долота",
|
||||||
|
300 => "Низкое давление",
|
||||||
|
301 => "Высокое давление",
|
||||||
|
700 => "Изменение глубины долота и осевая нагрузка < веса на крюке",
|
||||||
|
_ => idReasonOfEnd.ToString($"Причина № {idReasonOfEnd}"),
|
||||||
|
};
|
||||||
|
|
||||||
private async Task<Stream> GetExcelTemplateStreamAsync(CancellationToken cancellationToken)
|
private async Task<Stream> GetExcelTemplateStreamAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
string resourceName = Assembly.GetExecutingAssembly()
|
string resourceName = Assembly.GetExecutingAssembly()
|
||||||
.GetManifestResourceNames()
|
.GetManifestResourceNames()
|
||||||
.FirstOrDefault(n => n.EndsWith("DetectOperations.xlsx"))!;
|
.FirstOrDefault(n => n.EndsWith("DetectOperations.xlsx"))!;
|
||||||
|
|
||||||
using var stream = Assembly.GetExecutingAssembly()
|
using var stream = Assembly.GetExecutingAssembly()
|
||||||
.GetManifestResourceStream(resourceName)!;
|
.GetManifestResourceStream(resourceName)!;
|
||||||
|
|
||||||
var memoryStream = new MemoryStream();
|
var memoryStream = new MemoryStream();
|
||||||
await stream.CopyToAsync(memoryStream, cancellationToken);
|
await stream.CopyToAsync(memoryStream, cancellationToken);
|
||||||
memoryStream.Position = 0;
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
return memoryStream;
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string CreateComment(DetectedOperationDto operation)
|
private static string CreateComment(DetectedOperationDto operation)
|
||||||
{
|
{
|
||||||
switch (operation.IdCategory)
|
switch (operation.IdCategory)
|
||||||
{
|
{
|
||||||
case WellOperationCategory.IdRotor:
|
case WellOperationCategory.IdRotor:
|
||||||
case WellOperationCategory.IdSlide:
|
case WellOperationCategory.IdSlide:
|
||||||
var comment = "";
|
var comment = "";
|
||||||
if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyAvgRotorSpeed, out object? oAvgRotorSpeed))
|
if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyAvgRotorSpeed, out object? oAvgRotorSpeed))
|
||||||
comment += $"Средняя скорость оборотов ротора: {oAvgRotorSpeed}\r\n";
|
comment += $"Средняя скорость оборотов ротора: {oAvgRotorSpeed}\r\n";
|
||||||
|
|
||||||
if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyDispersionOfNormalizedRotorSpeed, out object? oDispersionOfNormalizedRotorSpeed))
|
if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyDispersionOfNormalizedRotorSpeed,
|
||||||
comment += $"Дисперсия нормированных оборотов ротора: {oDispersionOfNormalizedRotorSpeed}";
|
out object? oDispersionOfNormalizedRotorSpeed))
|
||||||
|
comment += $"Дисперсия нормированных оборотов ротора: {oDispersionOfNormalizedRotorSpeed}";
|
||||||
|
|
||||||
return comment;
|
return comment;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -110,7 +110,7 @@ public class DetectedOperationService : IDetectedOperationService
|
|||||||
private async Task<int> GetIdTelemetryByWell(int idWell, CancellationToken token)
|
private async Task<int> GetIdTelemetryByWell(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var well = await wellService.GetOrDefaultAsync(idWell, token) ??
|
var well = await wellService.GetOrDefaultAsync(idWell, token) ??
|
||||||
throw new ArgumentInvalidException(nameof(idWell), "Well doesn`t exist");
|
throw new ArgumentInvalidException(nameof(idWell), "Well doesn't exist");
|
||||||
|
|
||||||
var idTelemetry = well.IdTelemetry ??
|
var idTelemetry = well.IdTelemetry ??
|
||||||
throw new ArgumentInvalidException(nameof(idWell), "У скважины отсутствует телеметрия");
|
throw new ArgumentInvalidException(nameof(idWell), "У скважины отсутствует телеметрия");
|
||||||
@ -177,72 +177,73 @@ public class DetectedOperationService : IDetectedOperationService
|
|||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<DetectedOperationDto>> DetectOperationsAsync(int idTelemetry, DateTimeOffset? beginDate, CancellationToken token)
|
public async Task<(DateTimeOffset LastDate, IEnumerable<DetectedOperationDto> Items)> DetectOperationsAsync(int idTelemetry,
|
||||||
|
TelemetryDataRequest request,
|
||||||
|
DetectedOperationDto? lastDetectedOperation,
|
||||||
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
const int take = 4 * 86_400;
|
|
||||||
|
|
||||||
var detectedOperations = new List<DetectedOperationDto>();
|
|
||||||
DetectedOperationDto? lastDetectedOperation = null;
|
|
||||||
const int minOperationLength = 5;
|
const int minOperationLength = 5;
|
||||||
const int maxDetectorsInterpolationFrameLength = 30;
|
const int maxDetectorsInterpolationFrameLength = 30;
|
||||||
const int gap = maxDetectorsInterpolationFrameLength + minOperationLength;
|
const int gap = maxDetectorsInterpolationFrameLength + minOperationLength;
|
||||||
var timezone = telemetryService.GetTimezone(idTelemetry);
|
|
||||||
|
|
||||||
while (true)
|
var telemetries = await telemetryDataSaubService.GetByTelemetryAsync(idTelemetry, request, token);
|
||||||
|
|
||||||
|
var count = telemetries.Count();
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
throw new InvalidOperationException("InvalidOperation_EmptyTelemetries");
|
||||||
|
|
||||||
|
var timeZone = telemetryService.GetTimezone(idTelemetry);
|
||||||
|
|
||||||
|
var detectedOperations = new List<DetectedOperationDto>();
|
||||||
|
|
||||||
|
var detectableTelemetries = telemetries
|
||||||
|
.Where(t => t.BlockPosition >= 0)
|
||||||
|
.Select(t => new DetectableTelemetry
|
||||||
|
{
|
||||||
|
DateTime = new DateTimeOffset(t.DateTime, timeZone.Offset),
|
||||||
|
IdUser = t.IdUser,
|
||||||
|
Mode = t.Mode,
|
||||||
|
WellDepth = t.WellDepth,
|
||||||
|
Pressure = t.Pressure,
|
||||||
|
HookWeight = t.HookWeight,
|
||||||
|
BlockPosition = t.BlockPosition,
|
||||||
|
BitDepth = t.BitDepth,
|
||||||
|
RotorSpeed = t.RotorSpeed,
|
||||||
|
AxialLoad = t.AxialLoad,
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
|
if (detectableTelemetries.Length <= gap)
|
||||||
{
|
{
|
||||||
var request = new TelemetryDataRequest
|
var lastTelemetry = telemetries.Last();
|
||||||
{
|
var lastDateTelemetry = new DateTimeOffset(lastTelemetry.DateTime, timeZone.Offset);
|
||||||
GeDate = beginDate,
|
return (lastDateTelemetry, Enumerable.Empty<DetectedOperationDto>());
|
||||||
Take = take,
|
|
||||||
Order = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
var dtos = await telemetryDataSaubService.GetByTelemetryAsync(idTelemetry, request, token);
|
|
||||||
var detectableTelemetries = dtos
|
|
||||||
.Where(t => t.BlockPosition >= 0)
|
|
||||||
.Select(t => new DetectableTelemetry
|
|
||||||
{
|
|
||||||
DateTime = new DateTimeOffset(t.DateTime, timezone.Offset),
|
|
||||||
IdUser = t.IdUser,
|
|
||||||
Mode = t.Mode,
|
|
||||||
WellDepth = t.WellDepth,
|
|
||||||
Pressure = t.Pressure,
|
|
||||||
HookWeight = t.HookWeight,
|
|
||||||
BlockPosition = t.BlockPosition,
|
|
||||||
BitDepth = t.BitDepth,
|
|
||||||
RotorSpeed = t.RotorSpeed,
|
|
||||||
AxialLoad = t.AxialLoad,
|
|
||||||
}).ToArray();
|
|
||||||
|
|
||||||
if (detectableTelemetries.Length <= gap)
|
|
||||||
break;
|
|
||||||
|
|
||||||
var isDetected = false;
|
|
||||||
var positionBegin = 0;
|
|
||||||
var positionEnd = detectableTelemetries.Length - gap;
|
|
||||||
while (positionEnd > positionBegin)
|
|
||||||
{
|
|
||||||
foreach (var detector in detectors)
|
|
||||||
{
|
|
||||||
if (!detector.TryDetect(idTelemetry, detectableTelemetries, positionBegin, positionEnd, lastDetectedOperation, out var result))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
detectedOperations.Add(result!.Operation);
|
|
||||||
lastDetectedOperation = result.Operation;
|
|
||||||
isDetected = true;
|
|
||||||
positionBegin = result.TelemetryEnd;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
positionBegin += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
beginDate = isDetected
|
|
||||||
? lastDetectedOperation!.DateEnd
|
|
||||||
: detectableTelemetries[positionEnd].DateTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return detectedOperations;
|
var positionBegin = 0;
|
||||||
|
var positionEnd = detectableTelemetries.Length - gap;
|
||||||
|
|
||||||
|
while (positionEnd > positionBegin)
|
||||||
|
{
|
||||||
|
foreach (var detector in detectors)
|
||||||
|
{
|
||||||
|
if (!detector.TryDetect(idTelemetry, detectableTelemetries, positionBegin, positionEnd, lastDetectedOperation,
|
||||||
|
out var result))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
detectedOperations.Add(result!.Operation);
|
||||||
|
lastDetectedOperation = result.Operation;
|
||||||
|
positionBegin = result.TelemetryEnd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var point0 = detectableTelemetries[positionBegin];
|
||||||
|
|
||||||
|
while (positionBegin < positionEnd && IsChangingTelemetryInterval(point0, detectableTelemetries[positionBegin]))
|
||||||
|
positionBegin++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (detectableTelemetries[positionBegin].DateTime, detectedOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token)
|
public async Task<int> DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token)
|
||||||
@ -256,6 +257,23 @@ public class DetectedOperationService : IDetectedOperationService
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsChangingTelemetryInterval(DetectableTelemetry telemetryBegin, DetectableTelemetry telemetryEnd)
|
||||||
|
{
|
||||||
|
return telemetryBegin.Mode == telemetryEnd.Mode &&
|
||||||
|
EqualParameter(telemetryBegin.WellDepth, telemetryEnd.WellDepth, 0.01f) &&
|
||||||
|
EqualParameter(telemetryBegin.Pressure, telemetryEnd.Pressure, 0.1f) &&
|
||||||
|
EqualParameter(telemetryBegin.HookWeight, telemetryEnd.HookWeight, 0.1f) &&
|
||||||
|
EqualParameter(telemetryBegin.BlockPosition, telemetryEnd.BlockPosition, 0.01f) &&
|
||||||
|
EqualParameter(telemetryBegin.BitDepth, telemetryEnd.BitDepth, 0.01f) &&
|
||||||
|
EqualParameter(telemetryBegin.RotorSpeed, telemetryEnd.RotorSpeed, 0.01f) &&
|
||||||
|
EqualParameter(telemetryBegin.AxialLoad, telemetryEnd.AxialLoad, 0.1f);
|
||||||
|
|
||||||
|
static bool EqualParameter(float value, float origin, float tolerance)
|
||||||
|
{
|
||||||
|
return value <= origin + tolerance && value >= origin - tolerance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerable<DetectedOperationDrillersStatDto> GetOperationsDrillersStat(IEnumerable<DetectedOperationWithDrillerDto> operations)
|
private static IEnumerable<DetectedOperationDrillersStatDto> GetOperationsDrillersStat(IEnumerable<DetectedOperationWithDrillerDto> operations)
|
||||||
{
|
{
|
||||||
var groups = operations.GroupBy(o => o.Driller);
|
var groups = operations.GroupBy(o => o.Driller);
|
||||||
@ -305,7 +323,6 @@ public class DetectedOperationService : IDetectedOperationService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static DetectedOperationWithDrillerDto Convert(DetectedOperationDto operation, IEnumerable<OperationValueDto> operationValues, IEnumerable<ScheduleDto> schedules)
|
private static DetectedOperationWithDrillerDto Convert(DetectedOperationDto operation, IEnumerable<OperationValueDto> operationValues, IEnumerable<ScheduleDto> schedules)
|
||||||
{
|
{
|
||||||
var dto = operation.Adapt<DetectedOperationWithDrillerDto>();
|
var dto = operation.Adapt<DetectedOperationWithDrillerDto>();
|
||||||
|
@ -2,410 +2,410 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using AsbCloudApp.Data.DetectedOperation;
|
using AsbCloudApp.Data.DetectedOperation;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
|
|
||||||
|
public abstract class DetectorAbstract
|
||||||
{
|
{
|
||||||
public abstract class DetectorAbstract
|
protected const int IdReasonOfEnd_NotDetected = 0;
|
||||||
|
protected const int IdReasonOfEnd_NotDetectBegin = 1;
|
||||||
|
|
||||||
|
protected const int IdReasonOfEnd_DeltaDepthIsLo = 100;
|
||||||
|
protected const int IdReasonOfEnd_DeltaDepthIsHi = 101;
|
||||||
|
protected const int IdReasonOfEnd_DeltaDepthOutOfRange = 102;
|
||||||
|
protected const int IdReasonOfEnd_WellDepthDeviates = 200;
|
||||||
|
|
||||||
|
protected const int IdReasonOfEnd_PressureIsLo = 300;
|
||||||
|
protected const int IdReasonOfEnd_PressureIsHi = 301;
|
||||||
|
protected const int IdReasonOfEnd_PressureOutOfRange = 302;
|
||||||
|
protected const int IdReasonOfEnd_PressureIsRising = 303;
|
||||||
|
|
||||||
|
protected const int IdReasonOfEnd_RotorSpeedIsLo = 400;
|
||||||
|
protected const int IdReasonOfEnd_RotorSpeedIsHi = 401;
|
||||||
|
protected const int IdReasonOfEnd_AvgRotorSpeedIsHi = 402;
|
||||||
|
protected const int IdReasonOfEnd_AvgRotorSpeedIsLo = 403;
|
||||||
|
|
||||||
|
protected const int IdReasonOfEnd_BlockPositionIsLo = 500;
|
||||||
|
protected const int IdReasonOfEnd_BlockPositionIsHi = 501;
|
||||||
|
protected const int IdReasonOfEnd_BlockPositionDeviates = 502;
|
||||||
|
|
||||||
|
protected const int IdReasonOfEnd_Drilling = 600;
|
||||||
|
|
||||||
|
protected const int IdReasonOfEnd_ChangeBitDepthAndAxiLoadLessHookWeight = 700;
|
||||||
|
|
||||||
|
protected const int IdReasonOfEnd_DeltaWellDepthAndBitDepthIsLo = 800;
|
||||||
|
|
||||||
|
protected const int IdReasonOfEnd_BitDepthIsLo = 900;
|
||||||
|
|
||||||
|
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperationDto? previousOperation,
|
||||||
|
out OperationDetectorResult? result)
|
||||||
{
|
{
|
||||||
protected const int IdReasonOfEnd_NotDetected = 0;
|
// Проверка соответствия критерию начала операции
|
||||||
protected const int IdReasonOfEnd_NotDetectBegin = 1;
|
if (DetectBegin(telemetry, begin, previousOperation))
|
||||||
|
|
||||||
protected const int IdReasonOfEnd_DeltaDepthIsLo = 100;
|
|
||||||
protected const int IdReasonOfEnd_DeltaDepthIsHi = 101;
|
|
||||||
protected const int IdReasonOfEnd_DeltaDepthOutOfRange = 102;
|
|
||||||
protected const int IdReasonOfEnd_WellDepthDeviates = 200;
|
|
||||||
|
|
||||||
protected const int IdReasonOfEnd_PressureIsLo = 300;
|
|
||||||
protected const int IdReasonOfEnd_PressureIsHi = 301;
|
|
||||||
protected const int IdReasonOfEnd_PressureOutOfRange = 302;
|
|
||||||
protected const int IdReasonOfEnd_PressureIsRising = 303;
|
|
||||||
|
|
||||||
protected const int IdReasonOfEnd_RotorSpeedIsLo = 400;
|
|
||||||
protected const int IdReasonOfEnd_RotorSpeedIsHi = 401;
|
|
||||||
protected const int IdReasonOfEnd_AvgRotorSpeedIsHi = 402;
|
|
||||||
protected const int IdReasonOfEnd_AvgRotorSpeedIsLo = 403;
|
|
||||||
|
|
||||||
protected const int IdReasonOfEnd_BlockPositionIsLo = 500;
|
|
||||||
protected const int IdReasonOfEnd_BlockPositionIsHi = 501;
|
|
||||||
protected const int IdReasonOfEnd_BlockPositionDeviates = 502;
|
|
||||||
|
|
||||||
protected const int IdReasonOfEnd_Drilling = 600;
|
|
||||||
|
|
||||||
protected const int IdReasonOfEnd_ChangeBithDepthAndAxiloadLessHookWeight = 700;
|
|
||||||
|
|
||||||
protected const int IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo = 800;
|
|
||||||
|
|
||||||
protected const int IdReasonOfEnd_BithDepthIsLo = 900;
|
|
||||||
|
|
||||||
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperationDto? previousOperation,
|
|
||||||
out OperationDetectorResult? result)
|
|
||||||
{
|
{
|
||||||
// Проверка соответствия критерию начала операции
|
// Поиск окончания соответствия критерию
|
||||||
if (DetectBegin(telemetry, begin, previousOperation))
|
int idReasonOfEnd = 0;
|
||||||
|
var positionEnd = begin;
|
||||||
|
|
||||||
|
while (positionEnd < end)
|
||||||
{
|
{
|
||||||
// Поиск окончания соответствия критерию
|
positionEnd += 1;
|
||||||
int idReasonOfEnd = 0;
|
if (positionEnd > end)
|
||||||
var positionEnd = begin;
|
break;
|
||||||
|
|
||||||
while (positionEnd < end)
|
//TODO: поиск провалов телеметрий. Следует обсудить, так как алгоритмы теряют в точности.
|
||||||
{
|
|
||||||
positionEnd += 1;
|
|
||||||
if (positionEnd > end)
|
|
||||||
break;
|
|
||||||
|
|
||||||
idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation);
|
idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation);
|
||||||
|
|
||||||
if (idReasonOfEnd != IdReasonOfEnd_NotDetected)
|
if (idReasonOfEnd != IdReasonOfEnd_NotDetected)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
var (Begin, End) = RefineEdges(telemetry, begin, positionEnd);
|
|
||||||
|
|
||||||
result = MakeOperationDetectorResult(idTelemetry, telemetry, Begin, End, idReasonOfEnd);
|
|
||||||
|
|
||||||
return IsValidOperationDetectorResult(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = null;
|
var (Begin, End) = RefineEdges(telemetry, begin, positionEnd);
|
||||||
|
|
||||||
|
result = MakeOperationDetectorResult(idTelemetry, telemetry, Begin, End, idReasonOfEnd);
|
||||||
|
|
||||||
|
return IsValidOperationDetectorResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual (int Begin, int End) RefineEdges(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
=> (begin, end);
|
||||||
|
|
||||||
|
protected virtual bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult)
|
||||||
|
=> operationDetectorResult.Operation.DateEnd - operationDetectorResult.Operation.DateStart > TimeSpan.FromSeconds(3);
|
||||||
|
|
||||||
|
protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation);
|
||||||
|
|
||||||
|
protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
|
||||||
|
=> DetectBegin(telemetry, position, previousOperation)
|
||||||
|
? IdReasonOfEnd_NotDetected
|
||||||
|
: IdReasonOfEnd_NotDetectBegin;
|
||||||
|
|
||||||
|
private OperationDetectorResult MakeOperationDetectorResult(
|
||||||
|
int idTelemetry,
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
int begin,
|
||||||
|
int end,
|
||||||
|
int idReasonOfEnd)
|
||||||
|
{
|
||||||
|
var operation = MakeDetectedOperation(idTelemetry, telemetry, begin, end);
|
||||||
|
|
||||||
|
operation.ExtraData["IdReasonOfEnd"] = idReasonOfEnd;
|
||||||
|
|
||||||
|
var result = new OperationDetectorResult
|
||||||
|
{
|
||||||
|
TelemetryBegin = begin,
|
||||||
|
TelemetryEnd = end,
|
||||||
|
Operation = operation,
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DetectedOperationDto MakeDetectedOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
var (IdCategory, ExtraData) = GetSpecificInformation(telemetry, begin, end);
|
||||||
|
var operation = new DetectedOperationDto
|
||||||
|
{
|
||||||
|
IdCategory = IdCategory,
|
||||||
|
IdTelemetry = idTelemetry,
|
||||||
|
IdUserAtStart = pBegin.IdUser ?? -1,
|
||||||
|
DateStart = pBegin.DateTime,
|
||||||
|
DateEnd = pEnd.DateTime,
|
||||||
|
DepthStart = (double)pBegin.WellDepth,
|
||||||
|
DepthEnd = (double)pEnd.WellDepth,
|
||||||
|
ExtraData = ExtraData,
|
||||||
|
Value = CalcValue(telemetry, begin, end),
|
||||||
|
EnabledSubsystems = DetectEnabledSubsystems(telemetry, begin, end, ExtraData)
|
||||||
|
};
|
||||||
|
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение информации специфичной для конкретного детектора
|
||||||
|
/// IdCategory - одна из констант WellOperationCategory
|
||||||
|
/// ExtraData - дополнительная информация для отладки алгоритмов авто определения
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected abstract (int IdCategory, IDictionary<string, object> ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Расчет ключевого параметра операции
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="end"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Определение включенных подсистем во время выполнения операции
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="end"></param>
|
||||||
|
/// <param name="extraData"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static int DetectEnabledSubsystems(DetectableTelemetry[] telemetry, int begin, int end, IDictionary<string, object> extraData)
|
||||||
|
{
|
||||||
|
var enabledSubsystems = 0;
|
||||||
|
|
||||||
|
if (extraData.TryGetValue(DetectorDrilling.ExtraDataKeyHasOscillation, out var hasOscillation)
|
||||||
|
&& hasOscillation is true)
|
||||||
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoOscillation;
|
||||||
|
|
||||||
|
for (var i = begin; i < end; i += 2)
|
||||||
|
{
|
||||||
|
var mode = telemetry[i].Mode;
|
||||||
|
|
||||||
|
if(mode == 1)
|
||||||
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoRotor;
|
||||||
|
|
||||||
|
if (mode == 3)
|
||||||
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoSlide;
|
||||||
|
|
||||||
|
if (mode == 2)
|
||||||
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoConditionig;
|
||||||
|
|
||||||
|
if (mode == 4)
|
||||||
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoSinking;
|
||||||
|
|
||||||
|
if (mode == 5)
|
||||||
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoLifting;
|
||||||
|
|
||||||
|
if (mode == 6)
|
||||||
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoLiftingWithConditionig;
|
||||||
|
|
||||||
|
if (mode == 10)
|
||||||
|
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoBlocknig;
|
||||||
|
}
|
||||||
|
|
||||||
|
return enabledSubsystems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// расчет продолжительности операции
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="end"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static double CalcDeltaMinutes(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
var result = (pEnd.DateTime - pBegin.DateTime).TotalMinutes;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// часто используемый предикат для определения отсутствия изменения глубины ствола скважины
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="end"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static bool IsValidByWellDepthDoesNotChange(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
if (Math.Abs((double)(pBegin.WellDepth - pEnd.WellDepth)) > 0.01)
|
||||||
return false;
|
return false;
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
protected virtual (int Begin, int End) RefineEdges(DetectableTelemetry[] telemetry, int begin, int end)
|
|
||||||
=> (begin, end);
|
|
||||||
|
|
||||||
protected virtual bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult)
|
|
||||||
=> operationDetectorResult.Operation.DateEnd - operationDetectorResult.Operation.DateStart > TimeSpan.FromSeconds(3);
|
|
||||||
|
|
||||||
protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation);
|
|
||||||
|
|
||||||
protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
|
|
||||||
=> DetectBegin(telemetry, position, previousOperation)
|
|
||||||
? IdReasonOfEnd_NotDetected
|
|
||||||
: IdReasonOfEnd_NotDetectBegin;
|
|
||||||
|
|
||||||
private OperationDetectorResult MakeOperationDetectorResult(
|
|
||||||
int idTelemetry,
|
|
||||||
DetectableTelemetry[] telemetry,
|
|
||||||
int begin,
|
|
||||||
int end,
|
|
||||||
int idReasonOfEnd)
|
|
||||||
{
|
|
||||||
var operation = MakeDetectedOperation(idTelemetry, telemetry, begin, end);
|
|
||||||
|
|
||||||
operation.ExtraData["IdReasonOfEnd"] = idReasonOfEnd;
|
|
||||||
|
|
||||||
var result = new OperationDetectorResult
|
|
||||||
{
|
|
||||||
TelemetryBegin = begin,
|
|
||||||
TelemetryEnd = end,
|
|
||||||
Operation = operation,
|
|
||||||
};
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DetectedOperationDto MakeDetectedOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end)
|
|
||||||
{
|
|
||||||
var pBegin = telemetry[begin];
|
|
||||||
var pEnd = telemetry[end];
|
|
||||||
var (IdCategory, ExtraData) = GetSpecificInformation(telemetry, begin, end);
|
|
||||||
var operation = new DetectedOperationDto
|
|
||||||
{
|
|
||||||
IdCategory = IdCategory,
|
|
||||||
IdTelemetry = idTelemetry,
|
|
||||||
IdUserAtStart = pBegin.IdUser ?? -1,
|
|
||||||
DateStart = pBegin.DateTime,
|
|
||||||
DateEnd = pEnd.DateTime,
|
|
||||||
DepthStart = (double)pBegin.WellDepth,
|
|
||||||
DepthEnd = (double)pEnd.WellDepth,
|
|
||||||
ExtraData = ExtraData,
|
|
||||||
Value = CalcValue(telemetry, begin, end),
|
|
||||||
EnabledSubsystems = DetectEnabledSubsystems(telemetry, begin, end, ExtraData)
|
|
||||||
};
|
|
||||||
|
|
||||||
return operation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение информации специфичной для конкретного детектора
|
|
||||||
/// IdCategory - одна из констант WellOperationCategory
|
|
||||||
/// ExtraData - дополнительная информация для отладки алгоритмов авто определения
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected abstract (int IdCategory, IDictionary<string, object> ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Расчет ключевого параметра операции
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="begin"></param>
|
|
||||||
/// <param name="end"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Определение включенных подсистем во время выполнения операции
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="begin"></param>
|
|
||||||
/// <param name="end"></param>
|
|
||||||
/// <param name="extraData"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private static int DetectEnabledSubsystems(DetectableTelemetry[] telemetry, int begin, int end, IDictionary<string, object> extraData)
|
|
||||||
{
|
|
||||||
var enabledSubsystems = 0;
|
|
||||||
|
|
||||||
if (extraData.TryGetValue(DetectorDrilling.ExtraDataKeyHasOscillation, out var hasOscillation)
|
|
||||||
&& hasOscillation is true)
|
|
||||||
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoOscillation;
|
|
||||||
|
|
||||||
for (var i = begin; i < end; i += 2)
|
|
||||||
{
|
|
||||||
var mode = telemetry[i].Mode;
|
|
||||||
|
|
||||||
if(mode == 1)
|
|
||||||
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoRotor;
|
|
||||||
|
|
||||||
if (mode == 3)
|
|
||||||
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoSlide;
|
|
||||||
|
|
||||||
if (mode == 2)
|
|
||||||
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoConditionig;
|
|
||||||
|
|
||||||
if (mode == 4)
|
|
||||||
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoSinking;
|
|
||||||
|
|
||||||
if (mode == 5)
|
|
||||||
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoLifting;
|
|
||||||
|
|
||||||
if (mode == 6)
|
|
||||||
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoLiftingWithConditionig;
|
|
||||||
|
|
||||||
if (mode == 10)
|
|
||||||
enabledSubsystems |= (int)EnabledSubsystemsFlags.AutoBlocknig;
|
|
||||||
}
|
|
||||||
|
|
||||||
return enabledSubsystems;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// расчет продолжительности операции
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="begin"></param>
|
|
||||||
/// <param name="end"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected static double CalcDeltaMinutes(DetectableTelemetry[] telemetry, int begin, int end)
|
|
||||||
{
|
|
||||||
var pBegin = telemetry[begin];
|
|
||||||
var pEnd = telemetry[end];
|
|
||||||
var result = (pEnd.DateTime - pBegin.DateTime).TotalMinutes;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// часто используемый предикат для определения отсутствия изменения глубины ствола скважины
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="begin"></param>
|
|
||||||
/// <param name="end"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected static bool IsValidByWellDepthDoesNotChange(DetectableTelemetry[] telemetry, int begin, int end)
|
|
||||||
{
|
|
||||||
var pBegin = telemetry[begin];
|
|
||||||
var pEnd = telemetry[end];
|
|
||||||
if (Math.Abs((double)(pBegin.WellDepth - pEnd.WellDepth)) > 0.01)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static bool IsValidByWellDepthIncreasing(DetectableTelemetry[] telemetry, int begin, int end)
|
|
||||||
{
|
|
||||||
var pBegin = telemetry[begin];
|
|
||||||
var pEnd = telemetry[end];
|
|
||||||
if (pBegin.WellDepth >= pEnd.WellDepth)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static double CalcRop(DetectableTelemetry[] telemetry, int begin, int end)
|
|
||||||
{
|
|
||||||
var pBegin = telemetry[begin];
|
|
||||||
var pEnd = telemetry[end];
|
|
||||||
var result = (double)(pEnd.WellDepth - pBegin.WellDepth) / (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Расчет статистики по массиву данных за интервал
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="getter"></param>
|
|
||||||
/// <param name="begin"></param>
|
|
||||||
/// <param name="count"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected static (double min, double max, double sum, int count) CalcStat(
|
|
||||||
DetectableTelemetry[] telemetry,
|
|
||||||
Func<DetectableTelemetry, double> getter,
|
|
||||||
int begin,
|
|
||||||
int count)
|
|
||||||
{
|
|
||||||
var sum = 0d;
|
|
||||||
var min = double.MaxValue;
|
|
||||||
var max = double.MinValue;
|
|
||||||
var end = begin + count;
|
|
||||||
end = end < telemetry.Length ? end : telemetry.Length;
|
|
||||||
|
|
||||||
for (var i = begin; i < end; i++)
|
|
||||||
{
|
|
||||||
var item = telemetry[i];
|
|
||||||
var itemValue = getter(item);
|
|
||||||
if (min > itemValue)
|
|
||||||
min = itemValue;
|
|
||||||
if (max < itemValue)
|
|
||||||
max = itemValue;
|
|
||||||
sum += itemValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (min, max, sum, end - begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Максимальное отклонение от среднего за интервал
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="getter"></param>
|
|
||||||
/// <param name="begin"></param>
|
|
||||||
/// <param name="count"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected static double CalcMaxDeviation(
|
|
||||||
DetectableTelemetry[] telemetry,
|
|
||||||
Func<DetectableTelemetry, double> getter,
|
|
||||||
int begin,
|
|
||||||
int count)
|
|
||||||
{
|
|
||||||
var stat = CalcStat(telemetry, getter, begin, count);
|
|
||||||
var avg = stat.sum / stat.count;
|
|
||||||
var dev1 = avg - stat.min;
|
|
||||||
var dev2 = stat.max - avg;
|
|
||||||
var dev = dev1 > dev2 ? dev1 : dev2;
|
|
||||||
return dev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Определяет наличие разброса значений в интервале большего указанного значения.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="telemetry"></param>
|
|
||||||
/// <param name="getter"></param>
|
|
||||||
/// <param name="begin"></param>
|
|
||||||
/// <param name="count"></param>
|
|
||||||
/// <param name="deviation"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected static bool ContainsDeviation(
|
|
||||||
DetectableTelemetry[] telemetry,
|
|
||||||
Func<DetectableTelemetry, double> getter,
|
|
||||||
int begin,
|
|
||||||
int count,
|
|
||||||
double deviation)
|
|
||||||
{
|
|
||||||
var min = double.MaxValue;
|
|
||||||
var max = double.MinValue;
|
|
||||||
var end = begin + count;
|
|
||||||
end = end < telemetry.Length ? end : telemetry.Length;
|
|
||||||
|
|
||||||
for (var i = begin; i < end; i++)
|
|
||||||
{
|
|
||||||
var item = telemetry[i];
|
|
||||||
var itemValue = getter(item);
|
|
||||||
if (min > itemValue)
|
|
||||||
min = itemValue;
|
|
||||||
if (max < itemValue)
|
|
||||||
max = itemValue;
|
|
||||||
if (max - min > deviation)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
protected static bool IsValidByWellDepthIncreasing(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var pBegin = telemetry[begin];
|
||||||
|
var pEnd = telemetry[end];
|
||||||
|
if (pBegin.WellDepth >= pEnd.WellDepth)
|
||||||
return false;
|
return false;
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
protected static double CalcRop(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
/// Определяет наличие разброса значений в интервале большего указанного значения. По нескольким значениям из интервала.
|
{
|
||||||
/// </summary>
|
var pBegin = telemetry[begin];
|
||||||
/// <param name="telemetry"></param>
|
var pEnd = telemetry[end];
|
||||||
/// <param name="getter"></param>
|
var result = (double)(pEnd.WellDepth - pBegin.WellDepth) / (pEnd.DateTime - pBegin.DateTime).TotalHours;
|
||||||
/// <param name="begin"></param>
|
return result;
|
||||||
/// <param name="count"></param>
|
}
|
||||||
/// <param name="deviation"></param>
|
|
||||||
/// <returns></returns>
|
/// <summary>
|
||||||
protected static bool ContainsDeviationApprox(
|
/// Расчет статистики по массиву данных за интервал
|
||||||
DetectableTelemetry[] telemetry,
|
/// </summary>
|
||||||
Func<DetectableTelemetry, double> getter,
|
/// <param name="telemetry"></param>
|
||||||
int begin,
|
/// <param name="getter"></param>
|
||||||
int count,
|
/// <param name="begin"></param>
|
||||||
double deviation)
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static (double min, double max, double sum, int count) CalcStat(
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
Func<DetectableTelemetry, double> getter,
|
||||||
|
int begin,
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
var sum = 0d;
|
||||||
|
var min = double.MaxValue;
|
||||||
|
var max = double.MinValue;
|
||||||
|
var end = begin + count;
|
||||||
|
end = end < telemetry.Length ? end : telemetry.Length;
|
||||||
|
|
||||||
|
for (var i = begin; i < end; i++)
|
||||||
{
|
{
|
||||||
var min = double.MaxValue;
|
var item = telemetry[i];
|
||||||
var max = double.MinValue;
|
var itemValue = getter(item);
|
||||||
var end = begin + count;
|
if (min > itemValue)
|
||||||
end = end < telemetry.Length ? end : telemetry.Length;
|
min = itemValue;
|
||||||
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
if (max < itemValue)
|
||||||
for (var i = begin; i < end; i += step)
|
max = itemValue;
|
||||||
{
|
sum += itemValue;
|
||||||
var item = telemetry[i];
|
|
||||||
var itemValue = getter(item);
|
|
||||||
if (min > itemValue)
|
|
||||||
min = itemValue;
|
|
||||||
if (max < itemValue)
|
|
||||||
max = itemValue;
|
|
||||||
if (max - min > deviation)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static bool DeviatesFromBegin(
|
return (min, max, sum, end - begin);
|
||||||
DetectableTelemetry[] telemetry,
|
}
|
||||||
Func<DetectableTelemetry, double> getter,
|
|
||||||
int begin,
|
/// <summary>
|
||||||
int count,
|
/// Максимальное отклонение от среднего за интервал
|
||||||
double deviation)
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="getter"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static double CalcMaxDeviation(
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
Func<DetectableTelemetry, double> getter,
|
||||||
|
int begin,
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
var stat = CalcStat(telemetry, getter, begin, count);
|
||||||
|
var avg = stat.sum / stat.count;
|
||||||
|
var dev1 = avg - stat.min;
|
||||||
|
var dev2 = stat.max - avg;
|
||||||
|
var dev = dev1 > dev2 ? dev1 : dev2;
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Определяет наличие разброса значений в интервале большего указанного значения.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="getter"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <param name="deviation"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static bool ContainsDeviation(
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
Func<DetectableTelemetry, double> getter,
|
||||||
|
int begin,
|
||||||
|
int count,
|
||||||
|
double deviation)
|
||||||
|
{
|
||||||
|
var min = double.MaxValue;
|
||||||
|
var max = double.MinValue;
|
||||||
|
var end = begin + count;
|
||||||
|
end = end < telemetry.Length ? end : telemetry.Length;
|
||||||
|
|
||||||
|
for (var i = begin; i < end; i++)
|
||||||
{
|
{
|
||||||
var beginPointValue = getter(telemetry[begin]);
|
var item = telemetry[i];
|
||||||
var end = begin + count;
|
var itemValue = getter(item);
|
||||||
end = end < telemetry.Length ? end : telemetry.Length;
|
if (min > itemValue)
|
||||||
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
min = itemValue;
|
||||||
for (var i = begin; i < end; i += step)
|
if (max < itemValue)
|
||||||
{
|
max = itemValue;
|
||||||
var item = telemetry[i];
|
if (max - min > deviation)
|
||||||
var itemValue = getter(item);
|
return true;
|
||||||
if (Math.Abs(beginPointValue - itemValue) > deviation)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static bool RisesFromBegin(
|
return false;
|
||||||
DetectableTelemetry[] telemetry,
|
}
|
||||||
Func<DetectableTelemetry, double> getter,
|
|
||||||
int begin,
|
/// <summary>
|
||||||
int count,
|
/// Определяет наличие разброса значений в интервале большего указанного значения. По нескольким значениям из интервала.
|
||||||
double deviation)
|
/// </summary>
|
||||||
|
/// <param name="telemetry"></param>
|
||||||
|
/// <param name="getter"></param>
|
||||||
|
/// <param name="begin"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <param name="deviation"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static bool ContainsDeviationApprox(
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
Func<DetectableTelemetry, double> getter,
|
||||||
|
int begin,
|
||||||
|
int count,
|
||||||
|
double deviation)
|
||||||
|
{
|
||||||
|
var min = double.MaxValue;
|
||||||
|
var max = double.MinValue;
|
||||||
|
var end = begin + count;
|
||||||
|
end = end < telemetry.Length ? end : telemetry.Length;
|
||||||
|
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
||||||
|
for (var i = begin; i < end; i += step)
|
||||||
{
|
{
|
||||||
var beginPointValue = getter(telemetry[begin]);
|
var item = telemetry[i];
|
||||||
var end = begin + count;
|
var itemValue = getter(item);
|
||||||
end = end < telemetry.Length ? end : telemetry.Length;
|
if (min > itemValue)
|
||||||
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
min = itemValue;
|
||||||
for (var i = begin; i < end; i += step)
|
if (max < itemValue)
|
||||||
{
|
max = itemValue;
|
||||||
var item = telemetry[i];
|
if (max - min > deviation)
|
||||||
var itemValue = getter(item);
|
return true;
|
||||||
if (itemValue - beginPointValue > deviation)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static bool DeviatesFromBegin(
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
Func<DetectableTelemetry, double> getter,
|
||||||
|
int begin,
|
||||||
|
int count,
|
||||||
|
double deviation)
|
||||||
|
{
|
||||||
|
var beginPointValue = getter(telemetry[begin]);
|
||||||
|
var end = begin + count;
|
||||||
|
end = end < telemetry.Length ? end : telemetry.Length;
|
||||||
|
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
||||||
|
for (var i = begin; i < end; i += step)
|
||||||
|
{
|
||||||
|
var item = telemetry[i];
|
||||||
|
var itemValue = getter(item);
|
||||||
|
if (Math.Abs(beginPointValue - itemValue) > deviation)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static bool RisesFromBegin(
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
Func<DetectableTelemetry, double> getter,
|
||||||
|
int begin,
|
||||||
|
int count,
|
||||||
|
double deviation)
|
||||||
|
{
|
||||||
|
var beginPointValue = getter(telemetry[begin]);
|
||||||
|
var end = begin + count;
|
||||||
|
end = end < telemetry.Length ? end : telemetry.Length;
|
||||||
|
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
||||||
|
for (var i = begin; i < end; i += step)
|
||||||
|
{
|
||||||
|
var item = telemetry[i];
|
||||||
|
var itemValue = getter(item);
|
||||||
|
if (itemValue - beginPointValue > deviation)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
if (currentPoint.RotorSpeed <=8)
|
if (currentPoint.RotorSpeed <=8)
|
||||||
return IdReasonOfEnd_RotorSpeedIsHi;
|
return IdReasonOfEnd_RotorSpeedIsHi;
|
||||||
if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.03d)
|
if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.03d)
|
||||||
return IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo;
|
return IdReasonOfEnd_DeltaWellDepthAndBitDepthIsLo;
|
||||||
if (currentPoint.BitDepth < 150)
|
if (currentPoint.BitDepth < 150)
|
||||||
return IdReasonOfEnd_BithDepthIsLo;
|
return IdReasonOfEnd_BitDepthIsLo;
|
||||||
return IdReasonOfEnd_NotDetected;
|
return IdReasonOfEnd_NotDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,11 +48,11 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
if (currentPoint.Pressure < 10)
|
if (currentPoint.Pressure < 10)
|
||||||
return IdReasonOfEnd_PressureIsLo;
|
return IdReasonOfEnd_PressureIsLo;
|
||||||
if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.01d)
|
if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.01d)
|
||||||
return IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo;
|
return IdReasonOfEnd_DeltaWellDepthAndBitDepthIsLo;
|
||||||
if (currentPoint.RotorSpeed > 8)
|
if (currentPoint.RotorSpeed > 8)
|
||||||
return IdReasonOfEnd_RotorSpeedIsHi;
|
return IdReasonOfEnd_RotorSpeedIsHi;
|
||||||
if (currentPoint.BitDepth < 150)
|
if (currentPoint.BitDepth < 150)
|
||||||
return IdReasonOfEnd_BithDepthIsLo;
|
return IdReasonOfEnd_BitDepthIsLo;
|
||||||
return IdReasonOfEnd_NotDetected;
|
return IdReasonOfEnd_NotDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ public class DetectorSlipsTime : DetectorAbstract
|
|||||||
var deltaBitDepth = Math.Abs(currentPoint.BitDepth - prevPoint.BitDepth);
|
var deltaBitDepth = Math.Abs(currentPoint.BitDepth - prevPoint.BitDepth);
|
||||||
|
|
||||||
if (deltaBitDepth > 0.001d && currentPoint.AxialLoad < currentPoint.HookWeight)
|
if (deltaBitDepth > 0.001d && currentPoint.AxialLoad < currentPoint.HookWeight)
|
||||||
return IdReasonOfEnd_ChangeBithDepthAndAxiloadLessHookWeight;
|
return IdReasonOfEnd_ChangeBitDepthAndAxiLoadLessHookWeight;
|
||||||
|
|
||||||
return IdReasonOfEnd_NotDetected;
|
return IdReasonOfEnd_NotDetected;
|
||||||
}
|
}
|
||||||
|
@ -1,54 +1,91 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.SAUB;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudInfrastructure.Background;
|
using AsbCloudInfrastructure.Background;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
||||||
|
|
||||||
public class WorkOperationDetection: Work
|
public class WorkOperationDetection : Work
|
||||||
{
|
{
|
||||||
|
private static readonly IDictionary<int, DateTimeOffset> CacheOfStartDatesByTelemetryId = new Dictionary<int, DateTimeOffset>();
|
||||||
|
|
||||||
public WorkOperationDetection()
|
public WorkOperationDetection()
|
||||||
:base("Operation detection")
|
: base("Operation detection")
|
||||||
{
|
{
|
||||||
Timeout = TimeSpan.FromMinutes(20);
|
Timeout = TimeSpan.FromMinutes(20);
|
||||||
OnErrorAsync = (id, exception, token) =>
|
OnErrorAsync = (id, exception, _) =>
|
||||||
{
|
{
|
||||||
var text = $"work {id}, when {CurrentState?.State}, throw error:{exception.Message}";
|
var text = $"work {id}, when {CurrentState?.State}, throw error:{exception.Message}";
|
||||||
Trace.TraceWarning(text);
|
Trace.TraceWarning(text);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task Action(string id, IServiceProvider services, Action<string, double?> onProgressCallback, CancellationToken token)
|
protected override async Task Action(string id,
|
||||||
{
|
IServiceProvider services,
|
||||||
var telemetryRepository = services.GetRequiredService<ICrudRepository<TelemetryDto>>();
|
Action<string, double?> onProgressCallback,
|
||||||
var detectedOperationRepository = services.GetRequiredService<IDetectedOperationRepository>();
|
CancellationToken token)
|
||||||
var detectedOperationService = services.GetRequiredService<IDetectedOperationService>();
|
{
|
||||||
|
var telemetryRepository = services.GetRequiredService<ICrudRepository<TelemetryDto>>();
|
||||||
|
var detectedOperationRepository = services.GetRequiredService<IDetectedOperationRepository>();
|
||||||
|
var detectedOperationService = services.GetRequiredService<IDetectedOperationService>();
|
||||||
|
var telemetryDataCache = services.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
||||||
|
|
||||||
var telemetryIds = (await telemetryRepository.GetAllAsync(token))
|
var idsTelemetry = (await telemetryRepository.GetAllAsync(token))
|
||||||
.Select(t => t.Id)
|
.Select(t => t.Id)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
var lastDetectedDates = await detectedOperationRepository.GetLastDetectedDatesAsync(token);
|
var lastDetectedOperations = await detectedOperationRepository.GetLastDetectedOperationsAsync(token);
|
||||||
|
|
||||||
for (var i = 0; i < telemetryIds.Length; i++)
|
for (int i = 0; i < idsTelemetry.Length; i++)
|
||||||
{
|
{
|
||||||
var telemetryId = telemetryIds[i];
|
var idTelemetry = idsTelemetry[i];
|
||||||
|
|
||||||
var beginDate = lastDetectedDates.TryGetValue(telemetryId, out var date) ? date : (DateTimeOffset?)null;
|
var telemetryDateRange = telemetryDataCache.GetOrDefaultWellDataDateRange(idTelemetry);
|
||||||
|
|
||||||
onProgressCallback($"Start detecting telemetry: {telemetryId} from {beginDate}", i / telemetryIds.Length);
|
if(telemetryDateRange == null)
|
||||||
var detectedOperations = await detectedOperationService.DetectOperationsAsync(telemetryId, beginDate, token);
|
continue;
|
||||||
|
|
||||||
if (detectedOperations.Any())
|
var dateBegin = telemetryDateRange.From;
|
||||||
await detectedOperationRepository.InsertRangeAsync(detectedOperations, token);
|
var dateEnd = telemetryDateRange.To;
|
||||||
}
|
|
||||||
}
|
if (lastDetectedOperations.TryGetValue(idTelemetry, out var lastDetectedOperation))
|
||||||
|
dateBegin = lastDetectedOperation.DateEnd;
|
||||||
|
|
||||||
|
if (CacheOfStartDatesByTelemetryId.TryGetValue(idTelemetry, out var dateBeginFromCache))
|
||||||
|
dateBegin = dateBeginFromCache;
|
||||||
|
|
||||||
|
onProgressCallback.Invoke($"Start detecting telemetry: {idTelemetry} from {dateBegin}", i / idsTelemetry.Length);
|
||||||
|
|
||||||
|
const int pointsCount = 4 * 86_400;
|
||||||
|
|
||||||
|
while (dateBegin < dateEnd)
|
||||||
|
{
|
||||||
|
var request = new TelemetryDataRequest
|
||||||
|
{
|
||||||
|
GeDate = dateBegin,
|
||||||
|
Take = pointsCount,
|
||||||
|
Order = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var detectedOperations =
|
||||||
|
await detectedOperationService.DetectOperationsAsync(idTelemetry, request, lastDetectedOperation, token);
|
||||||
|
|
||||||
|
dateBegin = detectedOperations.LastDate;
|
||||||
|
|
||||||
|
CacheOfStartDatesByTelemetryId[idTelemetry] = dateBegin;
|
||||||
|
|
||||||
|
await detectedOperationRepository.InsertRangeAsync(detectedOperations.Items, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -96,7 +96,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
var allUsers = await memoryCache.GetOrCreateBasicAsync(db.Set<TelemetryUser>(), token);
|
var allUsers = await memoryCache.GetOrCreateBasicAsync(db.Set<TelemetryUser>(), token);
|
||||||
var users = allUsers.Where(u => u.IdTelemetry == telemetry.Id);
|
var users = allUsers.Where(u => u.IdTelemetry == telemetry.Id);
|
||||||
|
|
||||||
var eventsDict = events.ToDictionary(x=>x.IdEvent, x => x);
|
var eventsDict = events.ToDictionary(x => x.IdEvent, x => x);
|
||||||
var usersDict = users.ToDictionary(x => x.IdUser, x => x);
|
var usersDict = users.ToDictionary(x => x.IdUser, x => x);
|
||||||
|
|
||||||
var messagesDtoList = new List<MessageDto>();
|
var messagesDtoList = new List<MessageDto>();
|
||||||
@ -154,6 +154,33 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
|
|
||||||
return db.SaveChangesAsync(token);
|
return db.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IQueryable<TelemetryMessage> BuildQuery(TelemetryPartDeleteRequest request)
|
||||||
|
{
|
||||||
|
var query = db.Set<TelemetryMessage>()
|
||||||
|
.Where(o => o.IdTelemetry == request.IdTelemetry);
|
||||||
|
|
||||||
|
if (request.GeDate is not null)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateTime <= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.LeDate is not null)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateTime >= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = BuildQuery(request);
|
||||||
|
db.Set<TelemetryMessage>().RemoveRange(query);
|
||||||
|
return await db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Exceptions;
|
using AsbCloudApp.Exceptions;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb;
|
using AsbCloudDb;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
@ -11,276 +12,299 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Requests;
|
|
||||||
using Mapster;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.SAUB
|
namespace AsbCloudInfrastructure.Services.SAUB;
|
||||||
|
|
||||||
|
public abstract class TelemetryDataBaseService<TDto, TEntity> : ITelemetryDataService<TDto>
|
||||||
|
where TDto : AsbCloudApp.Data.ITelemetryData
|
||||||
|
where TEntity : class, AsbCloudDb.Model.ITelemetryData
|
||||||
{
|
{
|
||||||
public abstract class TelemetryDataBaseService<TDto, TEntity> : ITelemetryDataService<TDto>
|
protected readonly IAsbCloudDbContext db;
|
||||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
protected readonly ITelemetryService telemetryService;
|
||||||
where TEntity : class, AsbCloudDb.Model.ITelemetryData
|
protected readonly ITelemetryDataCache<TDto> telemetryDataCache;
|
||||||
{
|
|
||||||
protected readonly IAsbCloudDbContext db;
|
|
||||||
protected readonly ITelemetryService telemetryService;
|
|
||||||
protected readonly ITelemetryDataCache<TDto> telemetryDataCache;
|
|
||||||
|
|
||||||
protected TelemetryDataBaseService(
|
protected TelemetryDataBaseService(
|
||||||
IAsbCloudDbContext db,
|
IAsbCloudDbContext db,
|
||||||
ITelemetryService telemetryService,
|
ITelemetryService telemetryService,
|
||||||
ITelemetryDataCache<TDto> telemetryDataCache)
|
ITelemetryDataCache<TDto> telemetryDataCache)
|
||||||
|
{
|
||||||
|
this.db = db;
|
||||||
|
this.telemetryService = telemetryService;
|
||||||
|
this.telemetryDataCache = telemetryDataCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public virtual async Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if (dtos == default || !dtos.Any())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var dtosList = dtos.OrderBy(d => d.DateTime).ToList();
|
||||||
|
|
||||||
|
var dtoMinDate = dtosList.First().DateTime;
|
||||||
|
var dtoMaxDate = dtosList.Last().DateTime;
|
||||||
|
|
||||||
|
if (dtosList.Count > 1)
|
||||||
{
|
{
|
||||||
this.db = db;
|
var duplicates = new List<TDto>(8);
|
||||||
this.telemetryService = telemetryService;
|
for (int i = 1; i < dtosList.Count; i++)
|
||||||
this.telemetryDataCache = telemetryDataCache;
|
if (dtosList[i].DateTime - dtosList[i - 1].DateTime < TimeSpan.FromMilliseconds(100))
|
||||||
|
duplicates.Add(dtosList[i - 1]);
|
||||||
|
foreach (var duplicate in duplicates)
|
||||||
|
dtosList.Remove(duplicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid);
|
||||||
public virtual async Task<int> UpdateDataAsync(string uid, IEnumerable<TDto> dtos, CancellationToken token = default)
|
var timeZone = telemetryService.GetTimezone(telemetry.Id);
|
||||||
|
|
||||||
|
telemetryDataCache.AddRange(telemetry.Id, dtos);
|
||||||
|
|
||||||
|
var entities = dtosList.Select(dto =>
|
||||||
{
|
{
|
||||||
if (dtos == default || !dtos.Any())
|
var entity = Convert(dto, timeZone.Hours);
|
||||||
return 0;
|
entity.IdTelemetry = telemetry.Id;
|
||||||
|
return entity;
|
||||||
|
});
|
||||||
|
|
||||||
var dtosList = dtos.OrderBy(d => d.DateTime).ToList();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
var dbSet = db.Set<TEntity>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await db.Database.ExecInsertOrUpdateAsync(dbSet, entities, token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
stopwatch.Stop();
|
||||||
|
Trace.WriteLine($"Fail to save data telemetry " +
|
||||||
|
$"uid: {uid}, " +
|
||||||
|
$"idTelemetry {telemetry.Id}, " +
|
||||||
|
$"count: {entities.Count()}, " +
|
||||||
|
$"dataDate: {entities.FirstOrDefault()?.DateTime}, " +
|
||||||
|
$"dbSaveDurationTime:{stopwatch.ElapsedMilliseconds}ms. " +
|
||||||
|
$"Message: {ex.Message}");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var dtoMinDate = dtosList.First().DateTime;
|
/// <inheritdoc/>
|
||||||
var dtoMaxDate = dtosList.Last().DateTime;
|
public virtual async Task<IEnumerable<TDto>> GetByWellAsync(int idWell,
|
||||||
|
DateTime dateBegin = default, double intervalSec = 600d,
|
||||||
|
int approxPointsCount = 1024, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
|
||||||
|
if (telemetry is null)
|
||||||
|
return Enumerable.Empty<TDto>();
|
||||||
|
|
||||||
if (dtosList.Count > 1)
|
var timezone = telemetryService.GetTimezone(telemetry.Id);
|
||||||
|
|
||||||
|
var filterByDateEnd = dateBegin != default;
|
||||||
|
DateTimeOffset dateBeginUtc;
|
||||||
|
if (dateBegin == default)
|
||||||
|
{
|
||||||
|
var dateRange = telemetryDataCache.GetOrDefaultWellDataDateRange(telemetry.Id);
|
||||||
|
dateBeginUtc = (dateRange?.To.ToUniversalTime() ?? DateTimeOffset.UtcNow)
|
||||||
|
.AddSeconds(-intervalSec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dateBeginUtc = dateBegin.ToUtcDateTimeOffset(timezone.Hours);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cacheData = telemetryDataCache.GetOrDefault(telemetry.Id, dateBeginUtc.ToRemoteDateTime(timezone.Hours), intervalSec, approxPointsCount);
|
||||||
|
if (cacheData is not null)
|
||||||
|
return cacheData;
|
||||||
|
|
||||||
|
var dateEnd = dateBeginUtc.AddSeconds(intervalSec);
|
||||||
|
var dbSet = db.Set<TEntity>();
|
||||||
|
|
||||||
|
var query = dbSet
|
||||||
|
.Where(d => d.IdTelemetry == telemetry.Id
|
||||||
|
&& d.DateTime >= dateBeginUtc);
|
||||||
|
|
||||||
|
if (filterByDateEnd)
|
||||||
|
query = query.Where(d => d.DateTime <= dateEnd);
|
||||||
|
|
||||||
|
var fullDataCount = await query.CountAsync(token)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (fullDataCount == 0)
|
||||||
|
return Enumerable.Empty<TDto>();
|
||||||
|
|
||||||
|
if (fullDataCount > 1.75 * approxPointsCount)
|
||||||
|
{
|
||||||
|
var m = (int)Math.Round(1d * fullDataCount / approxPointsCount);
|
||||||
|
if (m > 1)
|
||||||
|
query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var entities = await query
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
|
var dtos = entities.Select(e => Convert(e, timezone.Hours));
|
||||||
|
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public virtual async Task<IEnumerable<TDto>> GetByWellAsync(int idWell, TelemetryDataRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
|
||||||
|
if (telemetry is null)
|
||||||
|
return Enumerable.Empty<TDto>();
|
||||||
|
|
||||||
|
return await GetByTelemetryAsync(telemetry.Id, request, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TDto>> GetByTelemetryAsync(int idTelemetry, TelemetryDataRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var timeZone = telemetryService.GetTimezone(idTelemetry);
|
||||||
|
|
||||||
|
var cache = telemetryDataCache.GetOrDefault(idTelemetry, request);
|
||||||
|
|
||||||
|
if (cache is not null)
|
||||||
|
return cache;
|
||||||
|
|
||||||
|
var query = BuildQuery(idTelemetry, request);
|
||||||
|
|
||||||
|
var entities = await query
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
|
var dtos = entities.Select(e => Convert(e, timeZone.Hours));
|
||||||
|
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQueryable<TEntity> BuildQuery(int idTelemetry, TelemetryDataRequest request)
|
||||||
|
{
|
||||||
|
var dbSet = db.Set<TEntity>();
|
||||||
|
|
||||||
|
var query = dbSet
|
||||||
|
.Where(d => d.IdTelemetry == idTelemetry);
|
||||||
|
|
||||||
|
if (request.GeDate.HasValue)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.UtcDateTime;
|
||||||
|
query = query.Where(d => d.DateTime >= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.LeDate.HasValue)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.UtcDateTime;
|
||||||
|
query = query.Where(d => d.DateTime <= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Divider > 1)
|
||||||
|
query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % request.Divider == 0);
|
||||||
|
|
||||||
|
switch (request.Order)
|
||||||
|
{
|
||||||
|
case 1:// Поздние вперед
|
||||||
|
query = query
|
||||||
|
.OrderByDescending(d => d.DateTime)
|
||||||
|
.Skip(request.Skip)
|
||||||
|
.Take(request.Take)
|
||||||
|
.OrderBy(d => d.DateTime);
|
||||||
|
break;
|
||||||
|
default:// Ранние вперед
|
||||||
|
query = query
|
||||||
|
.OrderBy(d => d.DateTime)
|
||||||
|
.Skip(request.Skip)
|
||||||
|
.Take(request.Take);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQueryable<TEntity> BuildQuery(TelemetryPartDeleteRequest request)
|
||||||
|
{
|
||||||
|
var query = db.Set<TEntity>()
|
||||||
|
.Where(o => o.IdTelemetry == request.IdTelemetry);
|
||||||
|
|
||||||
|
if (request.GeDate is not null)
|
||||||
|
{
|
||||||
|
var geDate = request.GeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateTime <= geDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.LeDate is not null)
|
||||||
|
{
|
||||||
|
var leDate = request.LeDate.Value.ToUniversalTime();
|
||||||
|
query = query.Where(o => o.DateTime >= leDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<DatesRangeDto?> GetRangeAsync(int idWell, DateTimeOffset geDate, DateTimeOffset? leDate, CancellationToken token)
|
||||||
|
{
|
||||||
|
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell)
|
||||||
|
?? throw new ArgumentInvalidException(nameof(idWell), $"По скважине id:{idWell} нет телеметрии");
|
||||||
|
|
||||||
|
if ((DateTimeOffset.UtcNow - geDate) < TimeSpan.FromHours(12))
|
||||||
|
{
|
||||||
|
// пробуем обойтись кэшем
|
||||||
|
var cachedRange = telemetryDataCache.GetOrDefaultCachedDataDateRange(telemetry.Id);
|
||||||
|
if (cachedRange is not null)
|
||||||
{
|
{
|
||||||
var duplicates = new List<TDto>(8);
|
var datesRange = new DatesRangeDto { From = cachedRange.From, To = cachedRange.To };
|
||||||
for (int i = 1; i < dtosList.Count; i++)
|
if (geDate >= cachedRange.From)
|
||||||
if (dtosList[i].DateTime - dtosList[i - 1].DateTime < TimeSpan.FromMilliseconds(100))
|
datesRange.From = geDate.ToOffset(cachedRange.From.Offset);
|
||||||
duplicates.Add(dtosList[i - 1]);
|
|
||||||
foreach (var duplicate in duplicates)
|
if (leDate.HasValue && leDate <= cachedRange.To)
|
||||||
dtosList.Remove(duplicate);
|
datesRange.To = leDate.Value.ToOffset(cachedRange.To.Offset);
|
||||||
|
|
||||||
|
return datesRange;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid);
|
var query = db.Set<TEntity>()
|
||||||
var timezone = telemetryService.GetTimezone(telemetry.Id);
|
.Where(entity => entity.IdTelemetry == telemetry.Id)
|
||||||
|
.Where(entity => entity.DateTime >= geDate.ToUniversalTime());
|
||||||
|
|
||||||
telemetryDataCache.AddRange(telemetry.Id, dtos);
|
if (leDate.HasValue)
|
||||||
|
query = query.Where(entity => entity.DateTime <= leDate.Value.ToUniversalTime());
|
||||||
|
|
||||||
var entities = dtosList.Select(dto =>
|
var groupQuery = query
|
||||||
|
.GroupBy(entity => entity.IdTelemetry)
|
||||||
|
.Select(group => new
|
||||||
{
|
{
|
||||||
var entity = Convert(dto, timezone.Hours);
|
MinDate = group.Min(entity => entity.DateTime),
|
||||||
entity.IdTelemetry = telemetry.Id;
|
MaxDate = group.Max(entity => entity.DateTime),
|
||||||
return entity;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var stopwatch = Stopwatch.StartNew();
|
var result = await groupQuery.FirstOrDefaultAsync(token);
|
||||||
var dbSet = db.Set<TEntity>();
|
if (result is null)
|
||||||
try
|
return null;
|
||||||
{
|
|
||||||
return await db.Database.ExecInsertOrUpdateAsync(dbSet, entities, token).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
stopwatch.Stop();
|
|
||||||
Trace.WriteLine($"Fail to save data telemetry " +
|
|
||||||
$"uid: {uid}, " +
|
|
||||||
$"idTelemetry {telemetry.Id}, " +
|
|
||||||
$"count: {entities.Count()}, " +
|
|
||||||
$"dataDate: {entities.FirstOrDefault()?.DateTime}, " +
|
|
||||||
$"dbSaveDurationTime:{stopwatch.ElapsedMilliseconds}ms. " +
|
|
||||||
$"Message: {ex.Message}");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
var range = new DatesRangeDto
|
||||||
public virtual async Task<IEnumerable<TDto>> GetByWellAsync(int idWell,
|
|
||||||
DateTime dateBegin = default, double intervalSec = 600d,
|
|
||||||
int approxPointsCount = 1024, CancellationToken token = default)
|
|
||||||
{
|
{
|
||||||
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
|
From = result.MinDate.ToOffset(telemetry.TimeZone!.Offset),
|
||||||
if (telemetry is null)
|
To = result.MaxDate.ToOffset(telemetry.TimeZone!.Offset),
|
||||||
return Enumerable.Empty<TDto>();
|
};
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
var timezone = telemetryService.GetTimezone(telemetry.Id);
|
public DatesRangeDto? GetRange(int idWell)
|
||||||
|
{
|
||||||
|
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
|
||||||
|
if (telemetry is null)
|
||||||
|
return default;
|
||||||
|
|
||||||
var filterByDateEnd = dateBegin != default;
|
return telemetryDataCache.GetOrDefaultWellDataDateRange(telemetry.Id);
|
||||||
DateTimeOffset dateBeginUtc;
|
}
|
||||||
if (dateBegin == default)
|
|
||||||
{
|
|
||||||
var dateRange = telemetryDataCache.GetOrDefaultWellDataDateRange(telemetry.Id);
|
|
||||||
dateBeginUtc = (dateRange?.To.ToUniversalTime() ?? DateTimeOffset.UtcNow)
|
|
||||||
.AddSeconds(-intervalSec);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dateBeginUtc = dateBegin.ToUtcDateTimeOffset(timezone.Hours);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cacheData = telemetryDataCache.GetOrDefault(telemetry.Id, dateBeginUtc.ToRemoteDateTime(timezone.Hours), intervalSec, approxPointsCount);
|
protected abstract TDto Convert(TEntity src, double timeZoneOffset);
|
||||||
if (cacheData is not null)
|
|
||||||
return cacheData;
|
|
||||||
|
|
||||||
var dateEnd = dateBeginUtc.AddSeconds(intervalSec);
|
protected abstract TEntity Convert(TDto src, double timeZoneOffset);
|
||||||
var dbSet = db.Set<TEntity>();
|
|
||||||
|
|
||||||
var query = dbSet
|
|
||||||
.Where(d => d.IdTelemetry == telemetry.Id
|
|
||||||
&& d.DateTime >= dateBeginUtc);
|
|
||||||
|
|
||||||
if (filterByDateEnd)
|
|
||||||
query = query.Where(d => d.DateTime <= dateEnd);
|
|
||||||
|
|
||||||
var fullDataCount = await query.CountAsync(token)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (fullDataCount == 0)
|
|
||||||
return Enumerable.Empty<TDto>();
|
|
||||||
|
|
||||||
if (fullDataCount > 1.75 * approxPointsCount)
|
|
||||||
{
|
|
||||||
var m = (int)Math.Round(1d * fullDataCount / approxPointsCount);
|
|
||||||
if (m > 1)
|
|
||||||
query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
var entities = await query
|
|
||||||
.AsNoTracking()
|
|
||||||
.ToArrayAsync(token);
|
|
||||||
|
|
||||||
var dtos = entities.Select(e => Convert(e, timezone.Hours));
|
|
||||||
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public virtual async Task<IEnumerable<TDto>> GetByWellAsync(int idWell, TelemetryDataRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
|
|
||||||
if (telemetry is null)
|
|
||||||
return Enumerable.Empty<TDto>();
|
|
||||||
|
|
||||||
return await GetByTelemetryAsync(telemetry.Id, request, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<TDto>> GetByTelemetryAsync(int idTelemetry, TelemetryDataRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
var timezone = telemetryService.GetTimezone(idTelemetry);
|
|
||||||
|
|
||||||
var cache = telemetryDataCache.GetOrDefault(idTelemetry, request);
|
|
||||||
|
|
||||||
if(cache is not null)
|
|
||||||
return cache;
|
|
||||||
|
|
||||||
var query = BuildQuery(idTelemetry, request);
|
|
||||||
|
|
||||||
var entities = await query
|
|
||||||
.AsNoTracking()
|
|
||||||
.ToArrayAsync(token);
|
|
||||||
|
|
||||||
var dtos = entities.Select(e => Convert(e, timezone.Hours));
|
|
||||||
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQueryable<TEntity> BuildQuery(int idTelemetry, TelemetryDataRequest request)
|
|
||||||
{
|
|
||||||
var dbSet = db.Set<TEntity>();
|
|
||||||
|
|
||||||
var query = dbSet
|
|
||||||
.Where(d => d.IdTelemetry == idTelemetry);
|
|
||||||
|
|
||||||
if (request.GeDate.HasValue)
|
|
||||||
{
|
|
||||||
var geDate = request.GeDate.Value.UtcDateTime;
|
|
||||||
query = query.Where(d => d.DateTime >= geDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.LeDate.HasValue)
|
|
||||||
{
|
|
||||||
var leDate = request.LeDate.Value.UtcDateTime;
|
|
||||||
query = query.Where(d => d.DateTime <= leDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.Divider > 1)
|
|
||||||
query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % request.Divider == 0);
|
|
||||||
|
|
||||||
switch (request.Order)
|
|
||||||
{
|
|
||||||
case 1:// Поздние вперед
|
|
||||||
query = query
|
|
||||||
.OrderByDescending(d => d.DateTime)
|
|
||||||
.Skip(request.Skip)
|
|
||||||
.Take(request.Take)
|
|
||||||
.OrderBy(d => d.DateTime);
|
|
||||||
break;
|
|
||||||
default:// Ранние вперед
|
|
||||||
query = query
|
|
||||||
.OrderBy(d => d.DateTime)
|
|
||||||
.Skip(request.Skip)
|
|
||||||
.Take(request.Take);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<DatesRangeDto?> GetRangeAsync(int idWell, DateTimeOffset geDate, DateTimeOffset? leDate, CancellationToken token)
|
|
||||||
{
|
|
||||||
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell)
|
|
||||||
?? throw new ArgumentInvalidException(nameof(idWell), $"По скважине id:{idWell} нет телеметрии");
|
|
||||||
|
|
||||||
if ((DateTimeOffset.UtcNow - geDate) < TimeSpan.FromHours(12))
|
|
||||||
{
|
|
||||||
// пробуем обойтись кэшем
|
|
||||||
var cachedRange = telemetryDataCache.GetOrDefaultCachedDataDateRange(telemetry.Id);
|
|
||||||
if (cachedRange is not null)
|
|
||||||
{
|
|
||||||
var datesRange = new DatesRangeDto {From = cachedRange.From, To = cachedRange.To };
|
|
||||||
if (geDate >= cachedRange.From)
|
|
||||||
datesRange.From = geDate.ToOffset(cachedRange.From.Offset);
|
|
||||||
|
|
||||||
if (leDate.HasValue && leDate <= cachedRange.To)
|
|
||||||
datesRange.To = leDate.Value.ToOffset(cachedRange.To.Offset);
|
|
||||||
|
|
||||||
return datesRange;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var query = db.Set<TEntity>()
|
|
||||||
.Where(entity => entity.IdTelemetry == telemetry.Id)
|
|
||||||
.Where(entity => entity.DateTime >= geDate.ToUniversalTime());
|
|
||||||
|
|
||||||
if(leDate.HasValue)
|
|
||||||
query = query.Where(entity => entity.DateTime <= leDate.Value.ToUniversalTime());
|
|
||||||
|
|
||||||
var groupQuery = query
|
|
||||||
.GroupBy(entity => entity.IdTelemetry)
|
|
||||||
.Select(group => new
|
|
||||||
{
|
|
||||||
MinDate = group.Min(entity => entity.DateTime),
|
|
||||||
MaxDate = group.Max(entity => entity.DateTime),
|
|
||||||
});
|
|
||||||
|
|
||||||
var result = await groupQuery.FirstOrDefaultAsync(token);
|
|
||||||
if (result is null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var range = new DatesRangeDto
|
|
||||||
{
|
|
||||||
From = result.MinDate.ToOffset(telemetry.TimeZone!.Offset),
|
|
||||||
To = result.MaxDate.ToOffset(telemetry.TimeZone!.Offset),
|
|
||||||
};
|
|
||||||
return range;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DatesRangeDto? GetRange(int idWell)
|
|
||||||
{
|
|
||||||
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
|
|
||||||
if (telemetry is null)
|
|
||||||
return default;
|
|
||||||
|
|
||||||
return telemetryDataCache.GetOrDefaultWellDataDateRange(telemetry.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract TDto Convert(TEntity src, double timezoneOffset);
|
|
||||||
|
|
||||||
protected abstract TEntity Convert(TDto src, double timezoneOffset);
|
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = BuildQuery(request);
|
||||||
|
db.Set<TEntity>().RemoveRange(query);
|
||||||
|
return await db.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,8 +153,8 @@ public class TelemetryDataCache<TDto> : ITelemetryDataCache<TDto> where TDto : A
|
|||||||
if (cacheItem.LastData.Count == 0)
|
if (cacheItem.LastData.Count == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var to = FromDate(cacheItem.FirstByDate.DateTime, cacheItem.TimezoneOffset);
|
var to = FromDate(cacheItem.LastData[^1].DateTime, cacheItem.TimezoneOffset);
|
||||||
var from = FromDate(cacheItem.LastData[^1].DateTime, cacheItem.TimezoneOffset);
|
var from = FromDate(cacheItem.FirstByDate.DateTime, cacheItem.TimezoneOffset);
|
||||||
|
|
||||||
return new DatesRangeDto { From = from, To = to };
|
return new DatesRangeDto { From = from, To = to };
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
using AsbCloudApp.Data.SAUB;
|
||||||
|
using AsbCloudApp.Data.WITS;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.SAUB
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Сервис по работе с данными телеметрии
|
||||||
|
/// </summary>
|
||||||
|
public class TelemetryDataEditorService : ITelemetryDataEditorService
|
||||||
|
{
|
||||||
|
private readonly ITelemetryDataEditorService[] repositories;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataSaubService"></param>
|
||||||
|
/// <param name="dataSpinService"></param>
|
||||||
|
/// <param name="dataSaubStatRepository"></param>
|
||||||
|
/// <param name="messageService"></param>
|
||||||
|
/// <param name="drillTestRepository"></param>
|
||||||
|
/// <param name="limitingParameterRepository"></param>
|
||||||
|
/// <param name="detectedOperationRepository"></param>
|
||||||
|
/// <param name="witsRecord1Repository"></param>
|
||||||
|
/// <param name="witsRecord7Repository"></param>
|
||||||
|
/// <param name="witsRecord8Repository"></param>
|
||||||
|
/// <param name="witsRecord50Repository"></param>
|
||||||
|
/// <param name="witsRecord60Repository"></param>
|
||||||
|
/// <param name="witsRecord61Repository"></param>
|
||||||
|
/// <param name="gtrRepository"></param>
|
||||||
|
public TelemetryDataEditorService(
|
||||||
|
ITelemetryDataSaubService dataSaubService,
|
||||||
|
ITelemetryDataService<TelemetryDataSpinDto> dataSpinService,
|
||||||
|
IDataSaubStatRepository dataSaubStatRepository,
|
||||||
|
IMessageService messageService,
|
||||||
|
IDrillTestRepository drillTestRepository,
|
||||||
|
ILimitingParameterRepository limitingParameterRepository,
|
||||||
|
IDetectedOperationRepository detectedOperationRepository,
|
||||||
|
IWitsRecordRepository<Record1Dto> witsRecord1Repository,
|
||||||
|
IWitsRecordRepository<Record7Dto> witsRecord7Repository,
|
||||||
|
IWitsRecordRepository<Record8Dto> witsRecord8Repository,
|
||||||
|
IWitsRecordRepository<Record50Dto> witsRecord50Repository,
|
||||||
|
IWitsRecordRepository<Record60Dto> witsRecord60Repository,
|
||||||
|
IWitsRecordRepository<Record61Dto> witsRecord61Repository,
|
||||||
|
IGtrRepository gtrRepository
|
||||||
|
)
|
||||||
|
{
|
||||||
|
repositories =
|
||||||
|
[
|
||||||
|
dataSaubService,
|
||||||
|
dataSpinService,
|
||||||
|
dataSaubStatRepository,
|
||||||
|
messageService,
|
||||||
|
drillTestRepository,
|
||||||
|
limitingParameterRepository,
|
||||||
|
detectedOperationRepository,
|
||||||
|
witsRecord1Repository,
|
||||||
|
witsRecord7Repository,
|
||||||
|
witsRecord8Repository,
|
||||||
|
witsRecord50Repository,
|
||||||
|
witsRecord60Repository,
|
||||||
|
witsRecord61Repository,
|
||||||
|
gtrRepository,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = 0;
|
||||||
|
foreach (var repository in repositories)
|
||||||
|
{
|
||||||
|
result += await repository.DeleteAsync(request, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,8 @@ using System.Linq;
|
|||||||
using System.Text.Csv;
|
using System.Text.Csv;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.SAUB;
|
namespace AsbCloudInfrastructure.Services.SAUB;
|
||||||
|
|
||||||
|
@ -90,6 +90,26 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
return await db.SaveChangesAsync(token);
|
return await db.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> CopyAsync(int idWell, int idWellTarget, IEnumerable<int> contactIds, CancellationToken token)
|
||||||
|
{
|
||||||
|
var contacts = await GetContacts(idWell, contactIds, token);
|
||||||
|
if (!contacts.Any())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var newContacts = contacts.Select(contact =>
|
||||||
|
{
|
||||||
|
var newContact = contact.Adapt<Contact>();
|
||||||
|
newContact.IdWell = idWellTarget;
|
||||||
|
newContact.Id = default;
|
||||||
|
|
||||||
|
return newContact;
|
||||||
|
});
|
||||||
|
|
||||||
|
db.Contacts.AddRange(newContacts);
|
||||||
|
|
||||||
|
return await db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<Contact?> GetContact(int idWell, int idContact, CancellationToken token)
|
private async Task<Contact?> GetContact(int idWell, int idContact, CancellationToken token)
|
||||||
{
|
{
|
||||||
var contact = await db.Contacts
|
var contact = await db.Contacts
|
||||||
@ -100,5 +120,16 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
|
|
||||||
return contact;
|
return contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Contact[]> GetContacts(int idWell, IEnumerable<int> contactIds, CancellationToken token)
|
||||||
|
{
|
||||||
|
var contacts = await db.Contacts
|
||||||
|
.Where(c => c.IdWell == idWell)
|
||||||
|
.Where(c => contactIds.Contains(c.Id))
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
|
return contacts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -16,12 +19,15 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
public class AdminTelemetryController : CrudController<TelemetryDto, ICrudRepository<TelemetryDto>>
|
public class AdminTelemetryController : CrudController<TelemetryDto, ICrudRepository<TelemetryDto>>
|
||||||
{
|
{
|
||||||
private readonly ITelemetryService telemetryService;
|
private readonly ITelemetryService telemetryService;
|
||||||
|
private readonly ITelemetryDataEditorService telemetryEditorService;
|
||||||
|
|
||||||
public AdminTelemetryController(ICrudRepository<TelemetryDto> service,
|
public AdminTelemetryController(ICrudRepository<TelemetryDto> service,
|
||||||
ITelemetryService telemetryService)
|
ITelemetryService telemetryService,
|
||||||
|
ITelemetryDataEditorService telemetryEditorService)
|
||||||
: base(service)
|
: base(service)
|
||||||
{
|
{
|
||||||
this.telemetryService = telemetryService;
|
this.telemetryService = telemetryService;
|
||||||
|
this.telemetryEditorService = telemetryEditorService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -36,5 +42,22 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
return Ok(count);
|
return Ok(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Удаление куска телеметрии по запросу
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">запрос</param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpDelete("part")]
|
||||||
|
[Permission]
|
||||||
|
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||||
|
public async Task<IActionResult> DeleteAsync([FromQuery] TelemetryPartDeleteRequest request,CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await telemetryEditorService.DeleteAsync(request, token);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить список автоопределенных операций для редактирования
|
/// Получить список авто определенных операций для редактирования
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell"></param>
|
/// <param name="idWell"></param>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
@ -136,7 +136,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить статистику по автоопределенным операциям
|
/// Получить статистику по авто определенным операциям
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell"></param>
|
/// <param name="idWell"></param>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
|
@ -139,6 +139,34 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Скопировать контакты в другую скважину
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell">ключ скважины, откуда копировать контакты</param>
|
||||||
|
/// <param name="idWellTarget">ключ скважины, куда копировать контакты</param>
|
||||||
|
/// <param name="contactIds"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("copy/{idWellTarget}")]
|
||||||
|
[Permission]
|
||||||
|
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> CopyAsync(
|
||||||
|
int idWell,
|
||||||
|
int idWellTarget,
|
||||||
|
[FromBody] IEnumerable<int> contactIds,
|
||||||
|
CancellationToken token)
|
||||||
|
{
|
||||||
|
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
|
||||||
|
return Forbid();
|
||||||
|
|
||||||
|
if (!await CanUserAccessToWellAsync(idWellTarget, token).ConfigureAwait(false))
|
||||||
|
return Forbid();
|
||||||
|
|
||||||
|
var result = await wellContactsRepository.CopyAsync(idWell, idWellTarget, contactIds, token);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token)
|
private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
int? idCompany = User.GetCompanyId();
|
int? idCompany = User.GetCompanyId();
|
||||||
|
Loading…
Reference in New Issue
Block a user