DetectedOperationController переделаны route. Добавлено 2 детектора

This commit is contained in:
ngfrolov 2022-06-17 17:21:14 +05:00
parent 6d908478dd
commit 5cc3f50163
8 changed files with 108 additions and 64 deletions

View File

@ -1,5 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.ComponentModel.DataAnnotations;
namespace AsbCloudApp.Requests namespace AsbCloudApp.Requests
{ {
@ -9,9 +9,16 @@ namespace AsbCloudApp.Requests
public class DetectedOperationRequest : RequestBase public class DetectedOperationRequest : RequestBase
{ {
/// <summary> /// <summary>
/// категории операций /// категория операций
/// </summary> /// </summary>
public IEnumerable<int> CategoryIds { get; set; } [Required]
public int IdWell { get; set; }
/// <summary>
/// категория операций
/// </summary>
[Required]
public int IdCategory { get; set; }
/// <summary> /// <summary>
/// Больше или равно дате /// Больше или равно дате

View File

@ -8,8 +8,8 @@ namespace AsbCloudApp.Services
{ {
public interface IDetectedOperationService public interface IDetectedOperationService
{ {
Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(CancellationToken token); Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token);
Task<DetectedOperationListDto> GetAsync(int idWell, Requests.DetectedOperationRequest request, CancellationToken token); Task<DetectedOperationListDto> GetAsync(DetectedOperationRequest request, CancellationToken token);
Task<int> DeleteAsync(int idWell, DetectedOperationRequest request, CancellationToken token); Task<int> DeleteAsync(DetectedOperationRequest request, CancellationToken token);
} }
} }

View File

@ -33,9 +33,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
this.scheduleService = scheduleService; this.scheduleService = scheduleService;
} }
public async Task<DetectedOperationListDto> GetAsync(int idWell, DetectedOperationRequest request, CancellationToken token) public async Task<DetectedOperationListDto> GetAsync(DetectedOperationRequest request, CancellationToken token)
{ {
var well = await wellService.GetOrDefaultAsync(idWell, token); var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
if (well?.IdTelemetry is null || well.Timezone is null) if (well?.IdTelemetry is null || well.Timezone is null)
return null; return null;
@ -44,8 +44,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
var data = await query.ToListAsync(token); var data = await query.ToListAsync(token);
var operationValues = await operationValueService.GetByIdWellAsync(idWell, token); var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token);
var schedules = await scheduleService.GetByIdWellAsync(idWell, token); var schedules = await scheduleService.GetByIdWellAsync(request.IdWell, token);
var dtos = data.Select(o => Convert(o, well, operationValues, schedules)); var dtos = data.Select(o => Convert(o, well, operationValues, schedules));
var groups = dtos.GroupBy(o => o.Driller); var groups = dtos.GroupBy(o => o.Driller);
@ -78,9 +78,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
return result; return result;
} }
public async Task<int> DeleteAsync(int idWell, DetectedOperationRequest request, CancellationToken token) public async Task<int> DeleteAsync(DetectedOperationRequest request, CancellationToken token)
{ {
var well = await wellService.GetOrDefaultAsync(idWell, token); var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
if (well?.IdTelemetry is null || well.Timezone is null) if (well?.IdTelemetry is null || well.Timezone is null)
return 0; return 0;
@ -122,8 +122,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
if (request is not null) if (request is not null)
{ {
if (request.CategoryIds is not null) query = query.Where(o => request.IdCategory == o.IdCategory);
query = query.Where(o => request.CategoryIds.Contains(o.IdCategory));
if (request.GtDate is not null) if (request.GtDate is not null)
query = query.Where(o => o.DateStart >= request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours)); query = query.Where(o => o.DateStart >= request.GtDate.Value.ToUtcDateTimeOffset(well.Timezone.Hours));
@ -183,15 +182,32 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
return dto; return dto;
} }
public async Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(CancellationToken token) public async Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token)
{ {
var result = await db.WellOperationCategories IQueryable<WellOperationCategory> query = null;
if(idWell is null)
{
query = db.WellOperationCategories;
}
else
{
var well = await wellService.GetOrDefaultAsync((int )idWell, token);
if (well?.IdTelemetry is null)
return null;
var idTelemetry = (int)well.IdTelemetry;
query = db.DetectedOperations
.Include(o => o.OperationCategory)
.Where(o => o.IdTelemetry == idTelemetry)
.Select(o => o.OperationCategory)
.Distinct();
}
var result = await query
.Where(c => c.Id < 1000) .Where(c => c.Id < 1000)
.AsNoTracking()
.Select(c => c.Adapt<WellOperationCategoryDto>()) .Select(c => c.Adapt<WellOperationCategoryDto>())
.ToArrayAsync(token); .ToArrayAsync(token);
return result; return result;
} }
} }
} }

View File

@ -12,7 +12,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
public int IdCategory { get; } public int IdCategory { get; }
// TODO: assert MaxDurationSeconds and MinDurationSeconds // TODO: assert MaxDurationSeconds and MinDurationSeconds
public double MaxDurationSeconds { get; } = 31 * 24 * 60 * 60; public double MaxDurationSeconds { get; } = 24 * 60 * 60;
public double MinDurationSeconds { get; } = 3; public double MinDurationSeconds { get; } = 3;
/// <summary> /// <summary>

View File

@ -6,7 +6,12 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
#nullable enable #nullable enable
class DetectorDrillingRotor : DetectorAbstract class DetectorDrillingRotor : DetectorAbstract
{ {
public DetectorDrillingRotor() : base(1) const double minRop = 5; //м/час
const double minRotorSpeed = 5; //об/мин
const double ticksPerHour = 60 * 60 * 10_000_000d;
const double minPressure = 25;
public DetectorDrillingRotor() : base(2)
{ {
FragmentLength = 15; FragmentLength = 15;
StepLength = 10; StepLength = 10;
@ -15,17 +20,19 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
protected override bool DetectStart(DetectableTelemetry[] telemetry, int position) protected override bool DetectStart(DetectableTelemetry[] telemetry, int position)
{ {
var firstItem = telemetry[position]; var firstItem = telemetry[position];
var delta = firstItem.WellDepth - firstItem.BitDepth; var deltaDepth = firstItem.WellDepth - firstItem.BitDepth;
if (delta is not null && if (deltaDepth is not null &&
System.Math.Abs((float)delta) > 1d) System.Math.Abs((float)deltaDepth) > 1d)
return false;
if(firstItem.RotorSpeed > minRotorSpeed)
return false;
if (firstItem.Pressure < minPressure)
return false; return false;
var fragment = telemetry[position..(position + FragmentLength)]; var fragment = telemetry[position..(position + FragmentLength)];
const double minRop = 5; //м/час
const double minRotorSpeed = 5; //об/мин
const double ticksPerHour = 60 * 60 * 10_000_000d;
var lineBlockPosition = new InterpolationLine(fragment.Select(d => (d.BlockPosition ?? 0d, d.DateTime.Ticks / ticksPerHour))); var lineBlockPosition = new InterpolationLine(fragment.Select(d => (d.BlockPosition ?? 0d, d.DateTime.Ticks / ticksPerHour)));
if (!lineBlockPosition.IsYDecreases(minRop)) if (!lineBlockPosition.IsYDecreases(minRop))
return false; return false;
@ -34,19 +41,19 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
if (!lineWellDepth.IsYIncreases(minRop)) if (!lineWellDepth.IsYIncreases(minRop))
return false; return false;
var lineRotorSpeed = new InterpolationLine(fragment.Select(d => (d.RotorSpeed ?? 0d, d.DateTime.Ticks / ticksPerHour)));
if (!lineRotorSpeed.IsAverageYLessThanBound(minRotorSpeed))
return false;
return true; return true;
} }
protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position) protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position)
=> !DetectStart(telemetry, position); => !DetectStart(telemetry, position);
/// <summary>
/// Рассчитываем МСП, м/час
/// </summary>
/// <param name="result"></param>
protected override void CalcValue(ref DetectedOperation result) protected override void CalcValue(ref DetectedOperation result)
{ {
throw new System.NotImplementedException(); result.Value = (result.DepthEnd - result.DepthStart) / (result.DateEnd - result.DateStart).TotalHours;
} }
} }
#nullable disable #nullable disable

View File

@ -6,6 +6,11 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
#nullable enable #nullable enable
class DetectorDrillingSlide : DetectorAbstract class DetectorDrillingSlide : DetectorAbstract
{ {
const double minRop = 5; //м/час
const double minRotorSpeed = 5; //об/мин
const double ticksPerHour = 60 * 60 * 10_000_000d;
const double minPressure = 25;
public DetectorDrillingSlide() : base(3) public DetectorDrillingSlide() : base(3)
{ {
FragmentLength = 10; FragmentLength = 10;
@ -14,17 +19,19 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
protected override bool DetectStart(DetectableTelemetry[] telemetry, int position) protected override bool DetectStart(DetectableTelemetry[] telemetry, int position)
{ {
var firstItem = telemetry[position]; var firstItem = telemetry[position];
var delta = firstItem.WellDepth - firstItem.BitDepth; var deltaDepth = firstItem.WellDepth - firstItem.BitDepth;
if (delta is not null && if (deltaDepth is not null &&
System.Math.Abs((float)delta) > 1d) System.Math.Abs((float)deltaDepth) > 1d)
return false;
if(firstItem.RotorSpeed < minRotorSpeed)
return false;
if (firstItem.Pressure < minPressure)
return false; return false;
var fragment = telemetry[position..(position + FragmentLength)]; var fragment = telemetry[position..(position + FragmentLength)];
const double minRop = 5; //м/час
const double minRotorSpeed = 5; //об/мин
const double ticksPerHour = 60 * 60 * 10_000_000d;
var lineBlockPosition = new InterpolationLine(fragment.Select(d => (d.BlockPosition ?? 0d, d.DateTime.Ticks / ticksPerHour))); var lineBlockPosition = new InterpolationLine(fragment.Select(d => (d.BlockPosition ?? 0d, d.DateTime.Ticks / ticksPerHour)));
if (!lineBlockPosition.IsYDecreases(minRop)) if (!lineBlockPosition.IsYDecreases(minRop))
return false; return false;
@ -33,19 +40,19 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
if (!lineWellDepth.IsYIncreases(minRop)) if (!lineWellDepth.IsYIncreases(minRop))
return false; return false;
var lineRotorSpeed = new InterpolationLine(fragment.Select(d => (d.RotorSpeed ?? 0d, d.DateTime.Ticks / ticksPerHour)));
if (!lineRotorSpeed.IsAverageYMoreThanBound(minRotorSpeed))
return false;
return true; return true;
} }
protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position) protected override bool DetectEnd(DetectableTelemetry[] telemetry, int position)
=> !DetectStart(telemetry, position); => !DetectStart(telemetry, position);
/// <summary>
/// Рассчитываем МСП, м/час
/// </summary>
/// <param name="result"></param>
protected override void CalcValue(ref DetectedOperation result) protected override void CalcValue(ref DetectedOperation result)
{ {
throw new System.NotImplementedException(); result.Value = (result.DepthEnd - result.DepthStart) / (result.DateEnd - result.DateStart).TotalHours;
} }
} }
#nullable disable #nullable disable

View File

@ -16,8 +16,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
private readonly IEnumerable<DetectorAbstract> detectors = new List<DetectorAbstract> private readonly IEnumerable<DetectorAbstract> detectors = new List<DetectorAbstract>
{ {
new Detectors.DetectorSlipsTime(), new Detectors.DetectorSlipsTime(),
// new Detectors.DetectorDrillingRotor(), new Detectors.DetectorDrillingRotor(),
// new Detectors.DetectorDrillingSlide(), new Detectors.DetectorDrillingSlide(),
}; };
private readonly int minStepLength; private readonly int minStepLength;

View File

@ -1,8 +1,10 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Requests; using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -11,8 +13,9 @@ namespace AsbCloudWebApi.Controllers.SAUB
/// <summary> /// <summary>
/// Операции определенные по телеметрии САУБ /// Операции определенные по телеметрии САУБ
/// </summary> /// </summary>
[Route("api/well/{idWell}/[controller]")] [Route("api/[controller]")]
[ApiController] [ApiController]
[Authorize]
public class DetectedOperationController : ControllerBase public class DetectedOperationController : ControllerBase
{ {
private readonly IDetectedOperationService detectedOperationService; private readonly IDetectedOperationService detectedOperationService;
@ -25,38 +28,36 @@ namespace AsbCloudWebApi.Controllers.SAUB
} }
/// <summary> /// <summary>
/// получить справочник операций. Отличается от операций заводимых вручную /// получить справочник операций. Отличается от операций заводимых вручную.
/// При задании id скважины вернет только те операции, которые определились в телеметрии этой скважины.
/// </summary> /// </summary>
/// <param name="idWell">[опционально] id скважины</param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet("categories")] [HttpGet("categories")]
[ProducesResponseType(typeof(IEnumerable<WellOperationCategoryDto>), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(IEnumerable<WellOperationCategoryDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetCategoriesAsync(CancellationToken token = default) public async Task<IActionResult> GetCategoriesAsync([FromQuery] int? idWell, CancellationToken token = default)
{ {
var result = await detectedOperationService.GetCategoriesAsync(token); var result = await detectedOperationService.GetCategoriesAsync(idWell, token);
return Ok(result); return Ok(result);
} }
/// <summary> /// <summary>
/// Получить фильтрованный список операций по телеметрии САУБ /// Получить фильтрованный список операций по телеметрии САУБ
/// </summary> /// </summary>
/// <param name="idWell"></param>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
[ProducesResponseType(typeof(DetectedOperationListDto), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(DetectedOperationListDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetAsync( public async Task<IActionResult> GetAsync(
int idWell,
[FromQuery] DetectedOperationRequest request, [FromQuery] DetectedOperationRequest request,
CancellationToken token = default) CancellationToken token = default)
{ {
int? idCompany = User.GetCompanyId(); if (!await UserHasAccesToWellAsync(request.IdWell, token))
if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false))
return Forbid(); return Forbid();
var result = await detectedOperationService.GetAsync(idWell, request, token); var result = await detectedOperationService.GetAsync(request, token);
return Ok(result); return Ok(result);
} }
@ -65,7 +66,6 @@ namespace AsbCloudWebApi.Controllers.SAUB
/// Удаленные операции будут определены повторно сервисом автоматизированного определения операций. /// Удаленные операции будут определены повторно сервисом автоматизированного определения операций.
/// Может потребоваться при изменении алгоритмов определения /// Может потребоваться при изменении алгоритмов определения
/// </summary> /// </summary>
/// <param name="idWell"></param>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
@ -73,17 +73,24 @@ namespace AsbCloudWebApi.Controllers.SAUB
[Permission] [Permission]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> DeleteAsync( public async Task<IActionResult> DeleteAsync(
int idWell,
[FromQuery] DetectedOperationRequest request, [FromQuery] DetectedOperationRequest request,
CancellationToken token = default) CancellationToken token)
{ {
int? idCompany = User.GetCompanyId(); if (!await UserHasAccesToWellAsync(request.IdWell, token))
if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false))
return Forbid(); return Forbid();
var result = await detectedOperationService.DeleteAsync(idWell, request, token); var result = await detectedOperationService.DeleteAsync(request, token);
return Ok(result); return Ok(result);
} }
protected async Task<bool> UserHasAccesToWellAsync(int idWell, CancellationToken token)
{
var idCompany = User.GetCompanyId();
if (idCompany is not null &&
await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token)
.ConfigureAwait(false))
return true;
return false;
}
} }
} }