nit refactoring by VS recommendations
This commit is contained in:
ngfrolov 2023-12-05 14:48:56 +05:00
parent e67e260f35
commit 17c13b7a7b
Signed by: ng.frolov
GPG Key ID: E99907A0357B29A7
30 changed files with 273 additions and 273 deletions

View File

@ -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];
} }

View File

@ -94,5 +94,5 @@ public class ProcessMapReportWellDrillingDto
/// <summary> /// <summary>
/// Механическая скорость, м/ч /// Механическая скорость, м/ч
/// </summary> /// </summary>
public PlanFactDto<double?> Rop { get; set; } public PlanFactDto<double?> Rop { get; set; } = new();
} }

View File

@ -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;
} }

View File

@ -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>
/// Получить диапазон дат телеметрии. /// Получить диапазон дат телеметрии.

View File

@ -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>
/// Получение истории файлов /// Получение истории файлов

View File

@ -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)

View File

@ -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())

View File

@ -349,6 +349,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()

View File

@ -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 = "мин" },

View File

@ -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>
/// Ошибка в главном цикле, никогда не должна появляться /// Ошибка в главном цикле, никогда не должна появляться

View File

@ -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

View File

@ -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;
} }

View File

@ -95,12 +95,10 @@ 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) if (!await IsDateDailyReportInRangeAsync(idWell, dateDailyReport, cancellationToken))
throw new ArgumentNullException(nameof(idWell), $"Скважина с Id: {idWell} не найдена");
if (!await IsDateDailyReportInRangeAsync(idWell, dateDailyReport, cancellationToken))
throw new ArgumentInvalidException(nameof(dateDailyReport), "Невозможно получить суточный отчёт"); throw new ArgumentInvalidException(nameof(dateDailyReport), "Невозможно получить суточный отчёт");

View File

@ -61,10 +61,12 @@ public class DetectorDrilling : DetectorAbstract
{ {
var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed) = CalcCriteries(telemetry, begin, end); var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed) = CalcCriteries(telemetry, begin, end);
var idCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed); var idCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed);
var extraData = new Dictionary<string, object>(); var extraData = new Dictionary<string, object>
extraData[ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed; {
extraData[ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed; [ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed,
extraData[ExtraDataKeyHasOscillation] = dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold; [ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed,
[ExtraDataKeyHasOscillation] = dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold
};
return (idCategory, extraData); return (idCategory, extraData);
} }

View File

@ -118,6 +118,7 @@ public class WorkOperationDetection: Work
{ {
var data = await query var data = await query
.Where(d => d.DateTime > startDate) .Where(d => d.DateTime > startDate)
.Take(take)
.ToArrayAsync(token); .ToArrayAsync(token);
if (data.Length < gap) if (data.Length < gap)

View File

@ -13,203 +13,201 @@ 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
{ {
private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
private readonly FileService fileService;
private readonly IWellService wellService;
private readonly BackgroundWorker backgroundWorkerService;
public class ReportService : IReportService public int ReportCategoryId { get; private set; }
public ReportService(IAsbCloudDbContext db,
ITelemetryService telemetryService,
IWellService wellService,
FileService fileService,
BackgroundWorker backgroundWorkerService)
{ {
private readonly IAsbCloudDbContext db; this.db = db;
private readonly ITelemetryService telemetryService; this.wellService = wellService;
private readonly FileService fileService; this.backgroundWorkerService = backgroundWorkerService;
private readonly IWellService wellService; this.telemetryService = telemetryService;
private readonly BackgroundWorker backgroundWorkerService; this.fileService = fileService;
ReportCategoryId = db.FileCategories
public int ReportCategoryId { get; private set; }
public ReportService(IAsbCloudDbContext db,
ITelemetryService telemetryService,
IWellService wellService,
FileService fileService,
BackgroundWorker backgroundWorkerService)
{
this.db = db;
this.wellService = wellService;
this.backgroundWorkerService = backgroundWorkerService;
this.telemetryService = telemetryService;
this.fileService = fileService;
ReportCategoryId = db.FileCategories
.AsNoTracking()
.First(c => c.Name.Equals("Рапорт"))
.Id;
}
public string EnqueueCreateReportWork(int idWell, int idUser, int stepSeconds, int format, DateTime begin,
DateTime end, Action<object, string> progressHandler)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset);
var endUtc = end.ToUtcDateTimeOffset(timezoneOffset);
var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset);
var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset);
var workId = $"create report by wellid:{idWell} for userid:{idUser} requested at {DateTime.Now}";
var workAction = async (string id, IServiceProvider serviceProvider, Action<string, double?> onProgress, CancellationToken token) =>
{
using var context = serviceProvider.GetRequiredService<IAsbCloudDbContext>();
var fileService = serviceProvider.GetRequiredService<FileService>();
var tempDir = Path.Combine(Path.GetTempPath(), "report");
var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, context);
var reportFileName = Path.Combine(tempDir, generator.GetReportDefaultFileName());
var totalPages = generator.GetPagesCount();
generator.OnProgress += (s, e) =>
{
var arg = e.Adapt<ReportProgressDto>();
onProgress(arg.Operation?? string.Empty, arg.Progress);
progressHandler.Invoke(arg, id);
};
generator.Make(reportFileName);
var fileInfo = (await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token))!;
progressHandler.Invoke(new
{
Operation = "done",
Progress = 100f,
TotalPages = totalPages,
CurrentPage = totalPages,
file = fileInfo,
}, id);
var newReportProperties = new ReportProperty
{
IdWell = idWell,
IdFile = fileInfo.Id,
Begin = beginUtc,
End = endUtc,
Step = stepSeconds,
Format = format
};
context.ReportProperties.Add(newReportProperties);
context.SaveChanges();
};
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);
progressHandler.Invoke(new ReportProgressDto
{
Operation = "Ожидает начала в очереди.",
Progress = 0f,
}, workId);
return workId;
}
public int GetReportPagesCount(int idWell, DateTime begin, DateTime end, int stepSeconds, int format)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset);
var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset);
var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, db);
var pagesCount = generator.GetPagesCount();
return pagesCount;
}
public DatesRangeDto? GetDatesRangeOrDefault(int idWell)
{
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
if (telemetry is null)
return null;
var range = telemetryService.GetDatesRange(telemetry.Id);
return range;
}
public async Task<IEnumerable<ReportPropertiesDto>> GetAllReportsByWellAsync(int idWell, CancellationToken token)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var propertiesQuery = db.ReportProperties.Include(r => r.File)
.Where(p => p.IdWell == idWell)
.OrderBy(o => o.File.UploadDate)
.AsNoTracking() .AsNoTracking()
.Take(1024); .First(c => c.Name.Equals("Рапорт"))
var entities = await propertiesQuery.ToListAsync(token); .Id;
var dtos = entities.Select(p => new ReportPropertiesDto }
{
Id = p.Id,
Name = p.File.Name,
File = new FileInfoDto
{
Id = p.File.Id,
Author = null,
IdAuthor = p.File.IdAuthor ?? 0,
IdCategory = p.File.IdCategory,
IdWell = p.File.IdWell,
Name = p.File.Name,
Size = p.File.Size,
UploadDate = p.File.UploadDate.ToRemoteDateTime(timezoneOffset),
},
IdWell = p.IdWell,
Date = p.File.UploadDate.ToRemoteDateTime(timezoneOffset),
Begin = p.Begin.ToRemoteDateTime(timezoneOffset),
End = p.End.ToRemoteDateTime(timezoneOffset),
Step = p.Step,
Format = p.Format == 0 ? ".pdf" : ".las"
});
return dtos;
}
private static IReportGenerator GetReportGenerator(int idWell, DateTime begin, public string EnqueueCreateReportWork(int idWell, int idUser, int stepSeconds, int format, DateTime begin,
DateTime end, int stepSeconds, int format, IAsbCloudDbContext context) DateTime end, Action<object, string> progressHandler)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset);
var endUtc = end.ToUtcDateTimeOffset(timezoneOffset);
var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset);
var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset);
var workId = $"create report by wellid:{idWell} for userid:{idUser} requested at {DateTime.Now}";
var workAction = async (string id, IServiceProvider serviceProvider, Action<string, double?> onProgress, CancellationToken token) =>
{ {
var dataSource = new ReportDataSourcePgCloud(context, idWell); using var context = serviceProvider.GetRequiredService<IAsbCloudDbContext>();
IReportGenerator generator = format switch var fileService = serviceProvider.GetRequiredService<FileService>();
var tempDir = Path.Combine(Path.GetTempPath(), "report");
var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, context);
var reportFileName = Path.Combine(tempDir, generator.GetReportDefaultFileName());
var totalPages = generator.GetPagesCount();
generator.OnProgress += (s, e) =>
{ {
//LAS var arg = e.Adapt<ReportProgressDto>();
1 => new AsbSaubReportLas.ReprotGeneratorLas(dataSource), onProgress(arg.Operation?? string.Empty, arg.Progress);
//PDF progressHandler.Invoke(arg, id);
_ => new AsbSaubReportPdf.ReprotGeneratorPdf(dataSource),
}; };
generator.Make(reportFileName);
if(begin == default || end == default) var fileInfo = (await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token))!;
progressHandler.Invoke(new
{ {
var analyzeResult = dataSource.Analyze(); Operation = "done",
begin = begin == default ? analyzeResult.MinDate : begin; Progress = 100f,
end = end == default ? begin.AddDays(1) : end; TotalPages = totalPages,
} CurrentPage = totalPages,
file = fileInfo,
}, id);
generator.Begin = begin; var newReportProperties = new ReportProperty
generator.End = end; {
generator.Step = TimeSpan.FromSeconds(stepSeconds); IdWell = idWell,
generator.WithCharts = true; IdFile = fileInfo.Id,
generator.WithEvents = true; Begin = beginUtc,
End = endUtc,
Step = stepSeconds,
Format = format
};
context.ReportProperties.Add(newReportProperties);
context.SaveChanges();
};
return generator; 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);
public async Task<int> DeleteAllOldReportsAsync(TimeSpan lifetime, CancellationToken token) backgroundWorkerService.Enqueue(work);
progressHandler.Invoke(new ReportProgressDto
{ {
var lifeTimeStartDate = DateTime.UtcNow.Date - lifetime; Operation = "Ожидает начала в очереди.",
var fileIds = await db.ReportProperties Progress = 0f,
.Where(r => r.File.UploadDate.Date < lifeTimeStartDate) }, workId);
.Select(r => r.IdFile) return workId;
.ToArrayAsync(token); }
return await fileService.DeleteAsync(fileIds, token); public int GetReportPagesCount(int idWell, DateTime begin, DateTime end, int stepSeconds, int format)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset);
var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset);
var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, db);
var pagesCount = generator.GetPagesCount();
return pagesCount;
}
public DatesRangeDto? GetDatesRangeOrDefault(int idWell)
{
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
if (telemetry is null)
return null;
var range = telemetryService.GetDatesRange(telemetry.Id);
return range;
}
public async Task<IEnumerable<ReportPropertiesDto>> GetAllReportsByWellAsync(int idWell, CancellationToken token)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var propertiesQuery = db.ReportProperties.Include(r => r.File)
.Where(p => p.IdWell == idWell)
.OrderBy(o => o.File.UploadDate)
.AsNoTracking()
.Take(1024);
var entities = await propertiesQuery.ToListAsync(token);
var dtos = entities.Select(p => new ReportPropertiesDto
{
Id = p.Id,
Name = p.File.Name,
File = new FileInfoDto
{
Id = p.File.Id,
Author = null,
IdAuthor = p.File.IdAuthor ?? 0,
IdCategory = p.File.IdCategory,
IdWell = p.File.IdWell,
Name = p.File.Name,
Size = p.File.Size,
UploadDate = p.File.UploadDate.ToRemoteDateTime(timezoneOffset),
},
IdWell = p.IdWell,
Date = p.File.UploadDate.ToRemoteDateTime(timezoneOffset),
Begin = p.Begin.ToRemoteDateTime(timezoneOffset),
End = p.End.ToRemoteDateTime(timezoneOffset),
Step = p.Step,
Format = p.Format == 0 ? ".pdf" : ".las"
});
return dtos;
}
private static IReportGenerator GetReportGenerator(int idWell, DateTime begin,
DateTime end, int stepSeconds, int format, IAsbCloudDbContext context)
{
var dataSource = new ReportDataSourcePgCloud(context, idWell);
IReportGenerator generator = format switch
{
//LAS
1 => new AsbSaubReportLas.ReprotGeneratorLas(dataSource),
//PDF
_ => new AsbSaubReportPdf.ReprotGeneratorPdf(dataSource),
};
if(begin == default || end == default)
{
var analyzeResult = dataSource.Analyze();
begin = begin == default ? analyzeResult.MinDate : begin;
end = end == default ? begin.AddDays(1) : end;
} }
generator.Begin = begin;
generator.End = end;
generator.Step = TimeSpan.FromSeconds(stepSeconds);
generator.WithCharts = true;
generator.WithEvents = true;
return generator;
}
public async Task<int> DeleteAllOldReportsAsync(TimeSpan lifetime, CancellationToken token)
{
var lifeTimeStartDate = DateTime.UtcNow.Date - lifetime;
var fileIds = await db.ReportProperties
.Where(r => r.File.UploadDate.Date < lifeTimeStartDate)
.Select(r => r.IdFile)
.ToArrayAsync(token);
return await fileService.DeleteAsync(fileIds, token);
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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;
} }

View File

@ -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);

View File

@ -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>>();

View File

@ -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

View File

@ -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;
} }

View File

@ -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;

View File

@ -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();

View File

@ -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";
}
} }

View File

@ -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";
}
} }

View File

@ -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;
} }

View File

@ -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");
} }