forked from ddrilling/AsbCloudServer
Merge branch 'dev' into feature/sections
This commit is contained in:
commit
521e36834e
@ -6,7 +6,7 @@ namespace System.Collections.Generic
|
|||||||
/// Цикличный массив
|
/// Цикличный массив
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
public class CyclycArray<T> : IEnumerable<T>
|
public class CyclicArray<T> : IEnumerable<T>
|
||||||
{
|
{
|
||||||
readonly T[] array;
|
readonly T[] array;
|
||||||
int used, current = -1;
|
int used, current = -1;
|
||||||
@ -15,7 +15,7 @@ namespace System.Collections.Generic
|
|||||||
/// constructor
|
/// constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="capacity"></param>
|
/// <param name="capacity"></param>
|
||||||
public CyclycArray(int capacity)
|
public CyclicArray(int capacity)
|
||||||
{
|
{
|
||||||
array = new T[capacity];
|
array = new T[capacity];
|
||||||
}
|
}
|
@ -94,5 +94,5 @@ public class ProcessMapReportWellDrillingDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Механическая скорость, м/ч
|
/// Механическая скорость, м/ч
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PlanFactDto<double?> Rop { get; set; }
|
public PlanFactDto<double?> Rop { get; set; } = new();
|
||||||
}
|
}
|
@ -35,14 +35,18 @@ public class SectionByOperationsDto
|
|||||||
public DateTimeOffset DateStart { get; set; }
|
public DateTimeOffset DateStart { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Глубина после завершения последней операции операции в секции, м
|
/// Глубина после завершения последней операции в секции, м
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Range(0, 50_000)]
|
[Range(0, 50_000)]
|
||||||
public double DepthEnd { get; set; }
|
public double DepthEnd { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Дата после завершения последней операции операции в секции
|
/// Дата после завершения последней операции в секции
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTimeOffset DateEnd { get; set; }
|
public DateTimeOffset DateEnd { get; set; }
|
||||||
public string Caption { get; set; }
|
|
||||||
|
/// <summary>
|
||||||
|
/// Название
|
||||||
|
/// </summary>
|
||||||
|
public string Caption { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace AsbCloudApp.Repositories
|
|||||||
void AddRange(int idTelemetry, IEnumerable<TDto> range);
|
void AddRange(int idTelemetry, IEnumerable<TDto> range);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// вернуть последнюю записть
|
/// вернуть последнюю запись
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idTelemetry"></param>
|
/// <param name="idTelemetry"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@ -49,7 +49,7 @@ namespace AsbCloudApp.Repositories
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idTelemetry"></param>
|
/// <param name="idTelemetry"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
DatesRangeDto? GetOrDefaultCachedaDateRange(int idTelemetry);
|
DatesRangeDto? GetOrDefaultCachedDateRange(int idTelemetry);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить диапазон дат телеметрии.
|
/// Получить диапазон дат телеметрии.
|
||||||
|
@ -18,7 +18,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> UpdateRangeAsync(int idWell, IEnumerable<WellFinalDocumentInputDto>? dtos, CancellationToken token);
|
Task<int> UpdateRangeAsync(int idWell, IEnumerable<WellFinalDocumentInputDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение истории файлов
|
/// Получение истории файлов
|
||||||
|
@ -12,14 +12,13 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace AsbCloudDb
|
namespace AsbCloudDb
|
||||||
{
|
{
|
||||||
public static class EFExtentions
|
public static class EFExtensions
|
||||||
{
|
{
|
||||||
private static readonly System.Text.Json.JsonSerializerOptions jsonSerializerOptions = new()
|
private static readonly JsonSerializerOptions jsonSerializerOptions = new()
|
||||||
{
|
{
|
||||||
AllowTrailingCommas = true,
|
AllowTrailingCommas = true,
|
||||||
WriteIndented = true,
|
WriteIndented = true,
|
||||||
NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString |
|
NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.AllowNamedFloatingPointLiterals,
|
||||||
System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder<TProperty> HasJsonConversion<TProperty>(
|
public static Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder<TProperty> HasJsonConversion<TProperty>(
|
||||||
@ -28,11 +27,11 @@ namespace AsbCloudDb
|
|||||||
|
|
||||||
public static Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder<TProperty> HasJsonConversion<TProperty>(
|
public static Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder<TProperty> HasJsonConversion<TProperty>(
|
||||||
this Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder<TProperty> builder,
|
this Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder<TProperty> builder,
|
||||||
System.Text.Json.JsonSerializerOptions jsonSerializerOptions)
|
JsonSerializerOptions jsonSerializerOptions)
|
||||||
{
|
{
|
||||||
builder.HasConversion(
|
builder.HasConversion(
|
||||||
s => System.Text.Json.JsonSerializer.Serialize(s, jsonSerializerOptions),
|
s => JsonSerializer.Serialize(s, jsonSerializerOptions),
|
||||||
s => System.Text.Json.JsonSerializer.Deserialize<TProperty>(s, jsonSerializerOptions)!);
|
s => JsonSerializer.Deserialize<TProperty>(s, jsonSerializerOptions)!);
|
||||||
|
|
||||||
ValueComparer<TProperty> valueComparer = new (
|
ValueComparer<TProperty> valueComparer = new (
|
||||||
(a,b) =>
|
(a,b) =>
|
||||||
@ -102,7 +101,7 @@ namespace AsbCloudDb
|
|||||||
return factory.Columns;
|
return factory.Columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<T> Upsert<T>(this DbSet<T> dbSet, T value)
|
public static EntityEntry<T> Upsert<T>(this DbSet<T> dbSet, T value)
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
return dbSet.Contains(value)
|
return dbSet.Contains(value)
|
@ -5,9 +5,9 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
|||||||
|
|
||||||
namespace AsbCloudDb
|
namespace AsbCloudDb
|
||||||
{
|
{
|
||||||
public static class EFExtentionsInnitialization
|
public static class EFExtensionsInitialization
|
||||||
{
|
{
|
||||||
public static void EnshureCreatedAndMigrated(this DatabaseFacade db)
|
public static void EnsureCreatedAndMigrated(this DatabaseFacade db)
|
||||||
{
|
{
|
||||||
db.SetCommandTimeout(TimeSpan.FromMinutes(5));
|
db.SetCommandTimeout(TimeSpan.FromMinutes(5));
|
||||||
if (db.EnsureCreated())
|
if (db.EnsureCreated())
|
9083
AsbCloudDb/Migrations/20231205062914_Daily_report_lost_migration.Designer.cs
generated
Normal file
9083
AsbCloudDb/Migrations/20231205062914_Daily_report_lost_migration.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Migrations
|
||||||
|
{
|
||||||
|
public partial class Daily_report_lost_migration : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_relation_user_role_permission",
|
||||||
|
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||||
|
keyValues: new object[] { 529, 1 });
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_permission",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 529);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "t_permission",
|
||||||
|
columns: new[] { "id", "description", "name" },
|
||||||
|
values: new object[] { 529, "Разрешение редактировать фактические траектории", "FactTrajectory.edit" });
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "t_relation_user_role_permission",
|
||||||
|
columns: new[] { "id_permission", "id_user_role" },
|
||||||
|
values: new object[] { 529, 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9090
AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.Designer.cs
generated
Normal file
9090
AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,72 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Migrations
|
||||||
|
{
|
||||||
|
public partial class DetectedOperation_add_subsystems_and_extraData : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_relation_user_role_permission",
|
||||||
|
keyColumns: new[] { "id_permission", "id_user_role" },
|
||||||
|
keyValues: new object[] { 529, 1 });
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "t_permission",
|
||||||
|
keyColumn: "id",
|
||||||
|
keyValue: 529);
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "id_reason_of_end",
|
||||||
|
table: "t_detected_operation");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "enabled_subsystems",
|
||||||
|
table: "t_detected_operation",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0,
|
||||||
|
comment: "флаги аключенных подсистем");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<IDictionary<string, object>>(
|
||||||
|
name: "extra_data",
|
||||||
|
table: "t_detected_operation",
|
||||||
|
type: "jsonb",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new { },
|
||||||
|
comment: "доп. инфо по операции");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "enabled_subsystems",
|
||||||
|
table: "t_detected_operation");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "extra_data",
|
||||||
|
table: "t_detected_operation");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "id_reason_of_end",
|
||||||
|
table: "t_detected_operation",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0,
|
||||||
|
comment: "Код признака окончания операции");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "t_permission",
|
||||||
|
columns: new[] { "id", "description", "name" },
|
||||||
|
values: new object[] { 529, "Разрешение редактировать фактические траектории", "FactTrajectory.edit" });
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "t_relation_user_role_permission",
|
||||||
|
columns: new[] { "id_permission", "id_user_role" },
|
||||||
|
values: new object[] { 529, 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -19,7 +20,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", "6.0.22")
|
.HasAnnotation("ProductVersion", "6.0.7")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
||||||
@ -136,21 +137,21 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Caption = "Недропользователь",
|
Caption = "Недропользователь",
|
||||||
IsContact = false,
|
IsContact = true,
|
||||||
Order = 3
|
Order = 3
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 2,
|
Id = 2,
|
||||||
Caption = "Буровой подрядчик",
|
Caption = "Буровой подрядчик",
|
||||||
IsContact = false,
|
IsContact = true,
|
||||||
Order = 2
|
Order = 2
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Caption = "Сервис автоматизации бурения",
|
Caption = "Сервис автоматизации бурения",
|
||||||
IsContact = false,
|
IsContact = true,
|
||||||
Order = 0
|
Order = 0
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
@ -178,7 +179,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
{
|
{
|
||||||
Id = 7,
|
Id = 7,
|
||||||
Caption = "Служба супервайзинга",
|
Caption = "Служба супервайзинга",
|
||||||
IsContact = true,
|
IsContact = false,
|
||||||
Order = 1
|
Order = 1
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
@ -189,11 +190,18 @@ namespace AsbCloudDb.Migrations
|
|||||||
Order = 7
|
Order = 7
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
|
{
|
||||||
|
Id = 11,
|
||||||
|
Caption = "Дизельный сервис",
|
||||||
|
IsContact = false,
|
||||||
|
Order = 9
|
||||||
|
},
|
||||||
|
new
|
||||||
{
|
{
|
||||||
Id = 12,
|
Id = 12,
|
||||||
Caption = "Сервис по обслуживанию верхних силовых приводов",
|
Caption = "Сервис по обслуживанию верхних силовых приводов",
|
||||||
IsContact = true,
|
IsContact = true,
|
||||||
Order = 7
|
Order = 8
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -264,24 +272,46 @@ namespace AsbCloudDb.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("AsbCloudDb.Model.DailyReports.DailyReport", b =>
|
modelBuilder.Entity("AsbCloudDb.Model.DailyReports.DailyReport", b =>
|
||||||
{
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("Date")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("date")
|
||||||
|
.HasComment("Дата формирования отчёта");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateLastUpdate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("date_last_update")
|
||||||
|
.HasComment("Дата последнего обновления");
|
||||||
|
|
||||||
b.Property<int>("IdWell")
|
b.Property<int>("IdWell")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
.HasColumnName("id_well")
|
.HasColumnName("id_well")
|
||||||
.HasComment("ID скважины");
|
.HasComment("ID скважины");
|
||||||
|
|
||||||
b.Property<DateOnly>("StartDate")
|
b.Property<string>("SignBlock")
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("start_date")
|
|
||||||
.HasComment("Дата отчёта");
|
|
||||||
|
|
||||||
b.Property<string>("Info")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("info")
|
.HasColumnName("sign_block")
|
||||||
.HasComment("Список параметров для отчёта");
|
.HasComment("Подпись");
|
||||||
|
|
||||||
b.HasKey("IdWell", "StartDate")
|
b.Property<string>("SubsystemBlock")
|
||||||
.HasName("t_id_well_date_start_pk");
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("subsystem_block")
|
||||||
|
.HasComment("Наработкой подсистем");
|
||||||
|
|
||||||
|
b.Property<string>("TimeBalanceBlock")
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("time_balance_block")
|
||||||
|
.HasComment("Баланс времени");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IdWell", "Date")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("t_daily_report");
|
b.ToTable("t_daily_report");
|
||||||
|
|
||||||
@ -353,16 +383,22 @@ namespace AsbCloudDb.Migrations
|
|||||||
.HasColumnName("depth_start")
|
.HasColumnName("depth_start")
|
||||||
.HasComment("Глубина на начало операции, м");
|
.HasComment("Глубина на начало операции, м");
|
||||||
|
|
||||||
|
b.Property<int>("EnabledSubsystems")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("enabled_subsystems")
|
||||||
|
.HasComment("флаги аключенных подсистем");
|
||||||
|
|
||||||
|
b.Property<IDictionary<string, object>>("ExtraData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("extra_data")
|
||||||
|
.HasComment("доп. инфо по операции");
|
||||||
|
|
||||||
b.Property<int>("IdCategory")
|
b.Property<int>("IdCategory")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
.HasColumnName("id_category")
|
.HasColumnName("id_category")
|
||||||
.HasComment("Id категории операции");
|
.HasComment("Id категории операции");
|
||||||
|
|
||||||
b.Property<int>("IdReasonOfEnd")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id_reason_of_end")
|
|
||||||
.HasComment("Код признака окончания операции");
|
|
||||||
|
|
||||||
b.Property<int>("IdTelemetry")
|
b.Property<int>("IdTelemetry")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
.HasColumnName("id_telemetry");
|
.HasColumnName("id_telemetry");
|
||||||
@ -8147,7 +8183,7 @@ namespace AsbCloudDb.Migrations
|
|||||||
b.Navigation("Well");
|
b.Navigation("Well");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("AsbCloudDb.Model.DailyReport.DailyReport", b =>
|
modelBuilder.Entity("AsbCloudDb.Model.DailyReports.DailyReport", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("AsbCloudDb.Model.Well", "Well")
|
b.HasOne("AsbCloudDb.Model.Well", "Well")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
|
@ -351,6 +351,10 @@ namespace AsbCloudDb.Model
|
|||||||
.HasJsonConversion();
|
.HasJsonConversion();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<DetectedOperation>(entity => entity
|
||||||
|
.Property(p=>p.ExtraData)
|
||||||
|
.HasJsonConversion());
|
||||||
|
|
||||||
modelBuilder.Entity<TelemetryDataSaubStat>(entity =>
|
modelBuilder.Entity<TelemetryDataSaubStat>(entity =>
|
||||||
{
|
{
|
||||||
entity.HasNoKey()
|
entity.HasNoKey()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
@ -40,8 +41,11 @@ namespace AsbCloudDb.Model
|
|||||||
[Column("value"), Comment("Ключевой показатель операции")]
|
[Column("value"), Comment("Ключевой показатель операции")]
|
||||||
public double Value { get; set; }
|
public double Value { get; set; }
|
||||||
|
|
||||||
[Column("id_reason_of_end"), Comment("Код признака окончания операции")]
|
[Column("enabled_subsystems"), Comment("флаги аключенных подсистем")]
|
||||||
public int IdReasonOfEnd { get; set; }
|
public int EnabledSubsystems { get; set; }
|
||||||
|
|
||||||
|
[Column("extra_data", TypeName = "jsonb"), Comment("доп. инфо по операции")]
|
||||||
|
public IDictionary<string, object> ExtraData { get; set; } = null!;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
[ForeignKey(nameof(IdTelemetry))]
|
[ForeignKey(nameof(IdTelemetry))]
|
||||||
@ -53,5 +57,57 @@ namespace AsbCloudDb.Model
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"{IdCategory}\t{DateStart:G}\t{DateEnd:G}\t{DurationMinutes:#0.#}\t{DepthStart:#0.#}\t{DepthEnd:#0.#}";
|
=> $"{IdCategory}\t{DateStart:G}\t{DateEnd:G}\t{DurationMinutes:#0.#}\t{DepthStart:#0.#}\t{DepthEnd:#0.#}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Флаги аключенных подсистем
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum EnabledSubsystemsFlags
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Автоподача долота
|
||||||
|
/// </summary>
|
||||||
|
AutoRotor = 1 << 0,
|
||||||
|
/// <summary>
|
||||||
|
/// БУРЕНИЕ В СЛАЙДЕ
|
||||||
|
/// </summary>
|
||||||
|
AutoSlide = 1 << 1,
|
||||||
|
/// <summary>
|
||||||
|
/// ПРОРАБОТКА
|
||||||
|
/// </summary>
|
||||||
|
AutoConditionig = 1 << 2,
|
||||||
|
/// <summary>
|
||||||
|
/// СПУСК СПО
|
||||||
|
/// </summary>
|
||||||
|
AutoSinking = 1 << 3,
|
||||||
|
/// <summary>
|
||||||
|
/// ПОДЪЕМ СПО
|
||||||
|
/// </summary>
|
||||||
|
AutoLifting = 1 << 4,
|
||||||
|
/// <summary>
|
||||||
|
/// ПОДЪЕМ С ПРОРАБОТКОЙ
|
||||||
|
/// </summary>
|
||||||
|
AutoLiftingWithConditionig = 1 << 5,
|
||||||
|
/// <summary>
|
||||||
|
/// блокировка
|
||||||
|
/// </summary>
|
||||||
|
AutoBlocknig = 1 << 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Есть ли флаг подсистемы у операции
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flag"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool HasSubsystemFlag(EnabledSubsystemsFlags flag)
|
||||||
|
=> HasSubsystemFlag((int)flag);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Есть ли флаг/флаги подсистемы у операции
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flags"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool HasSubsystemFlag(int flags)
|
||||||
|
=> (EnabledSubsystems & flags) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,7 +42,7 @@ namespace AsbCloudDb.Model
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// КНБК
|
/// КНБК
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int IdKnbk = 4000;
|
public const int IdBha = 4000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Механическое. бурение
|
/// Механическое. бурение
|
||||||
@ -246,7 +246,7 @@ namespace AsbCloudDb.Model
|
|||||||
/// Виды работ
|
/// Виды работ
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static WellOperationCategory[] WorkTypes { get; } = new WellOperationCategory[]{
|
public static WellOperationCategory[] WorkTypes { get; } = new WellOperationCategory[]{
|
||||||
new () {Id = IdKnbk, IdParent = 3000, Name = "КНБК", KeyValueName = "dT", KeyValueUnits = "мин" },
|
new () {Id = IdBha, IdParent = 3000, Name = "КНБК", KeyValueName = "dT", KeyValueUnits = "мин" },
|
||||||
new () {Id = IdMechanicalDrilling, IdParent = 3000, Name = "Механическое. бурение", KeyValueName = "dT", KeyValueUnits = "м/ч" },
|
new () {Id = IdMechanicalDrilling, IdParent = 3000, Name = "Механическое. бурение", KeyValueName = "dT", KeyValueUnits = "м/ч" },
|
||||||
new () {Id = IdMeasurementStat, IdParent = 3000, Name = "Статический замер", KeyValueName = "dT", KeyValueUnits = "мин" },
|
new () {Id = IdMeasurementStat, IdParent = 3000, Name = "Статический замер", KeyValueName = "dT", KeyValueUnits = "мин" },
|
||||||
new () {Id = IdNormalizedWellDiameter, IdParent = 3000, Name = "Нормализация диаметра скважины", KeyValueName = "dT", KeyValueUnits = "мин" },
|
new () {Id = IdNormalizedWellDiameter, IdParent = 3000, Name = "Нормализация диаметра скважины", KeyValueName = "dT", KeyValueUnits = "мин" },
|
||||||
|
@ -36,12 +36,12 @@ public class BackgroundWorker : BackgroundService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// последние 16 завершившиеся с ошибкой
|
/// последние 16 завершившиеся с ошибкой
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CyclycArray<Work> Felled { get; } = new(16);
|
public CyclicArray<Work> Felled { get; } = new(16);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// последние 16 успешно завершенных
|
/// последние 16 успешно завершенных
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CyclycArray<Work> Done { get; } = new(16);
|
public CyclicArray<Work> Done { get; } = new(16);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ошибка в главном цикле, никогда не должна появляться
|
/// Ошибка в главном цикле, никогда не должна появляться
|
||||||
|
@ -167,7 +167,6 @@ public class WorkSubsystemOscillationOperationTimeCalc : WorkSubsystemOperationT
|
|||||||
.Where(d => d.IdTelemetry == idTelemetry)
|
.Where(d => d.IdTelemetry == idTelemetry)
|
||||||
.Where(d => d.DateTime >= dateBegin)
|
.Where(d => d.DateTime >= dateBegin)
|
||||||
.Where(d => d.DateTime <= dateEnd)
|
.Where(d => d.DateTime <= dateEnd)
|
||||||
.Where(d => d.WellDepth != null)
|
|
||||||
.Where(d => d.WellDepth > 0)
|
.Where(d => d.WellDepth > 0)
|
||||||
.GroupBy(d => Math.Ceiling(d.WellDepth * 10))
|
.GroupBy(d => Math.Ceiling(d.WellDepth * 10))
|
||||||
.Select(g => new
|
.Select(g => new
|
||||||
|
@ -111,7 +111,8 @@ public class WellOperationRepository : IWellOperationRepository
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (lastFactOperation is not null)
|
if (lastFactOperation is not null)
|
||||||
return DateTime.SpecifyKind(lastFactOperation.OperationPlan.DateStart.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified);
|
return DateTime.SpecifyKind(lastFactOperation.OperationPlan!.DateStart.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,10 +95,8 @@ public class DailyReportService : IDailyReportService
|
|||||||
|
|
||||||
public async Task<DailyReportDto> GetAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken)
|
public async Task<DailyReportDto> GetAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken);
|
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken)
|
||||||
|
?? throw new ArgumentNullException(nameof(idWell), $"Скважина с Id: {idWell} не найдена");
|
||||||
if (well is null)
|
|
||||||
throw new ArgumentNullException(nameof(idWell), $"Скважина с Id: {idWell} не найдена");
|
|
||||||
|
|
||||||
if (!await IsDateDailyReportInRangeAsync(idWell, dateDailyReport, cancellationToken))
|
if (!await IsDateDailyReportInRangeAsync(idWell, dateDailyReport, cancellationToken))
|
||||||
throw new ArgumentInvalidException(nameof(dateDailyReport), "Невозможно получить суточный отчёт");
|
throw new ArgumentInvalidException(nameof(dateDailyReport), "Невозможно получить суточный отчёт");
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -1,18 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations
|
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
||||||
{
|
|
||||||
|
|
||||||
public class DetectableTelemetry
|
public class DetectableTelemetry
|
||||||
{
|
{
|
||||||
public DateTimeOffset DateTime { get; set; }
|
public DateTimeOffset DateTime { get; set; }
|
||||||
public int? IdUser { get; set; }
|
public int? IdUser { get; set; }
|
||||||
|
public int Mode { get; set; }
|
||||||
public float WellDepth { get; set; }
|
public float WellDepth { get; set; }
|
||||||
public float Pressure { get; set; }
|
public float Pressure { get; set; }
|
||||||
public float HookWeight { get; set; }
|
public float HookWeight { get; set; }
|
||||||
public float BlockPosition { get; set; }
|
public float BlockPosition { get; set; }
|
||||||
public float BitDepth { get; set; }
|
public float BitDepth { get; set; }
|
||||||
public float RotorSpeed { get; set; }
|
public float RotorSpeed { get; set; }
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,17 @@ using System.Reflection;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
namespace AsbCloudInfrastructure.Services.DetectOperations;
|
||||||
|
|
||||||
public class DetectedOperationExportService
|
public class DetectedOperationExportService
|
||||||
{
|
{
|
||||||
private readonly DetectorAbstract[] detectors = { new DetectorDrilling(), new DetectorSlipsTime() };
|
private readonly DetectorAbstract[] detectors =
|
||||||
|
{
|
||||||
|
new DetectorDrilling(),
|
||||||
|
new DetectorSlipsTime()
|
||||||
|
};
|
||||||
|
|
||||||
private readonly IDictionary<int, string> domains = new Dictionary<int, string>
|
private readonly IDictionary<int, string> domains = new Dictionary<int, string>
|
||||||
{
|
{
|
||||||
@ -38,12 +43,15 @@ public class DetectedOperationExportService
|
|||||||
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 readonly IAsbCloudDbContext dbContext;
|
private readonly IAsbCloudDbContext dbContext;
|
||||||
|
private readonly IWellOperationRepository wellOperationRepository;
|
||||||
|
|
||||||
public DetectedOperationExportService(IAsbCloudDbContext dbContext)
|
public DetectedOperationExportService(IAsbCloudDbContext dbContext, IWellOperationRepository wellOperationRepository)
|
||||||
{
|
{
|
||||||
this.dbContext = dbContext;
|
this.dbContext = dbContext;
|
||||||
|
this.wellOperationRepository = wellOperationRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Stream> ExportAsync(int idWell, int idDomain, CancellationToken cancellationToken)
|
public async Task<Stream> ExportAsync(int idWell, int idDomain, CancellationToken cancellationToken)
|
||||||
@ -59,20 +67,19 @@ public class DetectedOperationExportService
|
|||||||
if (!well.IdTelemetry.HasValue)
|
if (!well.IdTelemetry.HasValue)
|
||||||
throw new ArgumentNullException(nameof(well));
|
throw new ArgumentNullException(nameof(well));
|
||||||
|
|
||||||
var operations = await DetectOperationsAsync(well.IdTelemetry.Value, new DateTime(2023, 10, 14)
|
var operations = await DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, cancellationToken);
|
||||||
.ToUtcDateTimeOffset(well.Timezone.Hours), cancellationToken);
|
|
||||||
|
|
||||||
return await GenerateExcelFileStreamAsync(well, idDomain, operations, cancellationToken);
|
return await GenerateExcelFileStreamAsync(well, idDomain, operations, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Stream> GenerateExcelFileStreamAsync(Well well, int idDomain, IEnumerable<DetectedOperation> detectedOperations,
|
private async Task<Stream> GenerateExcelFileStreamAsync(Well well, int idDomain, IEnumerable<OperationDetectorResult> operationDetectorResults,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
||||||
|
|
||||||
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
|
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
|
||||||
|
|
||||||
await AddToWorkbookAsync(workbook, well, idDomain, detectedOperations, cancellationToken);
|
await AddToWorkbookAsync(workbook, well, idDomain, operationDetectorResults, cancellationToken);
|
||||||
|
|
||||||
MemoryStream memoryStream = new MemoryStream();
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
workbook.SaveAs(memoryStream, new SaveOptions { });
|
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||||
@ -80,22 +87,23 @@ public class DetectedOperationExportService
|
|||||||
return memoryStream;
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, int idDomain, IEnumerable<DetectedOperation> detectedOperations,
|
private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, int idDomain, IEnumerable<OperationDetectorResult> operationDetectorResults,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
const string sheetName = "Операции";
|
const string sheetName = "Операции";
|
||||||
|
|
||||||
if (!detectedOperations.Any())
|
if (!operationDetectorResults.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
|
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
|
||||||
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
|
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
|
||||||
|
|
||||||
await AddToSheetAsync(sheet, well, idDomain, detectedOperations.OrderBy(x => x.DateStart).ThenBy(x => x.DepthStart).ToArray(),
|
await AddToSheetAsync(sheet, well, idDomain, operationDetectorResults
|
||||||
|
.OrderBy(x => x.Operation.DateStart).ThenBy(x => x.Operation.DepthStart).ToArray(),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, int idDomain, IList<DetectedOperation> detectedOperations,
|
private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, int idDomain, IList<OperationDetectorResult> operationDetectorResults,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var wellOperationCategories = await dbContext.WellOperationCategories.ToListAsync(cancellationToken);
|
var wellOperationCategories = await dbContext.WellOperationCategories.ToListAsync(cancellationToken);
|
||||||
@ -103,39 +111,69 @@ public class DetectedOperationExportService
|
|||||||
sheet.Cell(cellDepositName).Value = well.Cluster.Deposit.Caption;
|
sheet.Cell(cellDepositName).Value = well.Cluster.Deposit.Caption;
|
||||||
sheet.Cell(cellClusterName).Value = well.Cluster.Caption;
|
sheet.Cell(cellClusterName).Value = well.Cluster.Caption;
|
||||||
sheet.Cell(cellWellName).Value = well.Caption;
|
sheet.Cell(cellWellName).Value = well.Caption;
|
||||||
sheet.Cell(cellDeltaDate).Value = detectedOperations.Max(o => o.DateEnd) - detectedOperations.Min(o => o.DateStart);
|
sheet.Cell(cellDeltaDate).Value = operationDetectorResults.Max(o => o.Operation.DateEnd) - operationDetectorResults.Min(o => o.Operation.DateStart);
|
||||||
|
|
||||||
var timeZoneWell = TimeSpan.FromHours(well.Timezone.Hours);
|
var detectedOperations = operationDetectorResults.Select(o => o.Operation).ToArray();
|
||||||
|
|
||||||
for (int i = 0; i < detectedOperations.Count; i++)
|
for (int i = 0; i < operationDetectorResults.Count; i++)
|
||||||
{
|
{
|
||||||
var dateStart = detectedOperations[i].DateStart.ToOffset(timeZoneWell);
|
var current = detectedOperations[i];
|
||||||
var dateEnd = detectedOperations[i].DateEnd.ToOffset(timeZoneWell);
|
var dateStart = current.DateStart.ToRemoteDateTime(well.Timezone.Hours);
|
||||||
|
var dateEnd = current.DateEnd.ToRemoteDateTime(well.Timezone.Hours);
|
||||||
|
|
||||||
var row = sheet.Row(5 + i + headerRowsCount);
|
var row = sheet.Row(5 + i + headerRowsCount);
|
||||||
|
|
||||||
row.Cell(columnOperationName).Value = detectedOperations[i].IdCategory == 12000
|
row.Cell(columnOperationName).Value = GetCategoryName(wellOperationCategories, current);
|
||||||
? "Бурение в слайде с осцилляцией"
|
|
||||||
: wellOperationCategories.Single(o => o.Id == detectedOperations[i].IdCategory).Name;
|
|
||||||
row.Cell(columnDateEnd).Value = dateEnd;
|
row.Cell(columnDateEnd).Value = dateEnd;
|
||||||
row.Cell(columnDuration).Value = (dateEnd - dateStart).TotalMinutes;
|
row.Cell(columnDuration).Value = (dateEnd - dateStart).TotalMinutes;
|
||||||
row.Cell(columnDepthStart).Value = detectedOperations[i].DepthStart;
|
row.Cell(columnDepthStart).Value = current.DepthStart;
|
||||||
row.Cell(columnDepthEnd).Value = detectedOperations[i].DepthEnd;
|
row.Cell(columnDepthEnd).Value = current.DepthEnd;
|
||||||
row.Cell(columnDepth).Value = detectedOperations[i].DepthEnd - detectedOperations[i].DepthStart;
|
row.Cell(columnDepth).Value = current.DepthEnd - current.DepthStart;
|
||||||
row.Cell(columnIdReasonOfEnd).Value = detectedOperations[i].IdReasonOfEnd;
|
|
||||||
|
if (current.ExtraData.TryGetValue("IdReasonOfEnd", out object? idReasonOfEndObject)
|
||||||
|
&& idReasonOfEndObject is int idReasonOfEnd)
|
||||||
|
row.Cell(columnIdReasonOfEnd).Value = GetIdReasonOfEnd(idReasonOfEnd);
|
||||||
|
|
||||||
var link =
|
var link =
|
||||||
$"{domains[idDomain]}/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(3544).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=3600";
|
$"{domains[idDomain]}/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(1800 * 0.9).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=1800";
|
||||||
|
|
||||||
row.Cell(columnDateStart).Value = dateStart;
|
row.Cell(columnDateStart).Value = dateStart;
|
||||||
row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link));
|
row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link));
|
||||||
|
|
||||||
row.Cell(columnDeltaDepth).Value = i > 0 && i + 1 < detectedOperations.Count
|
row.Cell(columnDeltaDepth).Value = i > 0 && i + 1 < detectedOperations.Length
|
||||||
? detectedOperations[i].DepthStart - detectedOperations[i - 1].DepthEnd
|
? current.DepthStart - detectedOperations[i - 1].DepthEnd
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
row.Cell(columnComment).Value = CreateComment(operationDetectorResults[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetCategoryName(IEnumerable<WellOperationCategory> wellOperationCategories, DetectedOperation current)
|
||||||
|
{
|
||||||
|
var idCategory = current.IdCategory;
|
||||||
|
if (idCategory == WellOperationCategory.IdSlide
|
||||||
|
&& current.ExtraData[DetectorDrilling.ExtraDataKeyHasOscillation] is bool hasOscillation
|
||||||
|
&& hasOscillation)
|
||||||
|
return "Бурение в слайде с осцилляцией";
|
||||||
|
|
||||||
|
var category = wellOperationCategories.FirstOrDefault(o => o.Id == current.IdCategory);
|
||||||
|
|
||||||
|
if(category is not null)
|
||||||
|
return category.Name;
|
||||||
|
|
||||||
|
return $"Операция №{idCategory}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetIdReasonOfEnd(int idReasonOfEnd)
|
||||||
|
=> idReasonOfEnd switch {
|
||||||
|
0 => "Не определена",
|
||||||
|
1 => "Не определено начало операции",
|
||||||
|
101 => "Разница глубин забоя и положением долота",
|
||||||
|
300 => "Низкое давление",
|
||||||
|
_ => 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()
|
||||||
@ -152,7 +190,28 @@ public class DetectedOperationExportService
|
|||||||
return memoryStream;
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IEnumerable<DetectedOperation>> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin,
|
private static string CreateComment(OperationDetectorResult operationDetectorResult)
|
||||||
|
{
|
||||||
|
var operation = operationDetectorResult.Operation;
|
||||||
|
switch (operation.IdCategory)
|
||||||
|
{
|
||||||
|
case WellOperationCategory.IdRotor:
|
||||||
|
case WellOperationCategory.IdSlide:
|
||||||
|
var comment = "";
|
||||||
|
if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyAvgRotorSpeed, out object? oAvgRotorSpeed))
|
||||||
|
comment += $"Средняя скорость оборотов ротора: {oAvgRotorSpeed}\r\n";
|
||||||
|
|
||||||
|
if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyDispersionOfNormalizedRotorSpeed, out object? oDispersionOfNormalizedRotorSpeed))
|
||||||
|
comment += $"Дисперсия нормированных оборотов ротора: {oDispersionOfNormalizedRotorSpeed}";
|
||||||
|
|
||||||
|
return comment;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<OperationDetectorResult>> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var query = dbContext.TelemetryDataSaub
|
var query = dbContext.TelemetryDataSaub
|
||||||
@ -173,7 +232,7 @@ public class DetectedOperationExportService
|
|||||||
.OrderBy(d => d.DateTime);
|
.OrderBy(d => d.DateTime);
|
||||||
|
|
||||||
var startDate = begin;
|
var startDate = begin;
|
||||||
var detectedOperations = new List<DetectedOperation>(8);
|
var detectedOperationResults = new List<OperationDetectorResult>(8);
|
||||||
DetectedOperation? lastDetectedOperation = null;
|
DetectedOperation? lastDetectedOperation = null;
|
||||||
const int minOperationLength = 5;
|
const int minOperationLength = 5;
|
||||||
const int maxDetectorsInterpolationFrameLength = 30;
|
const int maxDetectorsInterpolationFrameLength = 30;
|
||||||
@ -191,26 +250,21 @@ public class DetectedOperationExportService
|
|||||||
var isDetected = false;
|
var isDetected = false;
|
||||||
var positionBegin = 0;
|
var positionBegin = 0;
|
||||||
var positionEnd = data.Length - gap;
|
var positionEnd = data.Length - gap;
|
||||||
var step = 10;
|
|
||||||
while (positionEnd > positionBegin)
|
while (positionEnd > positionBegin)
|
||||||
{
|
{
|
||||||
step++;
|
|
||||||
foreach (var detector in detectors)
|
foreach (var detector in detectors)
|
||||||
{
|
{
|
||||||
if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result))
|
if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
detectedOperations.Add(result!.Operation);
|
detectedOperationResults.Add(result!);
|
||||||
lastDetectedOperation = result.Operation;
|
lastDetectedOperation = result!.Operation;
|
||||||
isDetected = true;
|
isDetected = true;
|
||||||
step = 1;
|
|
||||||
positionBegin = result.TelemetryEnd;
|
positionBegin = result.TelemetryEnd;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step > 20)
|
positionBegin += 1;
|
||||||
step = 10;
|
|
||||||
positionBegin += step;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDetected)
|
if (isDetected)
|
||||||
@ -219,6 +273,6 @@ public class DetectedOperationExportService
|
|||||||
startDate = data[positionEnd].DateTime;
|
startDate = data[positionEnd].DateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
return detectedOperations;
|
return detectedOperationResults;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -201,7 +201,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
if (well?.IdTelemetry is null || well.Timezone is null)
|
if (well?.IdTelemetry is null || well.Timezone is null)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var query = BuildQuery(well, request);
|
var query = BuildQueryBase(well, request);
|
||||||
|
|
||||||
if (query is null)
|
if (query is null)
|
||||||
return 0;
|
return 0;
|
||||||
@ -232,13 +232,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQueryable<DetectedOperation>? BuildQuery(WellDto well, DetectedOperationRequest request)
|
|
||||||
{
|
|
||||||
if (well?.IdTelemetry is null || well.Timezone is null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
|
private IQueryable<DetectedOperation> BuildQueryBase(WellDto well, DetectedOperationRequest request)
|
||||||
|
{
|
||||||
var query = db.Set<DetectedOperation>()
|
var query = db.Set<DetectedOperation>()
|
||||||
.Include(o => o.OperationCategory)
|
|
||||||
.Where(o => o.IdTelemetry == well.IdTelemetry);
|
.Where(o => o.IdTelemetry == well.IdTelemetry);
|
||||||
|
|
||||||
if (request is not null)
|
if (request is not null)
|
||||||
@ -262,6 +259,14 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
query = query.Where(o => o.IdUsersAtStart == request.EqIdTelemetryUser);
|
query = query.Where(o => o.IdUsersAtStart == request.EqIdTelemetryUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQueryable<DetectedOperation> BuildQuery(WellDto well, DetectedOperationRequest request)
|
||||||
|
{
|
||||||
|
IQueryable<DetectedOperation> query = BuildQueryBase(well, request)
|
||||||
|
.Include(o => o.OperationCategory);
|
||||||
|
|
||||||
if (request?.SortFields?.Any() == true)
|
if (request?.SortFields?.Any() == true)
|
||||||
{
|
{
|
||||||
query = query.SortBy(request.SortFields);
|
query = query.SortBy(request.SortFields);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
{
|
{
|
||||||
|
public abstract class DetectorAbstract
|
||||||
internal abstract class DetectorAbstract
|
|
||||||
{
|
{
|
||||||
private readonly int stepLength = 3;
|
private readonly int stepLength = 3;
|
||||||
|
|
||||||
@ -35,9 +35,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
|
|
||||||
protected const int IdReasonOfEnd_Custom1 = 10_000;
|
protected const int IdReasonOfEnd_Custom1 = 10_000;
|
||||||
|
|
||||||
public abstract Func<DetectableTelemetry[], int, int, int> GetIdOperation { get; }
|
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation,
|
||||||
|
out OperationDetectorResult? result)
|
||||||
public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation, out OperationDetectorResult? result)
|
|
||||||
{
|
{
|
||||||
// Проверка соответствия критерию начала операции
|
// Проверка соответствия критерию начала операции
|
||||||
if (DetectBegin(telemetry, begin, previousOperation))
|
if (DetectBegin(telemetry, begin, previousOperation))
|
||||||
@ -53,83 +52,141 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
|
|
||||||
idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation);
|
idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation);
|
||||||
|
|
||||||
if(idReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo &&
|
|
||||||
!IsValidByWellDepthDoesNotChange(telemetry, begin, positionEnd))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (idReasonOfEnd != IdReasonOfEnd_NotDetected)
|
if (idReasonOfEnd != IdReasonOfEnd_NotDetected)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = null;
|
var (Begin, End) = RefineEdges(telemetry, begin, positionEnd);
|
||||||
result = MakeOperation(idTelemetry, telemetry, begin, positionEnd, idReasonOfEnd);
|
|
||||||
return true;
|
if (!IsValidTelemetryRange(telemetry, Begin, End))
|
||||||
}
|
{
|
||||||
result = null;
|
result = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = MakeOperationDetectorResult(idTelemetry, telemetry, Begin, End, idReasonOfEnd);
|
||||||
|
|
||||||
|
return IsValidOperationDetectorResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual bool IsValidTelemetryRange(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
=> end - begin > 1;
|
||||||
|
|
||||||
|
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, DetectedOperation? previousOperation);
|
protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation);
|
||||||
|
|
||||||
protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
=> DetectBegin(telemetry, position, previousOperation)
|
=> DetectBegin(telemetry, position, previousOperation)
|
||||||
? IdReasonOfEnd_NotDetected
|
? IdReasonOfEnd_NotDetected
|
||||||
: IdReasonOfEnd_NotDetectBegin;
|
: IdReasonOfEnd_NotDetectBegin;
|
||||||
|
|
||||||
private OperationDetectorResult MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, int idReasonOfEnd)
|
private OperationDetectorResult MakeOperationDetectorResult(
|
||||||
|
int idTelemetry,
|
||||||
|
DetectableTelemetry[] telemetry,
|
||||||
|
int begin,
|
||||||
|
int end,
|
||||||
|
int idReasonOfEnd)
|
||||||
{
|
{
|
||||||
var pBegin = telemetry[begin];
|
var operation = MakeDetectedOperation(idTelemetry, telemetry, begin, end);
|
||||||
var pEnd = telemetry[end];
|
|
||||||
|
operation.ExtraData["IdReasonOfEnd"] = idReasonOfEnd;
|
||||||
|
|
||||||
var result = new OperationDetectorResult
|
var result = new OperationDetectorResult
|
||||||
{
|
{
|
||||||
TelemetryBegin = begin,
|
TelemetryBegin = begin,
|
||||||
TelemetryEnd = end,
|
TelemetryEnd = end,
|
||||||
Operation = new DetectedOperation
|
Operation = operation,
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DetectedOperation 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 DetectedOperation
|
||||||
|
{
|
||||||
|
IdCategory = IdCategory,
|
||||||
IdTelemetry = idTelemetry,
|
IdTelemetry = idTelemetry,
|
||||||
IdCategory = GetIdOperation.Invoke(telemetry, begin, end),
|
|
||||||
IdUsersAtStart = pBegin.IdUser ?? -1,
|
IdUsersAtStart = pBegin.IdUser ?? -1,
|
||||||
DateStart = pBegin.DateTime,
|
DateStart = pBegin.DateTime,
|
||||||
DateEnd = pEnd.DateTime,
|
DateEnd = pEnd.DateTime,
|
||||||
DepthStart = (double)pBegin.WellDepth,
|
DepthStart = (double)pBegin.WellDepth,
|
||||||
DepthEnd = (double)pEnd.WellDepth,
|
DepthEnd = (double)pEnd.WellDepth,
|
||||||
|
ExtraData = ExtraData,
|
||||||
Value = CalcValue(telemetry, begin, end),
|
Value = CalcValue(telemetry, begin, end),
|
||||||
IdReasonOfEnd = idReasonOfEnd,
|
EnabledSubsystems = DetectEnabledSubsystems(telemetry, begin, end)
|
||||||
},
|
|
||||||
};
|
};
|
||||||
return result;
|
|
||||||
|
return operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract bool IsValid(DetectableTelemetry[] telemetry, int begin, int end);
|
/// <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);
|
protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Среднее арифметическое
|
/// Определение включенных подсистем во время выполнения операции
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="yGetter"></param>
|
|
||||||
/// <param name="telemetry"></param>
|
/// <param name="telemetry"></param>
|
||||||
/// <param name="begin"></param>
|
/// <param name="begin"></param>
|
||||||
/// <param name="fragmentLength"></param>
|
/// <param name="end"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static double CalcAvgAppr(
|
private static int DetectEnabledSubsystems(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
Func<DetectableTelemetry, double> yGetter,
|
|
||||||
DetectableTelemetry[] telemetry,
|
|
||||||
int begin,
|
|
||||||
int fragmentLength)
|
|
||||||
{
|
{
|
||||||
var end = begin + fragmentLength;
|
var enabledSubsystems = 0;
|
||||||
end = end < telemetry.Length
|
|
||||||
? end
|
for (var i = begin; i < end; i += 2)
|
||||||
: telemetry.Length;
|
|
||||||
var subData = telemetry[begin..end].Select(yGetter);
|
|
||||||
if (end - begin > 10)
|
|
||||||
{
|
{
|
||||||
var ratio = (end - begin) / 5;
|
var mode = telemetry[i].Mode;
|
||||||
subData = subData.Where((_,i) => i % ratio > 0);
|
|
||||||
|
if(mode == 1)
|
||||||
|
enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoRotor;
|
||||||
|
|
||||||
|
if (mode == 3)
|
||||||
|
enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoSlide;
|
||||||
|
|
||||||
|
if (mode == 2)
|
||||||
|
enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoConditionig;
|
||||||
|
|
||||||
|
if (mode == 4)
|
||||||
|
enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoSinking;
|
||||||
|
|
||||||
|
if (mode == 5)
|
||||||
|
enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoLifting;
|
||||||
|
|
||||||
|
if (mode == 6)
|
||||||
|
enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoLiftingWithConditionig;
|
||||||
|
|
||||||
|
if (mode == 10)
|
||||||
|
enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoBlocknig;
|
||||||
}
|
}
|
||||||
|
|
||||||
var avg = subData.Average();
|
return enabledSubsystems;
|
||||||
return avg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -210,6 +267,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
max = itemValue;
|
max = itemValue;
|
||||||
sum += itemValue;
|
sum += itemValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (min, max, sum, end - begin);
|
return (min, max, sum, end - begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +314,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
var end = begin + count;
|
var end = begin + count;
|
||||||
end = end < telemetry.Length ? end : telemetry.Length;
|
end = end < telemetry.Length ? end : telemetry.Length;
|
||||||
|
|
||||||
for (var i = begin; i < end; i ++)
|
for (var i = begin; i < end; i++)
|
||||||
{
|
{
|
||||||
var item = telemetry[i];
|
var item = telemetry[i];
|
||||||
var itemValue = getter(item);
|
var itemValue = getter(item);
|
||||||
@ -264,9 +322,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
min = itemValue;
|
min = itemValue;
|
||||||
if (max < itemValue)
|
if (max < itemValue)
|
||||||
max = itemValue;
|
max = itemValue;
|
||||||
if(max - min > deviation)
|
if (max - min > deviation)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,8 +349,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
var max = double.MinValue;
|
var max = double.MinValue;
|
||||||
var end = begin + count;
|
var end = begin + count;
|
||||||
end = end < telemetry.Length ? end : telemetry.Length;
|
end = end < telemetry.Length ? end : telemetry.Length;
|
||||||
var step = count > 15 ? count / 5 : count > 3 ? 3: 1;
|
var step = count > 15 ? count / 5 : count > 3 ? 3 : 1;
|
||||||
for (var i = begin; i < end; i+= step)
|
for (var i = begin; i < end; i += step)
|
||||||
{
|
{
|
||||||
var item = telemetry[i];
|
var item = telemetry[i];
|
||||||
var itemValue = getter(item);
|
var itemValue = getter(item);
|
||||||
@ -302,6 +361,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
if (max - min > deviation)
|
if (max - min > deviation)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,6 +383,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
if (Math.Abs(beginPointValue - itemValue) > deviation)
|
if (Math.Abs(beginPointValue - itemValue) > deviation)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,13 +402,12 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
{
|
{
|
||||||
var item = telemetry[i];
|
var item = telemetry[i];
|
||||||
var itemValue = getter(item);
|
var itemValue = getter(item);
|
||||||
if ( itemValue - beginPointValue > deviation)
|
if (itemValue - beginPointValue > deviation)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,68 +1,66 @@
|
|||||||
using System;
|
// using System;
|
||||||
using AsbCloudDb.Model;
|
// using AsbCloudDb.Model;
|
||||||
|
//
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
{
|
// {
|
||||||
|
//
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// Проработка перед наращиванием
|
// /// Проработка перед наращиванием
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
internal class DetectorDevelopment : DetectorAbstract
|
// internal class DetectorDevelopment : DetectorAbstract
|
||||||
{
|
// {
|
||||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
// => CalcDeltaMinutes(telemetry, begin, end);
|
||||||
|
//
|
||||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _)
|
// public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _)
|
||||||
=> WellOperationCategory.IdDevelopment;
|
// => WellOperationCategory.IdDevelopment;
|
||||||
|
//
|
||||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
{
|
// {
|
||||||
if (previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime)
|
// if (previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime)
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
var point0 = telemetry[position];
|
// var point0 = telemetry[position];
|
||||||
var delta = point0.WellDepth - point0.BitDepth;
|
// var delta = point0.WellDepth - point0.BitDepth;
|
||||||
if (delta < 0.03d || delta > 30)
|
// if (delta < 0.03d || delta > 30)
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
if (point0.Pressure < 15)
|
// if (point0.Pressure < 15)
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
if (point0.BlockPosition > 2.5)
|
// if (point0.BlockPosition > 2.5)
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
if (point0.RotorSpeed < 10)
|
// if (point0.RotorSpeed < 10)
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
if (!ContainsDeviationApprox(telemetry, d => d.BlockPosition, position, 60, 0.03))
|
// if (!ContainsDeviationApprox(telemetry, d => d.BlockPosition, position, 60, 0.03))
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
{
|
// {
|
||||||
var point0 = telemetry[position];
|
// var point0 = telemetry[position];
|
||||||
var delta = point0.WellDepth - point0.BitDepth;
|
// var delta = point0.WellDepth - point0.BitDepth;
|
||||||
if (delta < 0.03d || delta > 30)
|
// if (delta < 0.03d || delta > 30)
|
||||||
return IdReasonOfEnd_DeltaDepthOutOfRange;
|
// return IdReasonOfEnd_DeltaDepthOutOfRange;
|
||||||
|
//
|
||||||
if (point0.Pressure < 15)
|
// if (point0.Pressure < 15)
|
||||||
return IdReasonOfEnd_PressureIsLo;
|
// return IdReasonOfEnd_PressureIsLo;
|
||||||
|
//
|
||||||
if (point0.BlockPosition > 31)
|
// if (point0.BlockPosition > 31)
|
||||||
return IdReasonOfEnd_BlockPositionIsHi;
|
// return IdReasonOfEnd_BlockPositionIsHi;
|
||||||
|
//
|
||||||
if (point0.RotorSpeed < 10)
|
// if (point0.RotorSpeed < 10)
|
||||||
return IdReasonOfEnd_RotorSpeedIsLo;
|
// return IdReasonOfEnd_RotorSpeedIsLo;
|
||||||
|
//
|
||||||
return IdReasonOfEnd_NotDetected;
|
// return IdReasonOfEnd_NotDetected;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
// => IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
|
|
||||||
internal class DetectorDrilling : DetectorAbstract
|
public class DetectorDrilling : DetectorAbstract
|
||||||
{
|
{
|
||||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => DefineDrillingOperation;
|
private const double dispersionOfNormalizedRotorSpeedThreshold = 0.2d;
|
||||||
|
public const string ExtraDataKeyHasOscillation = "hasOscillation";
|
||||||
|
public const string ExtraDataKeyDispersionOfNormalizedRotorSpeed = "dispersionOfNormalizedRotorSpeed";
|
||||||
|
public const string ExtraDataKeyAvgRotorSpeed = "avgRotorSpeed";
|
||||||
|
|
||||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
{
|
{
|
||||||
@ -15,10 +20,7 @@ internal class DetectorDrilling : DetectorAbstract
|
|||||||
if (delta > 0.03d)
|
if (delta > 0.03d)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (point0.Pressure < 25)
|
if (point0.Pressure < 18)
|
||||||
return false;
|
|
||||||
|
|
||||||
if (point0.RotorSpeed < 5)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -32,32 +34,61 @@ internal class DetectorDrilling : DetectorAbstract
|
|||||||
if (delta > 0.03d)
|
if (delta > 0.03d)
|
||||||
return IdReasonOfEnd_DeltaDepthIsHi;
|
return IdReasonOfEnd_DeltaDepthIsHi;
|
||||||
|
|
||||||
if (point0.Pressure < 25)
|
if (point0.Pressure < 18)
|
||||||
return IdReasonOfEnd_PressureIsLo;
|
return IdReasonOfEnd_PressureIsLo;
|
||||||
|
|
||||||
return IdReasonOfEnd_NotDetected;
|
return IdReasonOfEnd_NotDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
|
||||||
=> IsValidByWellDepthIncreasing(telemetry, begin, end);
|
|
||||||
|
|
||||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
=> CalcRop(telemetry, begin, end);
|
=> CalcRop(telemetry, begin, end);
|
||||||
|
|
||||||
private static int DefineDrillingOperation(DetectableTelemetry[] telemetry, int begin, int end)
|
protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) =>
|
||||||
|
base.IsValidOperationDetectorResult(operationDetectorResult)
|
||||||
|
&& (operationDetectorResult.Operation.DepthEnd - operationDetectorResult.Operation.DepthStart) > 0.01;
|
||||||
|
|
||||||
|
protected override (int Begin, int End) RefineEdges(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
{
|
{
|
||||||
const int idSlideWithOscillation = 12000;
|
var i = end;
|
||||||
|
for (; i > begin + 1; i--)
|
||||||
|
if (telemetry[i].WellDepth - telemetry[i - 1].WellDepth > 0.001d)
|
||||||
|
break;
|
||||||
|
|
||||||
var telemetryRange = telemetry[begin.. end];
|
return (begin, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override (int IdCategory, IDictionary<string, object> ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed) = CalcCriteries(telemetry, begin, end);
|
||||||
|
var idCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed);
|
||||||
|
var extraData = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
[ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed,
|
||||||
|
[ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed,
|
||||||
|
[ExtraDataKeyHasOscillation] = dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold
|
||||||
|
};
|
||||||
|
return (idCategory, extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
|
{
|
||||||
|
var telemetryRange = telemetry[begin..end];
|
||||||
var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed);
|
var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed);
|
||||||
|
var dispersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed / avgRotorSpeed - 1, 2));
|
||||||
|
return (avgRotorSpeed, dispersion);
|
||||||
|
}
|
||||||
|
|
||||||
if (avgRotorSpeed < 10)
|
private static int GetIdOperation(double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed)
|
||||||
|
{
|
||||||
|
const int idSlideWithOscillation = WellOperationCategory.IdSlide;
|
||||||
|
|
||||||
|
if (avgRotorSpeed < 5)
|
||||||
return WellOperationCategory.IdSlide;
|
return WellOperationCategory.IdSlide;
|
||||||
|
|
||||||
var despersion = telemetryRange
|
if (dispersionOfNormalizedRotorSpeed < dispersionOfNormalizedRotorSpeedThreshold)
|
||||||
.Average(t => Math.Pow((t.RotorSpeed - avgRotorSpeed) / avgRotorSpeed, 2));
|
return WellOperationCategory.IdRotor;
|
||||||
|
else
|
||||||
return despersion < 0.2d ? WellOperationCategory.IdRotor : idSlideWithOscillation;
|
return idSlideWithOscillation;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,16 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
{
|
|
||||||
|
|
||||||
internal class DetectorSlipsTime : DetectorAbstract
|
public class DetectorSlipsTime : DetectorAbstract
|
||||||
{
|
{
|
||||||
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
=> CalcDeltaMinutes(telemetry, begin, end);
|
=> CalcDeltaMinutes(telemetry, begin, end);
|
||||||
|
|
||||||
public override Func<DetectableTelemetry[], int, int, int> GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime;
|
|
||||||
|
|
||||||
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
|
||||||
{
|
{
|
||||||
var point0 = telemetry[position];
|
var point0 = telemetry[position];
|
||||||
@ -30,10 +28,12 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end)
|
protected override (int IdCategory, IDictionary<string, object> ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end)
|
||||||
=> IsValidByWellDepthDoesNotChange(telemetry, begin, end);
|
{
|
||||||
|
return (WellOperationCategory.IdSlipsTime, new Dictionary<string, object>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) =>
|
||||||
|
Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,29 +1,27 @@
|
|||||||
Метод определения бурения
|
# Алгоритм определения бурения в роторе, слайде, слайде с осцилляцией
|
||||||
|
|
||||||
Признак начала операции =
|
## Метод определения операции бурения
|
||||||
|
|
||||||
расстояние от долота до забоя < 0.03м И
|
Признак начала операции =
|
||||||
|
(расстояние от долота до забоя < 0.03м) И
|
||||||
|
(давление > 18атм)
|
||||||
|
|
||||||
давление > 25атм
|
Признак окончания операции =
|
||||||
|
(расстояние от долота до забоя > 0.03м) ИЛИ
|
||||||
|
(давление < 18атм)
|
||||||
|
|
||||||
Признак окончания операции =
|
## Валидация
|
||||||
|
Для точного определения операции бурения, необходимо убрать диапазон в которых сработал признак окончания операции и не менялась глубина:
|
||||||
|
Определили точку окончания операции исходя из Признак окончания операции.
|
||||||
|
Определяем временной интервал, когда не менялась глубина (т.е. время шло, а глубина была неизменна)
|
||||||
|
Определив начальную точку и точку окончания операции
|
||||||
|
Исключаем этот интервал из операции.
|
||||||
|
|
||||||
расстояние от долота до забоя > 0.03м ИЛИ
|
## Метод определения бурения в слайде
|
||||||
|
Необходимо рассчитать средние обороты ротора за всю операцию бурения.
|
||||||
|
Если среднее арифметическое больше константы (5 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде.
|
||||||
|
|
||||||
давление < 25атм
|
## Метод определения бурения в роторе, слайде с осцилляцией
|
||||||
|
Необходимо рассчитать десперсию нормированных оборотов ротора по(по среднему значению)
|
||||||
Находим границы
|
1. Если полученное значение больше константы(0,2), то мы подтвердили что бурение в роторе.
|
||||||
|
2. Если полученное значение меньше константы, то это бурение в слайде с осцилляцией.
|
||||||
После того когда мы нашли границы, мы должны определить операцию, тогда мы смотрим на забой точки окончания операций сравниваем с забоем точками начала операций:
|
|
||||||
|
|
||||||
Если они равны друг другу, то мы эту операцию дальше не обрабатываем, а выбрасываем.
|
|
||||||
|
|
||||||
Если они не равны, то у нас произошло увеличение забоя, значит эта операция бурения.
|
|
||||||
|
|
||||||
Дальше мы определяем как мы бурили в роторе или слайде, для этого нам необходимо рассчитать среднюю скорость(среднее арифметическое) за всю операцию бурения . Если среднее арифметическое больше константы (10 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде.
|
|
||||||
|
|
||||||
Если бурение в роторе, то мы считаем только дисперсию нормированных оборотов ротора(по среднему значению). (Так как это может быть бурение в слайде с осцилляцией и выглядеть как бурение в роторе):
|
|
||||||
|
|
||||||
Если полученное значение меньше константы(0,2), то мы подтвердили что бурение в роторе.
|
|
||||||
|
|
||||||
Если полученное значение больше константы, то это бурение в слайде с осцилляцией.
|
|
@ -16,11 +16,12 @@ public class WorkOperationDetection: Work
|
|||||||
{
|
{
|
||||||
private static readonly DetectorAbstract[] detectors = new DetectorAbstract[]
|
private static readonly DetectorAbstract[] detectors = new DetectorAbstract[]
|
||||||
{
|
{
|
||||||
|
new DetectorDrilling(),
|
||||||
|
new DetectorSlipsTime()
|
||||||
// new DetectorRotor(),
|
// new DetectorRotor(),
|
||||||
// new DetectorSlide(),
|
// new DetectorSlide(),
|
||||||
//new DetectorDevelopment(),
|
//new DetectorDevelopment(),
|
||||||
//new DetectorTemplating(),
|
//new DetectorTemplating(),
|
||||||
new DetectorSlipsTime(),
|
|
||||||
//new DetectorStaticSurveying(),
|
//new DetectorStaticSurveying(),
|
||||||
//new DetectorFlashingBeforeConnection(),
|
//new DetectorFlashingBeforeConnection(),
|
||||||
//new DetectorFlashing(),
|
//new DetectorFlashing(),
|
||||||
@ -95,6 +96,7 @@ public class WorkOperationDetection: Work
|
|||||||
{
|
{
|
||||||
DateTime = d.DateTime,
|
DateTime = d.DateTime,
|
||||||
IdUser = d.IdUser,
|
IdUser = d.IdUser,
|
||||||
|
Mode = d.Mode,
|
||||||
WellDepth = d.WellDepth,
|
WellDepth = d.WellDepth,
|
||||||
Pressure = d.Pressure,
|
Pressure = d.Pressure,
|
||||||
HookWeight = d.HookWeight,
|
HookWeight = d.HookWeight,
|
||||||
@ -125,25 +127,21 @@ public class WorkOperationDetection: Work
|
|||||||
var isDetected = false;
|
var isDetected = false;
|
||||||
var positionBegin = 0;
|
var positionBegin = 0;
|
||||||
var positionEnd = data.Length - gap;
|
var positionEnd = data.Length - gap;
|
||||||
var step = 10;
|
|
||||||
while (positionEnd > positionBegin)
|
while (positionEnd > positionBegin)
|
||||||
{
|
{
|
||||||
step ++;
|
foreach (var detector in detectors)
|
||||||
for (int i = 0; i < detectors.Length; i++)
|
|
||||||
{
|
|
||||||
if (detectors[i].TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out OperationDetectorResult? result))
|
|
||||||
{
|
{
|
||||||
|
if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result))
|
||||||
|
continue;
|
||||||
|
|
||||||
detectedOperations.Add(result!.Operation);
|
detectedOperations.Add(result!.Operation);
|
||||||
lastDetectedOperation = result.Operation;
|
lastDetectedOperation = result.Operation;
|
||||||
isDetected = true;
|
isDetected = true;
|
||||||
step = 1;
|
|
||||||
positionBegin = result.TelemetryEnd;
|
positionBegin = result.TelemetryEnd;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (step > 20)
|
positionBegin += 1;
|
||||||
step = 10;
|
|
||||||
positionBegin += step;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDetected)
|
if (isDetected)
|
||||||
|
@ -13,11 +13,10 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services
|
namespace AsbCloudInfrastructure.Services;
|
||||||
{
|
|
||||||
|
|
||||||
public class ReportService : IReportService
|
public class ReportService : IReportService
|
||||||
{
|
{
|
||||||
private readonly IAsbCloudDbContext db;
|
private readonly IAsbCloudDbContext db;
|
||||||
private readonly ITelemetryService telemetryService;
|
private readonly ITelemetryService telemetryService;
|
||||||
private readonly FileService fileService;
|
private readonly FileService fileService;
|
||||||
@ -98,6 +97,17 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
};
|
};
|
||||||
|
|
||||||
var work = Work.CreateByDelegate(workId, workAction);
|
var work = Work.CreateByDelegate(workId, workAction);
|
||||||
|
work.OnErrorAsync = (message, exception, token) => Task.Run(() => progressHandler.Invoke(new
|
||||||
|
{
|
||||||
|
Operation = "error",
|
||||||
|
Progress = 100f,
|
||||||
|
Message = string.IsNullOrEmpty(message)
|
||||||
|
? exception.Message
|
||||||
|
: message,
|
||||||
|
Exception = exception,
|
||||||
|
}, workId)
|
||||||
|
, token);
|
||||||
|
|
||||||
backgroundWorkerService.Enqueue(work);
|
backgroundWorkerService.Enqueue(work);
|
||||||
|
|
||||||
progressHandler.Invoke(new ReportProgressDto
|
progressHandler.Invoke(new ReportProgressDto
|
||||||
@ -200,5 +210,4 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
|
|
||||||
return await fileService.DeleteAsync(fileIds, token);
|
return await fileService.DeleteAsync(fileIds, token);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
if ((DateTimeOffset.UtcNow - geDate) < TimeSpan.FromHours(12))
|
if ((DateTimeOffset.UtcNow - geDate) < TimeSpan.FromHours(12))
|
||||||
{
|
{
|
||||||
// пробуем обойтись кешем
|
// пробуем обойтись кешем
|
||||||
var cechedRange = telemetryDataCache.GetOrDefaultCachedaDateRange(telemetry.Id);
|
var cechedRange = telemetryDataCache.GetOrDefaultCachedDateRange(telemetry.Id);
|
||||||
if (cechedRange?.From <= geDate)
|
if (cechedRange?.From <= geDate)
|
||||||
{
|
{
|
||||||
var datesRange = new DatesRangeDto
|
var datesRange = new DatesRangeDto
|
||||||
|
@ -20,7 +20,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
class TelemetryDataCacheItem
|
class TelemetryDataCacheItem
|
||||||
{
|
{
|
||||||
public TDto FirstByDate { get; init; } = default!;
|
public TDto FirstByDate { get; init; } = default!;
|
||||||
public CyclycArray<TDto> LastData { get; init; } = null!;
|
public CyclicArray<TDto> LastData { get; init; } = null!;
|
||||||
public double TimezoneHours { get; init; } = 5;
|
public double TimezoneHours { get; init; } = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
cacheItem = caches.GetOrAdd(idTelemetry, _ => new TelemetryDataCacheItem()
|
cacheItem = caches.GetOrAdd(idTelemetry, _ => new TelemetryDataCacheItem()
|
||||||
{
|
{
|
||||||
FirstByDate = range.ElementAt(0),
|
FirstByDate = range.ElementAt(0),
|
||||||
LastData = new CyclycArray<TDto>(activeWellCapacity)
|
LastData = new CyclicArray<TDto>(activeWellCapacity)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return new DatesRangeDto { From = from.Value, To = to };
|
return new DatesRangeDto { From = from.Value, To = to };
|
||||||
}
|
}
|
||||||
|
|
||||||
public DatesRangeDto? GetOrDefaultCachedaDateRange(int idTelemetry)
|
public DatesRangeDto? GetOrDefaultCachedDateRange(int idTelemetry)
|
||||||
{
|
{
|
||||||
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
|
if (!caches.TryGetValue(idTelemetry, out TelemetryDataCacheItem? cacheItem))
|
||||||
return null;
|
return null;
|
||||||
@ -260,7 +260,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return dto;
|
return dto;
|
||||||
});
|
});
|
||||||
|
|
||||||
var cacheItem = new CyclycArray<TDto>(capacity);
|
var cacheItem = new CyclicArray<TDto>(capacity);
|
||||||
cacheItem.AddRange(dtos);
|
cacheItem.AddRange(dtos);
|
||||||
|
|
||||||
var item = new TelemetryDataCacheItem
|
var item = new TelemetryDataCacheItem
|
||||||
|
@ -43,7 +43,6 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
.Where(t => t.IdTelemetry == idTelemetry)
|
.Where(t => t.IdTelemetry == idTelemetry)
|
||||||
.Where(t => t.BlockPosition > 0.0001)
|
.Where(t => t.BlockPosition > 0.0001)
|
||||||
.Where(t => t.WellDepth > 0.0001)
|
.Where(t => t.WellDepth > 0.0001)
|
||||||
.Where(t => t.Mode != null)
|
|
||||||
.Where(t => modes.Contains(t.Mode))
|
.Where(t => modes.Contains(t.Mode))
|
||||||
.Where(t => t.WellDepth - t.BitDepth < 0.01)
|
.Where(t => t.WellDepth - t.BitDepth < 0.01)
|
||||||
.GroupBy(t => new {
|
.GroupBy(t => new {
|
||||||
|
@ -13,7 +13,7 @@ abstract class TrajectoryBaseService<TGeo, TCartesian>
|
|||||||
where TGeo : TrajectoryGeoDto
|
where TGeo : TrajectoryGeoDto
|
||||||
where TCartesian : TrajectoryCartesianDto, new()
|
where TCartesian : TrajectoryCartesianDto, new()
|
||||||
{
|
{
|
||||||
ITrajectoryRepository<TGeo> repository;
|
private readonly ITrajectoryRepository<TGeo> repository;
|
||||||
|
|
||||||
public TrajectoryBaseService(ITrajectoryRepository<TGeo> repository)
|
public TrajectoryBaseService(ITrajectoryRepository<TGeo> repository)
|
||||||
{
|
{
|
||||||
@ -31,16 +31,16 @@ abstract class TrajectoryBaseService<TGeo, TCartesian>
|
|||||||
public async Task<IEnumerable<TCartesian>?> GetAsync(int idWell, CancellationToken token)
|
public async Task<IEnumerable<TCartesian>?> GetAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var geoCoords = await repository.GetAsync(idWell, token);
|
var geoCoords = await repository.GetAsync(idWell, token);
|
||||||
var locs = GetTrajectoryVisualisation(geoCoords);
|
var locs = TrajectoryBaseService<TGeo, TCartesian>.GetTrajectoryVisualisation(geoCoords);
|
||||||
var dtos = locs.Select(l => Convert(l));
|
var dtos = locs.Select(l => Convert(l));
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<Location> GetTrajectoryVisualisation(IEnumerable<TrajectoryGeoDto> geoCoordinates)
|
private static IEnumerable<Location> GetTrajectoryVisualisation(IEnumerable<TrajectoryGeoDto> geoCoordinates)
|
||||||
{
|
{
|
||||||
var geoCoordinatesLength = geoCoordinates.Count();
|
var geoCoordinatesLength = geoCoordinates.Count();
|
||||||
if (geoCoordinatesLength < 2)
|
if (geoCoordinatesLength < 2)
|
||||||
return new Location[0];
|
return Enumerable.Empty<Location>();
|
||||||
|
|
||||||
var cartesianCoordinates = new Location[geoCoordinatesLength];
|
var cartesianCoordinates = new Location[geoCoordinatesLength];
|
||||||
cartesianCoordinates[0] = new();
|
cartesianCoordinates[0] = new();
|
||||||
@ -48,7 +48,7 @@ abstract class TrajectoryBaseService<TGeo, TCartesian>
|
|||||||
var geoCoordinatesArray = geoCoordinates.OrderBy(c => c.WellboreDepth).ToArray();
|
var geoCoordinatesArray = geoCoordinates.OrderBy(c => c.WellboreDepth).ToArray();
|
||||||
for (var i = 1; i < geoCoordinatesLength; i++)
|
for (var i = 1; i < geoCoordinatesLength; i++)
|
||||||
{
|
{
|
||||||
var coordinates = Calculate(cartesianCoordinates[i - 1],
|
var coordinates = TrajectoryBaseService<TGeo, TCartesian>.Calculate(cartesianCoordinates[i - 1],
|
||||||
geoCoordinatesArray[i - 1],
|
geoCoordinatesArray[i - 1],
|
||||||
geoCoordinatesArray[i]);
|
geoCoordinatesArray[i]);
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ abstract class TrajectoryBaseService<TGeo, TCartesian>
|
|||||||
return cartesianCoordinates;
|
return cartesianCoordinates;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Location Calculate(Location prevlocation, TrajectoryGeoDto prev, TrajectoryGeoDto current)
|
protected static Location Calculate(Location prevLocation, TrajectoryGeoDto prev, TrajectoryGeoDto current)
|
||||||
{
|
{
|
||||||
var intervalGeoParams = prev;
|
var intervalGeoParams = prev;
|
||||||
var deltaWellLength = current.WellboreDepth - intervalGeoParams.WellboreDepth;
|
var deltaWellLength = current.WellboreDepth - intervalGeoParams.WellboreDepth;
|
||||||
@ -70,9 +70,9 @@ abstract class TrajectoryBaseService<TGeo, TCartesian>
|
|||||||
|
|
||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
North = prevlocation.North + dNorth,
|
North = prevLocation.North + dNorth,
|
||||||
East = prevlocation.East + dEast,
|
East = prevLocation.East + dEast,
|
||||||
Depth = prevlocation.Depth + dDepth,
|
Depth = prevLocation.Depth + dDepth,
|
||||||
Trajectory = current,
|
Trajectory = current,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -125,9 +125,9 @@ class TrajectoryNnbService : TrajectoryBaseService<TrajectoryGeoFactDto, Traject
|
|||||||
|
|
||||||
public class TrajectoryService
|
public class TrajectoryService
|
||||||
{
|
{
|
||||||
private TrajectoryPlanService trajectoryPlanService;
|
private readonly TrajectoryPlanService trajectoryPlanService;
|
||||||
private TrajectoryFactService trajectoryFactService;
|
private readonly TrajectoryFactService trajectoryFactService;
|
||||||
private TrajectoryNnbService trajectoryNnbService;
|
private readonly TrajectoryNnbService trajectoryNnbService;
|
||||||
|
|
||||||
public TrajectoryService(
|
public TrajectoryService(
|
||||||
ITrajectoryEditableRepository<TrajectoryGeoPlanDto> planRepository,
|
ITrajectoryEditableRepository<TrajectoryGeoPlanDto> planRepository,
|
||||||
@ -147,11 +147,12 @@ public class TrajectoryService
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<TrajectoryPlanFactDto<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>> GetTrajectoryCartesianAsync(int idWell, CancellationToken token)
|
public async Task<TrajectoryPlanFactDto<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>> GetTrajectoryCartesianAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = new TrajectoryPlanFactDto<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>();
|
var result = new TrajectoryPlanFactDto<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>
|
||||||
|
{
|
||||||
result.Plan = await trajectoryPlanService.GetAsync(idWell, token);
|
Plan = await trajectoryPlanService.GetAsync(idWell, token),
|
||||||
result.FactManual = await trajectoryFactService.GetAsync(idWell, token);
|
FactManual = await trajectoryFactService.GetAsync(idWell, token),
|
||||||
result.FactNnb = await trajectoryNnbService.GetAsync(idWell, token);
|
FactNnb = await trajectoryNnbService.GetAsync(idWell, token)
|
||||||
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,6 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository;
|
private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository;
|
||||||
private readonly NotificationService notificationService;
|
private readonly NotificationService notificationService;
|
||||||
|
|
||||||
private const int FileServiceThrewException = -1;
|
|
||||||
|
|
||||||
public WellFinalDocumentsService(FileService fileService,
|
public WellFinalDocumentsService(FileService fileService,
|
||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
IWellService wellService,
|
IWellService wellService,
|
||||||
@ -48,7 +46,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
///<inheritdoc/>
|
///<inheritdoc/>
|
||||||
public async Task<int> UpdateRangeAsync(int idWell, IEnumerable<WellFinalDocumentInputDto>? dtos, CancellationToken token)
|
public async Task<int> UpdateRangeAsync(int idWell, IEnumerable<WellFinalDocumentInputDto> dtos, CancellationToken token)
|
||||||
{
|
{
|
||||||
var data = await wellFinalDocumentsRepository.UpdateRangeAsync(idWell, dtos, token);
|
var data = await wellFinalDocumentsRepository.UpdateRangeAsync(idWell, dtos, token);
|
||||||
|
|
||||||
|
@ -38,16 +38,15 @@ public class WellOperationExportService : IWellOperationExportService
|
|||||||
|
|
||||||
var timezone = wellService.GetTimezone(idWell);
|
var timezone = wellService.GetTimezone(idWell);
|
||||||
|
|
||||||
return await MakeExcelFileStreamAsync(operations, timezone.Hours, cancellationToken);
|
return MakeExcelFileStream(operations, timezone.Hours);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Stream> MakeExcelFileStreamAsync(IEnumerable<WellOperationDto> operations, double timezoneOffset,
|
private Stream MakeExcelFileStream(IEnumerable<WellOperationDto> operations, double timezoneOffset)
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
using Stream ecxelTemplateStream = wellOperationImportTemplateService.GetExcelTemplateStream();
|
using Stream ecxelTemplateStream = wellOperationImportTemplateService.GetExcelTemplateStream();
|
||||||
|
|
||||||
using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled);
|
using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled);
|
||||||
await AddOperationsToWorkbook(workbook, operations, timezoneOffset, cancellationToken);
|
AddOperationsToWorkbook(workbook, operations, timezoneOffset);
|
||||||
|
|
||||||
var memoryStream = new MemoryStream();
|
var memoryStream = new MemoryStream();
|
||||||
workbook.SaveAs(memoryStream, new SaveOptions { });
|
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||||
@ -55,15 +54,14 @@ public class WellOperationExportService : IWellOperationExportService
|
|||||||
return memoryStream;
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddOperationsToWorkbook(XLWorkbook workbook, IEnumerable<WellOperationDto> operations, double timezoneOffset,
|
private void AddOperationsToWorkbook(XLWorkbook workbook, IEnumerable<WellOperationDto> operations, double timezoneOffset)
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
var planOperations = operations.Where(o => o.IdType == 0);
|
var planOperations = operations.Where(o => o.IdType == 0);
|
||||||
if (planOperations.Any())
|
if (planOperations.Any())
|
||||||
{
|
{
|
||||||
var sheetPlan = workbook.Worksheets.FirstOrDefault(ws => ws.Name == DefaultTemplateInfo.SheetNamePlan);
|
var sheetPlan = workbook.Worksheets.FirstOrDefault(ws => ws.Name == DefaultTemplateInfo.SheetNamePlan);
|
||||||
if (sheetPlan is not null)
|
if (sheetPlan is not null)
|
||||||
await AddOperationsToSheetAsync(sheetPlan, planOperations, timezoneOffset, cancellationToken);
|
AddOperationsToSheet(sheetPlan, planOperations, timezoneOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
var factOperations = operations.Where(o => o.IdType == 1);
|
var factOperations = operations.Where(o => o.IdType == 1);
|
||||||
@ -71,12 +69,11 @@ public class WellOperationExportService : IWellOperationExportService
|
|||||||
{
|
{
|
||||||
var sheetFact = workbook.Worksheets.FirstOrDefault(ws => ws.Name == DefaultTemplateInfo.SheetNameFact);
|
var sheetFact = workbook.Worksheets.FirstOrDefault(ws => ws.Name == DefaultTemplateInfo.SheetNameFact);
|
||||||
if (sheetFact is not null)
|
if (sheetFact is not null)
|
||||||
await AddOperationsToSheetAsync(sheetFact, factOperations, timezoneOffset, cancellationToken);
|
AddOperationsToSheet(sheetFact, factOperations, timezoneOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddOperationsToSheetAsync(IXLWorksheet sheet, IEnumerable<WellOperationDto> operations, double timezoneOffset,
|
private void AddOperationsToSheet(IXLWorksheet sheet, IEnumerable<WellOperationDto> operations, double timezoneOffset)
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
var operationsToArray = operations.ToArray();
|
var operationsToArray = operations.ToArray();
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace AsbCloudInfrastructure
|
|||||||
var provider = scope.ServiceProvider;
|
var provider = scope.ServiceProvider;
|
||||||
|
|
||||||
var context = provider.GetRequiredService<IAsbCloudDbContext>();
|
var context = provider.GetRequiredService<IAsbCloudDbContext>();
|
||||||
context.Database.EnshureCreatedAndMigrated();
|
context.Database.EnsureCreatedAndMigrated();
|
||||||
|
|
||||||
// TODO: Сделать инициализацию кеша телеметрии более явной.
|
// TODO: Сделать инициализацию кеша телеметрии более явной.
|
||||||
_ = provider.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
_ = provider.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
||||||
|
@ -3,7 +3,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace AsbCloudWebApi.Tests
|
namespace AsbCloudWebApi.Tests
|
||||||
{
|
{
|
||||||
public static class AspExtentions
|
public static class AspExtensions
|
||||||
{
|
{
|
||||||
public static IServiceCollection ReplaceService<T>(this IServiceCollection services, T instance)
|
public static IServiceCollection ReplaceService<T>(this IServiceCollection services, T instance)
|
||||||
where T : notnull
|
where T : notnull
|
@ -0,0 +1,295 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudInfrastructure.Services.DetectOperations;
|
||||||
|
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Tests.Services.DetectedOperations.Detectors;
|
||||||
|
|
||||||
|
public class DetectorDrillingTests : DetectorDrilling
|
||||||
|
{
|
||||||
|
private const int idSlide = 5002;
|
||||||
|
private const int idRotor = 5003;
|
||||||
|
private const int idSlideWithOscillation = 12000;
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(TelemetryRangeDrillingRotor))]
|
||||||
|
public void DefineDrillingOperation_ShouldReturn_DrillingRotor(DetectableTelemetry[] telemetryRange)
|
||||||
|
{
|
||||||
|
//act
|
||||||
|
var result = GetSpecificInformation(telemetryRange, 0, telemetryRange.Length);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(idRotor, result.IdCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(TelemetryRangeDrillingSlide))]
|
||||||
|
public void DefineDrillingOperation_ShouldReturn_DrillingSlide(DetectableTelemetry[] telemetryRange)
|
||||||
|
{
|
||||||
|
//act
|
||||||
|
var result = GetSpecificInformation(telemetryRange, 0, telemetryRange.Length);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(idSlide, result.IdCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(TelemetryRangeDrillingSlideWithOscillation))]
|
||||||
|
public void DefineDrillingOperation_ShouldReturn_DrillingSlideWithOscillation(DetectableTelemetry[] telemetryRange)
|
||||||
|
{
|
||||||
|
//act
|
||||||
|
var result = GetSpecificInformation(telemetryRange, 0, telemetryRange.Length);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
var oHasOscillation = result.ExtraData[ExtraDataKeyHasOscillation];
|
||||||
|
|
||||||
|
Assert.Equal(idSlide, result.IdCategory);
|
||||||
|
Assert.True(oHasOscillation is bool hasOscillation && hasOscillation);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsValidOperationDetectorResult_ShouldReturn_True()
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
var operationDetectorResult = new OperationDetectorResult
|
||||||
|
{
|
||||||
|
Operation = new DetectedOperation
|
||||||
|
{
|
||||||
|
DepthStart = 5000,
|
||||||
|
DepthEnd = 6000,
|
||||||
|
DateStart = System.DateTimeOffset.Now.AddMinutes(-1),
|
||||||
|
DateEnd = System.DateTimeOffset.Now,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//act
|
||||||
|
var result = IsValidOperationDetectorResult(operationDetectorResult);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.True(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsValidOperationDetectorResult_ShouldReturn_False()
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
var operationDetectorResult = new OperationDetectorResult
|
||||||
|
{
|
||||||
|
Operation = new DetectedOperation
|
||||||
|
{
|
||||||
|
DepthStart = 5000,
|
||||||
|
DepthEnd = 5000,
|
||||||
|
DateStart = System.DateTimeOffset.Now.AddMinutes(-1),
|
||||||
|
DateEnd = System.DateTimeOffset.Now,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//act
|
||||||
|
var result = IsValidOperationDetectorResult(operationDetectorResult);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.False(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> TelemetryRangeDrillingRotor()
|
||||||
|
{
|
||||||
|
yield return new object[]
|
||||||
|
{
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 4.187f,
|
||||||
|
Pressure = 27.815952f,
|
||||||
|
HookWeight = 34.221367f,
|
||||||
|
BlockPosition = 24.388f,
|
||||||
|
BitDepth = 4.187f,
|
||||||
|
RotorSpeed = 40.3f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 4.232f,
|
||||||
|
Pressure = 28.080372f,
|
||||||
|
HookWeight = 34.162174f,
|
||||||
|
BlockPosition = 24.343f,
|
||||||
|
BitDepth = 4.232f,
|
||||||
|
RotorSpeed = 40.3f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 4.277f,
|
||||||
|
Pressure = 29.047901f,
|
||||||
|
HookWeight = 33.688717f,
|
||||||
|
BlockPosition = 24.298f,
|
||||||
|
BitDepth = 24.298f,
|
||||||
|
RotorSpeed = 40.3f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 4.309f,
|
||||||
|
Pressure = 29.574032f,
|
||||||
|
HookWeight = 33.692104f,
|
||||||
|
BlockPosition = 24.266f,
|
||||||
|
BitDepth = 4.309f,
|
||||||
|
RotorSpeed = 40.4f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 4.324f,
|
||||||
|
Pressure = 24.007977f,
|
||||||
|
HookWeight = 34.838448f,
|
||||||
|
BlockPosition = 24.251f,
|
||||||
|
BitDepth = 4.324f,
|
||||||
|
RotorSpeed = 40.5f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 4.324f,
|
||||||
|
Pressure = 24.04114f,
|
||||||
|
HookWeight = 34.423424f,
|
||||||
|
BlockPosition = 24.252f,
|
||||||
|
BitDepth = 4.323f,
|
||||||
|
RotorSpeed = 40.3f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> TelemetryRangeDrillingSlide()
|
||||||
|
{
|
||||||
|
yield return new object[]
|
||||||
|
{
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 447.276001f,
|
||||||
|
Pressure = 26.619421f,
|
||||||
|
HookWeight = 40.9143829f,
|
||||||
|
BlockPosition = 4.559f,
|
||||||
|
BitDepth = 477.265991f,
|
||||||
|
RotorSpeed = 0
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 477.289f,
|
||||||
|
Pressure = 28.716f,
|
||||||
|
HookWeight = 38.27f,
|
||||||
|
BlockPosition = 4.5f,
|
||||||
|
BitDepth = 477.289f,
|
||||||
|
RotorSpeed = 0.1f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
WellDepth = 477.30899f,
|
||||||
|
Pressure = 33.953495f,
|
||||||
|
HookWeight = 38.27f,
|
||||||
|
BlockPosition = 4.5359997f,
|
||||||
|
BitDepth = 477.289001f,
|
||||||
|
RotorSpeed = 0.1f
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> TelemetryRangeDrillingSlideWithOscillation()
|
||||||
|
{
|
||||||
|
yield return new object[]
|
||||||
|
{
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.306f,
|
||||||
|
Pressure = 53.731934f,
|
||||||
|
HookWeight = 41.049942f,
|
||||||
|
BlockPosition = 28.666f,
|
||||||
|
BitDepth = 415.293f,
|
||||||
|
RotorSpeed = 0.3f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.311f,
|
||||||
|
Pressure = 57.660595f,
|
||||||
|
HookWeight = 40.898712f,
|
||||||
|
BlockPosition = 28.648f,
|
||||||
|
BitDepth = 415.311f,
|
||||||
|
RotorSpeed = 0.2f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.326f,
|
||||||
|
Pressure = 59.211086f,
|
||||||
|
HookWeight = 40.882797f,
|
||||||
|
BlockPosition = 28.633f,
|
||||||
|
BitDepth = 415.326f,
|
||||||
|
RotorSpeed = 0.1f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.344f,
|
||||||
|
Pressure = 59.484406f,
|
||||||
|
HookWeight = 40.91972f,
|
||||||
|
BlockPosition = 28.615f,
|
||||||
|
BitDepth = 415.344f,
|
||||||
|
RotorSpeed = 0.2f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.364f,
|
||||||
|
Pressure = 60.739918f,
|
||||||
|
HookWeight = 40.795666f,
|
||||||
|
BlockPosition = 28.595f,
|
||||||
|
BitDepth = 415.364f,
|
||||||
|
RotorSpeed = 4.5f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.378f,
|
||||||
|
Pressure = 62.528984f,
|
||||||
|
HookWeight = 40.52114f,
|
||||||
|
BlockPosition = 28.581f,
|
||||||
|
BitDepth = 415.378f,
|
||||||
|
RotorSpeed = 22.6f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.392f,
|
||||||
|
Pressure = 67.0039f,
|
||||||
|
HookWeight = 38.878895f,
|
||||||
|
BlockPosition = 28.569f,
|
||||||
|
BitDepth = 415.39f,
|
||||||
|
RotorSpeed = 50f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.392f,
|
||||||
|
Pressure = 65.72418f,
|
||||||
|
HookWeight = 42.53173f,
|
||||||
|
BlockPosition = 28.622f,
|
||||||
|
BitDepth = 415.337f,
|
||||||
|
RotorSpeed = 93f
|
||||||
|
},
|
||||||
|
new DetectableTelemetry
|
||||||
|
{
|
||||||
|
IdUser = 1,
|
||||||
|
WellDepth = 415.392f,
|
||||||
|
Pressure = 56.82195f,
|
||||||
|
HookWeight = 43.15844f,
|
||||||
|
BlockPosition = 28.704f,
|
||||||
|
BitDepth = 415.255f,
|
||||||
|
RotorSpeed = 71.5f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -86,7 +86,7 @@ public class PeriodicBackgroundWorkerTest
|
|||||||
service.Add(badWork, TimeSpan.FromSeconds(2));
|
service.Add(badWork, TimeSpan.FromSeconds(2));
|
||||||
service.Add(goodWork, TimeSpan.FromSeconds(2));
|
service.Add(goodWork, TimeSpan.FromSeconds(2));
|
||||||
|
|
||||||
await Task.Delay(TimeSpan.FromMilliseconds(20));
|
await Task.Delay(TimeSpan.FromMilliseconds(128));
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(expectadResult, result);
|
Assert.Equal(expectadResult, result);
|
||||||
|
@ -20,15 +20,16 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
public class ReportController : ControllerBase
|
public class ReportController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IReportService reportService;
|
private readonly IReportService reportService;
|
||||||
private readonly FileService fileService;
|
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
private readonly IHubContext<ReportsHub, IReportHubClient> reportsHubContext;
|
private readonly IHubContext<ReportsHub, IReportHubClient> reportsHubContext;
|
||||||
|
|
||||||
public ReportController(IReportService reportService, IWellService wellService,
|
public ReportController(
|
||||||
FileService fileService, IHubContext<ReportsHub, IReportHubClient> reportsHubContext)
|
IReportService reportService,
|
||||||
|
IWellService wellService,
|
||||||
|
IHubContext<ReportsHub,
|
||||||
|
IReportHubClient> reportsHubContext)
|
||||||
{
|
{
|
||||||
this.reportService = reportService;
|
this.reportService = reportService;
|
||||||
this.fileService = fileService;
|
|
||||||
this.wellService = wellService;
|
this.wellService = wellService;
|
||||||
this.reportsHubContext = reportsHubContext;
|
this.reportsHubContext = reportsHubContext;
|
||||||
}
|
}
|
||||||
@ -150,6 +151,9 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
if (wellReportsDatesRange is null)
|
if (wellReportsDatesRange is null)
|
||||||
return NoContent();
|
return NoContent();
|
||||||
|
|
||||||
|
if (wellReportsDatesRange.From == wellReportsDatesRange.To)
|
||||||
|
return NoContent();
|
||||||
|
|
||||||
return Ok(wellReportsDatesRange);
|
return Ok(wellReportsDatesRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
[FromQuery] DetectedOperationRequest request,
|
[FromQuery] DetectedOperationRequest request,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
if (!await UserHasAccesToWellAsync(request.IdWell, token))
|
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
||||||
return Forbid();
|
return Forbid();
|
||||||
|
|
||||||
var result = await detectedOperationService.GetAsync(request, token);
|
var result = await detectedOperationService.GetAsync(request, token);
|
||||||
@ -79,7 +79,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
[FromQuery] DetectedOperationRequest request,
|
[FromQuery] DetectedOperationRequest request,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
if (!await UserHasAccesToWellAsync(request.IdWell, token))
|
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
||||||
return Forbid();
|
return Forbid();
|
||||||
|
|
||||||
var result = await detectedOperationService.GetOperationsStatAsync(request, token);
|
var result = await detectedOperationService.GetOperationsStatAsync(request, token);
|
||||||
@ -101,14 +101,14 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
|||||||
[FromQuery] DetectedOperationRequest request,
|
[FromQuery] DetectedOperationRequest request,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
if (!await UserHasAccesToWellAsync(request.IdWell, token))
|
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
||||||
return Forbid();
|
return Forbid();
|
||||||
|
|
||||||
var result = await detectedOperationService.DeleteAsync(request, token);
|
var result = await detectedOperationService.DeleteAsync(request, token);
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task<bool> UserHasAccesToWellAsync(int idWell, CancellationToken token)
|
protected async Task<bool> UserHasAccessToWellAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var idCompany = User.GetCompanyId();
|
var idCompany = User.GetCompanyId();
|
||||||
if (idCompany is not null &&
|
if (idCompany is not null &&
|
||||||
|
@ -21,7 +21,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory
|
|||||||
public abstract class TrajectoryController<TDto> : ControllerBase
|
public abstract class TrajectoryController<TDto> : ControllerBase
|
||||||
where TDto : TrajectoryGeoDto
|
where TDto : TrajectoryGeoDto
|
||||||
{
|
{
|
||||||
protected abstract string fileName { get; set; }
|
protected abstract string fileName { get; }
|
||||||
|
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
private readonly TrajectoryExportService<TDto> trajectoryExportService;
|
private readonly TrajectoryExportService<TDto> trajectoryExportService;
|
||||||
|
@ -19,19 +19,17 @@ namespace AsbCloudWebApi.Controllers.Trajectory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public abstract class TrajectoryEditableController<Tdto> : TrajectoryController<Tdto>
|
public abstract class TrajectoryEditableController<TDto> : TrajectoryController<TDto>
|
||||||
where Tdto : TrajectoryGeoDto
|
where TDto : TrajectoryGeoDto
|
||||||
{
|
{
|
||||||
protected override string fileName { get; set; }
|
private readonly TrajectoryParserService<TDto> trajectoryImportService;
|
||||||
|
private readonly TrajectoryExportService<TDto> trajectoryExportService;
|
||||||
private readonly TrajectoryParserService<Tdto> trajectoryImportService;
|
private readonly ITrajectoryEditableRepository<TDto> trajectoryRepository;
|
||||||
private readonly TrajectoryExportService<Tdto> trajectoryExportService;
|
|
||||||
private readonly ITrajectoryEditableRepository<Tdto> trajectoryRepository;
|
|
||||||
|
|
||||||
public TrajectoryEditableController(IWellService wellService,
|
public TrajectoryEditableController(IWellService wellService,
|
||||||
TrajectoryParserService<Tdto> trajectoryImportService,
|
TrajectoryParserService<TDto> trajectoryImportService,
|
||||||
TrajectoryExportService<Tdto> trajectoryExportService,
|
TrajectoryExportService<TDto> trajectoryExportService,
|
||||||
ITrajectoryEditableRepository<Tdto> trajectoryRepository)
|
ITrajectoryEditableRepository<TDto> trajectoryRepository)
|
||||||
: base(
|
: base(
|
||||||
wellService,
|
wellService,
|
||||||
trajectoryExportService,
|
trajectoryExportService,
|
||||||
@ -118,7 +116,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory
|
|||||||
/// <returns>количество успешно записанных строк в БД</returns>
|
/// <returns>количество успешно записанных строк в БД</returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> AddAsync(int idWell, [FromBody] Tdto row,
|
public async Task<IActionResult> AddAsync(int idWell, [FromBody] TDto row,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
|
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
|
||||||
@ -141,7 +139,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory
|
|||||||
/// <returns>количество успешно записанных строк в БД</returns>
|
/// <returns>количество успешно записанных строк в БД</returns>
|
||||||
[HttpPost("range")]
|
[HttpPost("range")]
|
||||||
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> AddRangeAsync(int idWell, [FromBody] IEnumerable<Tdto> rows,
|
public async Task<IActionResult> AddRangeAsync(int idWell, [FromBody] IEnumerable<TDto> rows,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
|
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
|
||||||
@ -169,7 +167,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory
|
|||||||
[HttpPut("{idRow}")]
|
[HttpPut("{idRow}")]
|
||||||
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> UpdateAsync(int idWell, int idRow,
|
public async Task<IActionResult> UpdateAsync(int idWell, int idRow,
|
||||||
[FromBody] Tdto row, CancellationToken token)
|
[FromBody] TDto row, CancellationToken token)
|
||||||
{
|
{
|
||||||
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
|
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
|
||||||
return Forbid();
|
return Forbid();
|
||||||
|
@ -14,7 +14,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory;
|
|||||||
[Route("api/well/{idWell}/[controller]")]
|
[Route("api/well/{idWell}/[controller]")]
|
||||||
public class TrajectoryFactManualController : TrajectoryEditableController<TrajectoryGeoFactDto>
|
public class TrajectoryFactManualController : TrajectoryEditableController<TrajectoryGeoFactDto>
|
||||||
{
|
{
|
||||||
protected override string fileName { get; set; }
|
protected override string fileName => "ЕЦП_шаблон_файла_фактическая_траектория.xlsx";
|
||||||
public TrajectoryFactManualController(IWellService wellService,
|
public TrajectoryFactManualController(IWellService wellService,
|
||||||
TrajectoryFactManualParserService factTrajectoryImportService,
|
TrajectoryFactManualParserService factTrajectoryImportService,
|
||||||
TrajectoryFactManualExportService factTrajectoryExportService,
|
TrajectoryFactManualExportService factTrajectoryExportService,
|
||||||
@ -24,7 +24,5 @@ public class TrajectoryFactManualController : TrajectoryEditableController<Traje
|
|||||||
factTrajectoryImportService,
|
factTrajectoryImportService,
|
||||||
factTrajectoryExportService,
|
factTrajectoryExportService,
|
||||||
trajectoryFactRepository)
|
trajectoryFactRepository)
|
||||||
{
|
{ }
|
||||||
fileName = "ЕЦП_шаблон_файла_фактическая_траектория.xlsx";
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -15,7 +15,7 @@ namespace AsbCloudWebApi.Controllers.Trajectory;
|
|||||||
[Route("api/well/{idWell}/[controller]")]
|
[Route("api/well/{idWell}/[controller]")]
|
||||||
public class TrajectoryFactNnbController : TrajectoryController<TrajectoryGeoFactDto>
|
public class TrajectoryFactNnbController : TrajectoryController<TrajectoryGeoFactDto>
|
||||||
{
|
{
|
||||||
protected override string fileName { get; set; }
|
protected override string fileName => "ЕЦП_шаблон_файла_фактическая_ннб_траектория.xlsx";
|
||||||
public TrajectoryFactNnbController(
|
public TrajectoryFactNnbController(
|
||||||
ITrajectoryNnbRepository trajectoryNnbRepository,
|
ITrajectoryNnbRepository trajectoryNnbRepository,
|
||||||
TrajectoryFactNnbExportService trajectoryExportService,
|
TrajectoryFactNnbExportService trajectoryExportService,
|
||||||
@ -24,7 +24,5 @@ public class TrajectoryFactNnbController : TrajectoryController<TrajectoryGeoFac
|
|||||||
wellService,
|
wellService,
|
||||||
trajectoryExportService,
|
trajectoryExportService,
|
||||||
trajectoryNnbRepository)
|
trajectoryNnbRepository)
|
||||||
{
|
{ }
|
||||||
fileName = "ЕЦП_шаблон_файла_фактическая_ннб_траектория.xlsx";
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -21,6 +21,8 @@ namespace AsbCloudWebApi.Controllers.Trajectory
|
|||||||
{
|
{
|
||||||
private readonly TrajectoryService trajectoryVisualizationService;
|
private readonly TrajectoryService trajectoryVisualizationService;
|
||||||
|
|
||||||
|
protected override string fileName => "ЕЦП_шаблон_файла_плановая_траектория.xlsx";
|
||||||
|
|
||||||
public TrajectoryPlanController(IWellService wellService,
|
public TrajectoryPlanController(IWellService wellService,
|
||||||
TrajectoryPlanParserService trajectoryPlanImportService,
|
TrajectoryPlanParserService trajectoryPlanImportService,
|
||||||
TrajectoryPlanExportService trajectoryPlanExportService,
|
TrajectoryPlanExportService trajectoryPlanExportService,
|
||||||
@ -32,7 +34,6 @@ namespace AsbCloudWebApi.Controllers.Trajectory
|
|||||||
trajectoryPlanExportService,
|
trajectoryPlanExportService,
|
||||||
trajectoryPlanRepository)
|
trajectoryPlanRepository)
|
||||||
{
|
{
|
||||||
fileName = "ЕЦП_шаблон_файла_плановая_траектория.xlsx";
|
|
||||||
this.trajectoryVisualizationService = trajectoryVisualizationService;
|
this.trajectoryVisualizationService = trajectoryVisualizationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ namespace AsbCloudWebApi
|
|||||||
{
|
{
|
||||||
// Uncomment next line to find wired exceptions by tracing.
|
// Uncomment next line to find wired exceptions by tracing.
|
||||||
//static TraceListenerView trace4debug = new TraceListenerView();
|
//static TraceListenerView trace4debug = new TraceListenerView();
|
||||||
|
enum A { a = 1 << 2 }
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudInfrastructure.Background;
|
using AsbCloudInfrastructure.Background;
|
||||||
using AsbCloudWebApi.SignalR.Clients;
|
using AsbCloudWebApi.SignalR.Clients;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using System.Linq;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -17,39 +18,44 @@ namespace AsbCloudWebApi.SignalR
|
|||||||
[Authorize]
|
[Authorize]
|
||||||
public class ReportsHub : BaseHub<IReportHubClient>
|
public class ReportsHub : BaseHub<IReportHubClient>
|
||||||
{
|
{
|
||||||
private readonly BackgroundWorker backgroundWorker;
|
private readonly IWellService wellService;
|
||||||
|
private readonly IReportService reportService;
|
||||||
|
|
||||||
public ReportsHub(BackgroundWorker backgroundWorker)
|
public ReportsHub(IWellService wellService, IReportService reportService)
|
||||||
{
|
{
|
||||||
this.backgroundWorker = backgroundWorker;
|
this.wellService = wellService;
|
||||||
|
this.reportService = reportService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавление в группу, отправка данных о формировании отчета
|
/// Добавление в группу, отправка данных о формировании отчета
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="groupName"></param>
|
/// <param name="groupName">группа</param>
|
||||||
|
/// <param name="idWell">ключ скважины</param>
|
||||||
|
/// <param name="request">параметры запроса</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public override async Task AddToGroup(string groupName)
|
public async Task CreateReport(string groupName, int idWell, ReportParametersRequest request)
|
||||||
{
|
{
|
||||||
|
var idUser = Context.User?.GetUserId();
|
||||||
|
var idCompany = Context.User?.GetCompanyId();
|
||||||
|
|
||||||
|
if ((idCompany is null) || (idUser is null))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, CancellationToken.None))
|
||||||
|
return;
|
||||||
|
|
||||||
await base.AddToGroup(groupName);
|
await base.AddToGroup(groupName);
|
||||||
|
|
||||||
var workId = groupName.Replace("Report_", "");
|
void HandleReportProgressAsync(object progress, string id) =>
|
||||||
var work = backgroundWorker.Works.FirstOrDefault(work => work.Id == workId);
|
Task.Run(async () =>
|
||||||
|
|
||||||
var progress = new ReportProgressDto()
|
|
||||||
{
|
{
|
||||||
Operation = "Ожидает начала в очереди.",
|
await Clients.Group(groupName)
|
||||||
Progress = 0f,
|
.GetReportProgress(progress, CancellationToken.None);
|
||||||
};
|
}, CancellationToken.None);
|
||||||
|
|
||||||
var state = work?.CurrentState;
|
var id = reportService.EnqueueCreateReportWork(idWell, (int)idUser,
|
||||||
if (state is not null)
|
request.StepSeconds, request.Format, request.Begin, request.End, HandleReportProgressAsync);
|
||||||
{
|
|
||||||
progress.Operation = state.State;
|
|
||||||
progress.Progress = (float)state.Progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Clients.Group(groupName).GetReportProgress(progress, CancellationToken.None);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ namespace SignalRTestClient;
|
|||||||
|
|
||||||
internal class Program
|
internal class Program
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main()
|
||||||
{
|
{
|
||||||
var connectionBuilder = new HubConnectionBuilder();
|
var connectionBuilder = new HubConnectionBuilder();
|
||||||
var connection = connectionBuilder
|
var connection = connectionBuilder
|
||||||
@ -47,7 +47,7 @@ internal class Program
|
|||||||
builder.AddProvider(provider);
|
builder.AddProvider(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Task<string?> AccessTokenProvider()
|
private static Task<string> AccessTokenProvider()
|
||||||
{
|
{
|
||||||
return Task.FromResult("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE");
|
return Task.FromResult("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user