forked from ddrilling/AsbCloudServer
не доделано перед праздниками
This commit is contained in:
parent
962d6e15b6
commit
4872b4a495
@ -9,8 +9,8 @@ namespace AsbCloudApp.Data
|
||||
public FileInfoDto File { get; set; }
|
||||
public int IdWell { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public DateTimeOffset Begin { get; set; }
|
||||
public DateTimeOffset End { get; set; }
|
||||
public DateTime Begin { get; set; }
|
||||
public DateTime End { get; set; }
|
||||
public int Step { get; set; }
|
||||
public string Format { get; set; }
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ namespace AsbCloudApp.Data
|
||||
{
|
||||
public class TelemetryOperationInfoDto
|
||||
{
|
||||
public DateTimeOffset IntervalBegin { get; set; }
|
||||
public DateTime IntervalBegin { get; set; }
|
||||
public IList<TelemetryOperationDetailsDto> Operations { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -10,14 +10,13 @@ namespace AsbCloudApp.Services
|
||||
{
|
||||
ITimeZoneService TimeZoneService { get; }
|
||||
ITelemetryTracker TelemetryTracker { get; }
|
||||
|
||||
int? GetIdWellByTelemetryUid(string uid);
|
||||
int GetOrCreateTelemetryIdByUid(string uid);
|
||||
double GetTimezoneOffsetByTelemetryId(int idTelemetry);
|
||||
Task<double?> GetTelemetryTimeZoneOffsetAsync(int idTelemetry, CancellationToken token);
|
||||
double GetTimezoneOffset(int idTelemetry);
|
||||
Task<double?> GetTimeZoneOffsetAsync(int idTelemetry, CancellationToken token);
|
||||
IEnumerable<TelemetryDto> GetTransmittingTelemetries();
|
||||
DateTime GetLastTelemetryDate(string telemetryUid);
|
||||
DateTime GetLastTelemetryDate(int telemetryId);
|
||||
DateTimeOffset GetLastTelemetryDate(string telemetryUid);
|
||||
DateTimeOffset GetLastTelemetryDate(int telemetryId);
|
||||
int? GetIdTelemetryByIdWell(int idWell);
|
||||
|
||||
Task UpdateInfoAsync(string uid, TelemetryInfoDto info, CancellationToken token);
|
||||
@ -34,7 +33,7 @@ namespace AsbCloudApp.Services
|
||||
/// <returns></returns>
|
||||
Task<int> MergeAsync(int from, int to, CancellationToken token);
|
||||
|
||||
void SaveRequestDate(string uid, DateTime remoteDate);
|
||||
void SaveRequestDate(string uid, DateTimeOffset remoteDate);
|
||||
Task<DatesRangeDto> GetDatesRangeAsync(int idWell, bool isUtc, CancellationToken token = default);
|
||||
}
|
||||
}
|
@ -6,9 +6,9 @@ namespace AsbCloudApp.Services
|
||||
{
|
||||
public interface ITelemetryTracker
|
||||
{
|
||||
DateTime GetLastTelemetryDateByUid(string uid);
|
||||
DateTimeOffset GetLastTelemetryDateByUid(string uid);
|
||||
DatesRangeDto GetTelemetryDateRangeByUid(string uid);
|
||||
IEnumerable<string> GetTransmittingTelemetriesUids();
|
||||
void SaveRequestDate(string uid, DateTime remoteDate);
|
||||
void SaveRequestDate(string uid, DateTimeOffset remoteDate);
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ namespace AsbCloudApp.Services
|
||||
{
|
||||
public interface ITimeZoneService
|
||||
{
|
||||
DateTime DateToUtc(DateTime date, double remoteTimezoneOffsetHours);
|
||||
DateTime DateToTimeZone(DateTime date, double remoteTimezoneOffsetHours);
|
||||
Task<Data.TelemetryTimeZoneDto> GetByCoordinatesAsync(double latitude, double longitude, CancellationToken token);
|
||||
}
|
||||
}
|
@ -8,6 +8,8 @@ namespace AsbCloudApp.Services
|
||||
{
|
||||
public interface IWellService: ICrudService<WellDto>
|
||||
{
|
||||
ITelemetryService TelemetryService { get; }
|
||||
|
||||
Task<IEnumerable<WellDto>> GetWellsByCompanyAsync(int idCompany, CancellationToken token);
|
||||
Task<bool> IsCompanyInvolvedInWellAsync(int idCompany, int idWell, CancellationToken token);
|
||||
Task<string> GetWellCaptionByIdAsync(int idWell, CancellationToken token);
|
||||
@ -15,7 +17,8 @@ namespace AsbCloudApp.Services
|
||||
Task<IEnumerable<CompanyDto>> GetCompaniesAsync(int idWell, CancellationToken token);
|
||||
bool IsCompanyInvolvedInWell(int idCompany, int idWell);
|
||||
string GetStateText(int state);
|
||||
DateTime GetLastTelemetryDate(int idWell);
|
||||
DateTimeOffset GetLastTelemetryDate(int idWell);
|
||||
Task<IEnumerable<int>> GetClusterWellsIdsAsync(int idWell, CancellationToken token);
|
||||
double? GetTimeZoneOffset(int idWell);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ namespace AsbCloudDb.Model
|
||||
public TelemetryInfo Info { get; set; }
|
||||
|
||||
[Column("timezone", TypeName = "jsonb"), Comment("Смещение часового пояса от UTC")]
|
||||
public TelemetryTimeZone TelemetryTimeZone { get; set; }
|
||||
public TelemetryTimeZone TimeZone { get; set; }
|
||||
|
||||
[InverseProperty(nameof(Model.Well.Telemetry))]
|
||||
public virtual Well Well { get; set; }
|
||||
|
29
AsbCloudInfrastructure/DateTimeExtentions.cs
Normal file
29
AsbCloudInfrastructure/DateTimeExtentions.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudInfrastructure
|
||||
{
|
||||
public static class DateTimeExtentions
|
||||
{
|
||||
public static DateTimeOffset ToUtcDateTimeOffset(this DateTime date, double remoteTimezoneOffsetHours)
|
||||
{
|
||||
if (date == default)
|
||||
return new DateTimeOffset();
|
||||
|
||||
var dateUtc = date.Kind switch
|
||||
{
|
||||
DateTimeKind.Local => date.ToUniversalTime(),
|
||||
DateTimeKind.Unspecified => date.AddHours(-remoteTimezoneOffsetHours),
|
||||
_ => date,
|
||||
};
|
||||
return new DateTimeOffset(dateUtc);
|
||||
}
|
||||
|
||||
public static DateTime ToRemoteDateTime(this DateTimeOffset date, double remoteTimezoneOffsetHours)
|
||||
{
|
||||
if (date == default)
|
||||
return new DateTime(0, DateTimeKind.Unspecified);
|
||||
var dateTz = date.ToOffset(TimeSpan.FromHours(remoteTimezoneOffsetHours));
|
||||
return dateTz.DateTime;
|
||||
}
|
||||
}
|
||||
}
|
@ -74,8 +74,8 @@ namespace AsbCloudInfrastructure
|
||||
|
||||
var result = new AnalyzeResult
|
||||
{
|
||||
MinDate = dataStat?.min ?? messagesStat?.min ?? default,
|
||||
MaxDate = dataStat?.max ?? messagesStat?.max ?? default,
|
||||
MinDate = dataStat?.min.DateTime ?? messagesStat?.min.DateTime ?? default,
|
||||
MaxDate = dataStat?.max.DateTime ?? messagesStat?.max.DateTime ?? default,
|
||||
MessagesCount = messagesStat?.count ?? 0,
|
||||
};
|
||||
|
||||
@ -91,7 +91,7 @@ namespace AsbCloudInfrastructure
|
||||
select new DataSaubReport
|
||||
{
|
||||
//Id = item.Id,
|
||||
Date = item.Date,
|
||||
Date = item.Date.DateTime,
|
||||
Mode = item.Mode,
|
||||
WellDepth = item.WellDepth,
|
||||
BitDepth = item.BitDepth,
|
||||
@ -121,7 +121,7 @@ namespace AsbCloudInfrastructure
|
||||
select new MessageReport
|
||||
{
|
||||
Id = item.Id,
|
||||
Date = item.Date,
|
||||
Date = item.Date.DateTime,
|
||||
Category = events.GetValueOrDefault(item.IdEvent) == null
|
||||
? $""
|
||||
: categories[events[item.IdEvent].IdCategory],
|
||||
|
@ -5,7 +5,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
|
||||
class DataSaubAnalyse
|
||||
{
|
||||
public int IdTelemetry { get; internal set; }
|
||||
public DateTime Date { get; internal set; }
|
||||
public DateTimeOffset Date { get; internal set; }
|
||||
public double WellDepth { get; internal set; }
|
||||
public double BitDepth { get; internal set; }
|
||||
public double BlockPosition { get; internal set; }
|
||||
|
@ -70,7 +70,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
|
||||
if (telemetryId is null)
|
||||
return null;
|
||||
|
||||
var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId((int)telemetryId);
|
||||
var timezoneOffset = telemetryService.GetTimezoneOffset((int)telemetryId);
|
||||
|
||||
var drillingPeriodsInfo = await db.TelemetryDataSaub
|
||||
.Where(t => t.IdTelemetry == telemetryId)
|
||||
@ -201,7 +201,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
|
||||
if (telemetryId is null)
|
||||
return null;
|
||||
|
||||
var timezoneOffset = telemetryService.GetTimezoneOffsetByTelemetryId((int)telemetryId);
|
||||
var timezoneOffset = telemetryService.GetTimezoneOffset((int)telemetryId);
|
||||
|
||||
// Get'n'Group all operations only by start date and by name (if there were several operations in interval).
|
||||
// Without dividing these operations duration by given interval
|
||||
@ -251,7 +251,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
|
||||
}
|
||||
}
|
||||
|
||||
private async Task AnalyseAndSaveTelemetryAsync(int idTelemetry, DateTime analyzeStartDate, CancellationToken token = default)
|
||||
private async Task AnalyseAndSaveTelemetryAsync(int idTelemetry, DateTimeOffset analyzeStartDate, CancellationToken token = default)
|
||||
{
|
||||
const int step = 10;
|
||||
const int take = step * 2;
|
||||
@ -355,7 +355,7 @@ namespace AsbCloudInfrastructure.Services.Analysis
|
||||
return lastAnalysisDate;
|
||||
}
|
||||
|
||||
private Task<List<DataSaubAnalyse>> GetDataSaubPartOrDefaultAsync(int idTelemetry, DateTime analyzeStartDate, CancellationToken token) =>
|
||||
private Task<List<DataSaubAnalyse>> GetDataSaubPartOrDefaultAsync(int idTelemetry, DateTimeOffset analyzeStartDate, CancellationToken token) =>
|
||||
db.TelemetryDataSaub
|
||||
.Where(d =>
|
||||
d.IdTelemetry == idTelemetry &&
|
||||
|
@ -5,15 +5,14 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudInfrastructure.Services.Cache;
|
||||
using Mapster;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
|
@ -95,7 +95,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
|
||||
entity.IdWell = idWell;
|
||||
entity.Timestamp = data.Timestamp;
|
||||
entity.Data = data.Data;
|
||||
entity.Data = (RawData)data.Data;
|
||||
|
||||
return await db.SaveChangesAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -68,21 +68,20 @@ namespace AsbCloudInfrastructure.Services
|
||||
|
||||
query = query.OrderByDescending(m => m.Date);
|
||||
|
||||
|
||||
var timeOffset = await telemetryService.GetTelemetryTimeZoneOffsetAsync(idTelemetry??default, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (timeOffset is not null)
|
||||
{
|
||||
begin = telemetryService.TimeZoneService.DateToUtc(begin, timeOffset ?? default);
|
||||
end = telemetryService.TimeZoneService.DateToUtc(end, timeOffset ?? default);
|
||||
}
|
||||
var timeZoneOffset = (await telemetryService.GetTimeZoneOffsetAsync(idTelemetry??default, token)
|
||||
.ConfigureAwait(false)) ?? 0;
|
||||
|
||||
if (begin != default)
|
||||
query = query.Where(m => m.Date >= begin);
|
||||
{
|
||||
var beginUtc = telemetryService.TimeZoneService.DateToUtc(begin, timeZoneOffset);
|
||||
query = query.Where(m => m.Date >= beginUtc);
|
||||
}
|
||||
|
||||
if (end != default)
|
||||
query = query.Where(m => m.Date <= end);
|
||||
{
|
||||
var endUtc = telemetryService.TimeZoneService.DateToUtc(end, timeZoneOffset);
|
||||
query = query.Where(m => m.Date <= endUtc);
|
||||
}
|
||||
|
||||
var result = new PaginationContainer<MessageDto>
|
||||
{
|
||||
@ -106,11 +105,14 @@ namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
var messageDto = new MessageDto
|
||||
{
|
||||
Date = message.Date,
|
||||
Id = message.Id,
|
||||
WellDepth = message.WellDepth
|
||||
};
|
||||
|
||||
messageDto.Date = isUtc
|
||||
? message.Date.UtcDateTime
|
||||
: telemetryService.TimeZoneService.DateToTimeZone(message.Date, timeZoneOffset);
|
||||
|
||||
if (message.IdTelemetryUser is not null)
|
||||
{
|
||||
if (users.Any())
|
||||
@ -131,16 +133,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
|
||||
result.Items.Add(messageDto);
|
||||
}
|
||||
|
||||
if (isUtc && timeOffset is not null)
|
||||
return result;
|
||||
|
||||
result.Items = result.Items.Select(m =>
|
||||
{
|
||||
m.Date = telemetryService.TimeZoneService.DateToTimeZone( m.Date, timeOffset ?? default);
|
||||
return m;
|
||||
}).ToList();
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -156,15 +149,18 @@ namespace AsbCloudInfrastructure.Services
|
||||
return null;
|
||||
|
||||
var telemetryId = telemetryService.GetOrCreateTelemetryIdByUid(uid);
|
||||
var timeZoneOffset = telemetryService.GetTimezoneOffset(telemetryId);
|
||||
|
||||
var maxDateDto = dtos.Max(m => m.Date);
|
||||
var maxDateDto = dtos.Max(m => m.Date);
|
||||
var maxDateUtc = maxDateDto.ToUtcDateTimeOffset(timeZoneOffset);
|
||||
telemetryService.SaveRequestDate(uid, maxDateDto);
|
||||
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var entity = dto.Adapt<TelemetryMessage>();
|
||||
var entity = dto.Adapt<TelemetryMessage>();
|
||||
entity.Id = 0;
|
||||
entity.IdTelemetry = telemetryId;
|
||||
entity.Date = dto.Date.ToUtcDateTimeOffset(timeZoneOffset);
|
||||
db.TelemetryMessages.Add(entity);
|
||||
}
|
||||
|
||||
|
@ -57,14 +57,13 @@ namespace AsbCloudInfrastructure.Services
|
||||
dtosList.Remove(duplicate);
|
||||
}
|
||||
|
||||
var offsetHours = await telemetryService.GetTelemetryTimeZoneOffsetAsync(idTelemetry, token);
|
||||
var timeZoneOffset = (await telemetryService.GetTimeZoneOffsetAsync(idTelemetry, token)) ?? 0;
|
||||
|
||||
var entities = dtosList.Select(d => {
|
||||
var e = Convert(d);
|
||||
e.IdTelemetry = idTelemetry;
|
||||
if(offsetHours is not null)
|
||||
e.Date = telemetryService.TimeZoneService.DateToUtc(d.Date, (double)offsetHours);
|
||||
return e;
|
||||
var entities = dtosList.Select(dto => {
|
||||
var entity = Convert(dto);
|
||||
entity.Date = dto.Date.ToUtcDateTimeOffset(timeZoneOffset);
|
||||
entity.IdTelemetry = idTelemetry;
|
||||
return entity;
|
||||
});
|
||||
|
||||
var entityMaxDate = entities.Max(e => e.Date);
|
||||
@ -79,7 +78,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
catch(Exception ex)
|
||||
{
|
||||
stopwatch.Stop();
|
||||
Trace.WriteLine($"Fail to save data telemerty " +
|
||||
Trace.WriteLine($"Fail to save data telemetry " +
|
||||
$"uid: {uid}, " +
|
||||
$"idTelemetry {idTelemetry}, " +
|
||||
$"count: {entities.Count()}, " +
|
||||
@ -100,32 +99,31 @@ namespace AsbCloudInfrastructure.Services
|
||||
|
||||
var idTelemetry = well?.IdTelemetry ?? default;
|
||||
|
||||
var timeZoneOffset = (await telemetryService.GetTimeZoneOffsetAsync(idTelemetry, token)) ?? 0d;
|
||||
|
||||
var filterByDateEnd = dateBegin != default;
|
||||
DateTimeOffset dateBeginUtc;
|
||||
if (dateBegin == default)
|
||||
{
|
||||
dateBegin = telemetryService.GetLastTelemetryDate(idTelemetry);
|
||||
if (dateBegin != default)
|
||||
dateBegin = dateBegin.AddSeconds(-intervalSec);
|
||||
}
|
||||
dateBeginUtc = telemetryService.GetLastTelemetryDate(idTelemetry)
|
||||
.UtcDateTime;
|
||||
if (dateBeginUtc != default)
|
||||
dateBeginUtc = dateBeginUtc.AddSeconds(-intervalSec);
|
||||
}
|
||||
else
|
||||
{
|
||||
dateBeginUtc = dateBegin.ToUtcDateTimeOffset(timeZoneOffset);
|
||||
}
|
||||
|
||||
if (dateBegin == default)
|
||||
dateBegin = DateTime.Now.AddSeconds(-intervalSec);
|
||||
if (dateBeginUtc == default)
|
||||
dateBeginUtc = DateTime.UtcNow.AddSeconds(-intervalSec);
|
||||
|
||||
if (dateBegin.Kind == DateTimeKind.Unspecified)
|
||||
dateBegin = DateTime.SpecifyKind(dateBegin, DateTimeKind.Utc);
|
||||
|
||||
var timeOffset = await telemetryService.GetTelemetryTimeZoneOffsetAsync(idTelemetry, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if(timeOffset is not null)
|
||||
dateBegin = telemetryService.TimeZoneService.DateToUtc(dateBegin, timeOffset?? default);
|
||||
|
||||
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
||||
var dateEnd = dateBeginUtc.AddSeconds(intervalSec);
|
||||
var dbSet = db.Set<TModel>();
|
||||
|
||||
var query = dbSet
|
||||
.Where(d => d.IdTelemetry == idTelemetry
|
||||
&& d.Date >= dateBegin);
|
||||
&& d.Date >= dateBeginUtc);
|
||||
|
||||
if (filterByDateEnd)
|
||||
query = query.Where(d => d.Date < dateEnd);
|
||||
@ -173,12 +171,9 @@ namespace AsbCloudInfrastructure.Services
|
||||
if (isUtc)
|
||||
return dtos;
|
||||
|
||||
if (timeOffset is null)
|
||||
return dtos;
|
||||
|
||||
dtos = dtos.Select(d =>
|
||||
{
|
||||
d.Date = telemetryService.TimeZoneService.DateToTimeZone(d.Date, timeOffset ?? default);
|
||||
d.Date = d.Date.ToTimeZoneOffsetHours(timeZoneOffset);
|
||||
return d;
|
||||
});
|
||||
|
||||
|
@ -16,7 +16,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
public class TelemetryService : ITelemetryService
|
||||
{
|
||||
private readonly CacheTable<Telemetry> cacheTelemetry;
|
||||
private readonly CacheTable<Well> cacheWells;//TODO: use wellService insad of this
|
||||
private readonly CacheTable<Well> cacheWells;//TODO: use wellService instead of this
|
||||
private readonly IAsbCloudDbContext db;
|
||||
private readonly ITelemetryTracker telemetryTracker;
|
||||
private readonly ITimeZoneService timeZoneService;
|
||||
@ -55,15 +55,15 @@ namespace AsbCloudInfrastructure.Services
|
||||
return telemetryDtos;
|
||||
}
|
||||
|
||||
public void SaveRequestDate(string uid, DateTime remoteDate) =>
|
||||
public void SaveRequestDate(string uid, DateTimeOffset remoteDate) =>
|
||||
telemetryTracker.SaveRequestDate(uid, remoteDate);
|
||||
|
||||
public DateTime GetLastTelemetryDate(string telemetryUid) =>
|
||||
public DateTimeOffset GetLastTelemetryDate(string telemetryUid) =>
|
||||
telemetryTracker.GetLastTelemetryDateByUid(telemetryUid);
|
||||
|
||||
public DateTime GetLastTelemetryDate(int telemetryId)
|
||||
public DateTimeOffset GetLastTelemetryDate(int telemetryId)
|
||||
{
|
||||
var lastTelemetryDate = DateTime.MinValue;
|
||||
var lastTelemetryDate = DateTimeOffset.MinValue;
|
||||
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == telemetryId);
|
||||
|
||||
if (telemetry is null)
|
||||
@ -105,9 +105,6 @@ namespace AsbCloudInfrastructure.Services
|
||||
public int? GetIdWellByTelemetryUid(string uid)
|
||||
=> GetWellByTelemetryUid(uid)?.Id;
|
||||
|
||||
public double GetTimezoneOffsetByTelemetryId(int idTelemetry) =>
|
||||
cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry).Info?.TimeZoneOffsetTotalHours ?? 0d;
|
||||
|
||||
public async Task UpdateInfoAsync(string uid, TelemetryInfoDto info,
|
||||
CancellationToken token)
|
||||
{
|
||||
@ -115,8 +112,8 @@ namespace AsbCloudInfrastructure.Services
|
||||
telemetry.Info = info.Adapt<TelemetryInfo>();
|
||||
|
||||
if (!string.IsNullOrEmpty(info.TimeZoneId) &&
|
||||
telemetry.TelemetryTimeZone?.IsOverride != true)
|
||||
telemetry.TelemetryTimeZone = new TelemetryTimeZone()
|
||||
telemetry.TimeZone?.IsOverride != true)
|
||||
telemetry.TimeZone = new TelemetryTimeZone()
|
||||
{
|
||||
Hours = info.TimeZoneOffsetTotalHours,
|
||||
TimeZoneId = info.TimeZoneId
|
||||
@ -126,17 +123,20 @@ namespace AsbCloudInfrastructure.Services
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<double?> GetTelemetryTimeZoneOffsetAsync(int idTelemetry, CancellationToken token)
|
||||
public double GetTimezoneOffset(int idTelemetry) =>
|
||||
cacheTelemetry.FirstOrDefault(t => t.Id == idTelemetry).Info?.TimeZoneOffsetTotalHours ?? 0d;
|
||||
|
||||
public async Task<double?> GetTimeZoneOffsetAsync(int idTelemetry, CancellationToken token)
|
||||
{
|
||||
var telemetry =
|
||||
await cacheTelemetry.FirstOrDefaultAsync(t => t.Id == idTelemetry, token);
|
||||
|
||||
if (!string.IsNullOrEmpty(telemetry.TelemetryTimeZone?.TimeZoneId))
|
||||
return telemetry.TelemetryTimeZone.Hours;
|
||||
if (!string.IsNullOrEmpty(telemetry.TimeZone?.TimeZoneId))
|
||||
return telemetry.TimeZone.Hours;
|
||||
|
||||
if (!string.IsNullOrEmpty(telemetry.Info?.TimeZoneId))
|
||||
{
|
||||
telemetry.TelemetryTimeZone = new TelemetryTimeZone
|
||||
telemetry.TimeZone = new TelemetryTimeZone
|
||||
{
|
||||
Hours = telemetry.Info.TimeZoneOffsetTotalHours,
|
||||
IsOverride = false,
|
||||
@ -162,26 +162,26 @@ namespace AsbCloudInfrastructure.Services
|
||||
if (requestedTimeZone is null)
|
||||
return null;
|
||||
|
||||
telemetry.TelemetryTimeZone = requestedTimeZone.Adapt<TelemetryTimeZone>();
|
||||
telemetry.TimeZone = requestedTimeZone.Adapt<TelemetryTimeZone>();
|
||||
}
|
||||
|
||||
await cacheTelemetry.UpsertAsync(telemetry, token).ConfigureAwait(false);
|
||||
|
||||
return telemetry.TelemetryTimeZone.Hours;
|
||||
return telemetry.TimeZone.Hours;
|
||||
}
|
||||
|
||||
public async Task<DatesRangeDto> DatesRangeToTelemetryTimeZoneAsync(int idTelemetry, DatesRangeDto range,
|
||||
CancellationToken token)
|
||||
{
|
||||
var offset = await GetTelemetryTimeZoneOffsetAsync(idTelemetry, token);
|
||||
var offset = await GetTimeZoneOffsetAsync(idTelemetry, token);
|
||||
|
||||
if (offset is null)
|
||||
return range;
|
||||
|
||||
return new DatesRangeDto()
|
||||
{
|
||||
From = timeZoneService.DateToTimeZone(range.From, offset ?? default),
|
||||
To = timeZoneService.DateToTimeZone(range.To, offset ?? default),
|
||||
From = range.From.ToTimeZoneOffsetHours(offset ?? default),
|
||||
To = range.To.ToTimeZoneOffsetHours(offset ?? default),
|
||||
};
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
var telemetry = GetOrCreateTelemetryByUid(uid);
|
||||
var newTelemetryTimeZone = timeZoneInfo.Adapt<TelemetryTimeZone>();
|
||||
if (newTelemetryTimeZone?.Equals(telemetry.TelemetryTimeZone) == true)
|
||||
if (newTelemetryTimeZone?.Equals(telemetry.TimeZone) == true)
|
||||
return;
|
||||
await cacheTelemetry.UpsertAsync(telemetry, token)
|
||||
.ConfigureAwait(false);
|
||||
@ -231,7 +231,8 @@ namespace AsbCloudInfrastructure.Services
|
||||
if (tele is null)
|
||||
return null;
|
||||
|
||||
return cacheWells.FirstOrDefault(w => w?.IdTelemetry == tele.Id);
|
||||
var well = cacheWells.FirstOrDefault(w => w?.IdTelemetry == tele.Id);
|
||||
return well;
|
||||
}
|
||||
|
||||
private Telemetry GetOrCreateTelemetryByUid(string uid)
|
||||
@ -275,7 +276,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
await transaction.CommitAsync(token).ConfigureAwait(false);
|
||||
|
||||
stopwath.Stop();
|
||||
Console.WriteLine($"Successfully commited in {1d * stopwath.ElapsedMilliseconds / 1000d: #0.00} sec. Affected {affected} rows.");
|
||||
Console.WriteLine($"Successfully committed in {1d * stopwath.ElapsedMilliseconds / 1000d: #0.00} sec. Affected {affected} rows.");
|
||||
return affected;
|
||||
}
|
||||
catch(Exception ex)
|
||||
|
@ -23,17 +23,17 @@ namespace AsbCloudInfrastructure.Services
|
||||
/// <summary>
|
||||
/// Время последнего запроса (по времени сервера)
|
||||
/// </summary>
|
||||
public DateTime LastTimeServer { get; set; }
|
||||
public DateTimeOffset LastTimeServer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата первых данных в БД
|
||||
/// </summary>
|
||||
public DateTime TelemetryDateMin { get; set; }
|
||||
public DateTimeOffset TelemetryDateMin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата последних данных в БД
|
||||
/// </summary>
|
||||
public DateTime TelemetryDateMax { get; set; }
|
||||
public DateTimeOffset TelemetryDateMax { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@ -88,15 +88,9 @@ namespace AsbCloudInfrastructure.Services
|
||||
foreach (var oldReq in oldRequests)
|
||||
{
|
||||
var telemetryStat = telemetriesStats.GetOrAdd(oldReq.Uid, (uid) => new TrackerStat { RemoteUid = uid });
|
||||
var dateMin = oldReq.DateMin.Kind == DateTimeKind.Local
|
||||
? oldReq.DateMin.ToUniversalTime()
|
||||
: oldReq.DateMin;
|
||||
var dateMax = oldReq.DateMax.Kind == DateTimeKind.Local
|
||||
? oldReq.DateMax.ToUniversalTime()
|
||||
: oldReq.DateMax;
|
||||
telemetryStat.TelemetryDateMin = dateMin;
|
||||
telemetryStat.TelemetryDateMax = dateMax;
|
||||
telemetryStat.LastTimeServer = dateMax;
|
||||
telemetryStat.TelemetryDateMin = oldReq.DateMin;
|
||||
telemetryStat.TelemetryDateMax = oldReq.DateMax;
|
||||
telemetryStat.LastTimeServer = oldReq.DateMax;
|
||||
}
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
@ -105,9 +99,9 @@ namespace AsbCloudInfrastructure.Services
|
||||
});
|
||||
}
|
||||
|
||||
private static DateTime ParseDateFromUidOrDefault(string remoteUid, DateTime defaultValue = default)
|
||||
private static DateTimeOffset ParseDateFromUidOrDefault(string remoteUid, DateTime defaultValue = default)
|
||||
{
|
||||
//eg: uid = 20211102_173407926
|
||||
//example: uid = 20211102_173407926
|
||||
if (string.IsNullOrEmpty(remoteUid) || (remoteUid.Length != 18))
|
||||
return defaultValue;
|
||||
|
||||
@ -120,7 +114,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void SaveRequestDate(string uid, DateTime remoteDate)
|
||||
public void SaveRequestDate(string uid, DateTimeOffset remoteDate)
|
||||
{
|
||||
var stat = telemetriesStats.GetOrAdd(uid, _ => new TrackerStat {
|
||||
RemoteUid = uid,
|
||||
@ -133,17 +127,16 @@ namespace AsbCloudInfrastructure.Services
|
||||
stat.TelemetryDateMax = remoteDate;
|
||||
}
|
||||
|
||||
public DateTime GetLastTelemetryDateByUid(string uid) =>
|
||||
public DateTimeOffset GetLastTelemetryDateByUid(string uid) =>
|
||||
telemetriesStats.GetValueOrDefault(uid)?.TelemetryDateMax ?? default;
|
||||
|
||||
|
||||
public DatesRangeDto GetTelemetryDateRangeByUid(string uid)
|
||||
{
|
||||
var stat = telemetriesStats.GetValueOrDefault(uid);
|
||||
var range = new DatesRangeDto
|
||||
{
|
||||
From = stat?.TelemetryDateMin ?? default,
|
||||
To = stat?.TelemetryDateMax ?? default,
|
||||
From = stat?.TelemetryDateMin.UtcDateTime ?? default,
|
||||
To = stat?.TelemetryDateMax.UtcDateTime ?? default,
|
||||
};
|
||||
return range;
|
||||
}
|
||||
|
@ -61,32 +61,6 @@ namespace AsbCloudInfrastructure.Services
|
||||
};
|
||||
}
|
||||
|
||||
public DateTime DateToUtc(DateTime date, double remoteTimezoneOffsetHours)
|
||||
{
|
||||
if (date == default)
|
||||
return new DateTime(0, DateTimeKind.Utc);
|
||||
|
||||
var newDate = date.Kind switch
|
||||
{
|
||||
DateTimeKind.Local => date.ToUniversalTime(),
|
||||
DateTimeKind.Unspecified => date.AddHours(-remoteTimezoneOffsetHours),
|
||||
_ => date,
|
||||
};
|
||||
return DateTime.SpecifyKind(newDate, DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
public DateTime DateToTimeZone(DateTime date, double remoteTimezoneOffsetHours)
|
||||
{
|
||||
if (date == default)
|
||||
return new DateTime(0, DateTimeKind.Unspecified);
|
||||
|
||||
var newDate = date.Kind switch
|
||||
{
|
||||
DateTimeKind.Local => date.ToUniversalTime().AddHours(remoteTimezoneOffsetHours),
|
||||
DateTimeKind.Utc => date.AddHours(remoteTimezoneOffsetHours),
|
||||
_ => date,
|
||||
};
|
||||
return DateTime.SpecifyKind(newDate, DateTimeKind.Unspecified);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,14 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
|
||||
public class WellOperationService : IWellOperationService
|
||||
{
|
||||
private readonly IAsbCloudDbContext db;
|
||||
private readonly IWellService wellService;
|
||||
private readonly CacheTable<WellOperationCategory> cachedOperationCategories;
|
||||
private readonly CacheTable<WellSectionType> cachedSectionTypes;
|
||||
|
||||
public WellOperationService(IAsbCloudDbContext db, CacheDb cache)
|
||||
public WellOperationService(IAsbCloudDbContext db, CacheDb cache, IWellService wellService)
|
||||
{
|
||||
this.db = db;
|
||||
this.wellService = wellService;
|
||||
cachedOperationCategories = cache.GetCachedTable<WellOperationCategory>((DbContext)db);
|
||||
cachedSectionTypes = cache.GetCachedTable<WellSectionType>((DbContext)db);
|
||||
}
|
||||
@ -31,7 +33,6 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
|
||||
public IEnumerable<WellOperationCategoryDto> GetCategories()
|
||||
{
|
||||
var operationTypes = cachedOperationCategories
|
||||
//.Where(oc => oc.Code > 999)
|
||||
.Distinct().OrderBy(o => o.Name);
|
||||
var result = operationTypes.Adapt<WellOperationCategoryDto>();
|
||||
|
||||
@ -56,6 +57,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
|
||||
.Include(s => s.OperationCategory)
|
||||
.Where(s => s.IdWell == idWell);
|
||||
|
||||
var timeZoneOffset = await wellService.GetTimeZoneOffsetAsync(idWell,token);
|
||||
|
||||
if (operationType != default)
|
||||
query = query.Where(e => e.IdType == (int)operationType);
|
||||
|
||||
@ -72,10 +75,14 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
|
||||
query = query.Where(e => e.DepthEnd <= maxDepth);
|
||||
|
||||
if (begin != default)
|
||||
{
|
||||
query = query.Where(e => e.DateStart >= begin);
|
||||
}
|
||||
|
||||
if (end != default)
|
||||
{
|
||||
query = query.Where(e => e.DateStart <= end);
|
||||
}
|
||||
|
||||
var result = new PaginationContainer<WellOperationDto>
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ using AsbCloudInfrastructure.Services.Cache;
|
||||
using Mapster;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -28,6 +29,8 @@ namespace AsbCloudInfrastructure.Services
|
||||
private readonly CacheTable<RelationCompanyWell> cacheRelationCompaniesWells;
|
||||
private readonly CacheTable<CompanyType> cacheCompanyWellTypes;
|
||||
|
||||
public ITelemetryService TelemetryService => telemetryService;
|
||||
|
||||
public WellService(IAsbCloudDbContext db, CacheDb cacheDb, ITelemetryService telemetryService)
|
||||
:base(db, cacheDb)
|
||||
{
|
||||
@ -40,12 +43,12 @@ namespace AsbCloudInfrastructure.Services
|
||||
Includes.Add(nameof(Well.WellType));
|
||||
}
|
||||
|
||||
public DateTime GetLastTelemetryDate(int idWell)
|
||||
public DateTimeOffset GetLastTelemetryDate(int idWell)
|
||||
{
|
||||
var well = Cache.FirstOrDefault(w => w.Id == idWell);
|
||||
|
||||
if (well?.IdTelemetry is null)
|
||||
return DateTime.MinValue;
|
||||
return DateTimeOffset.MinValue;
|
||||
|
||||
var lastTelemetryDate = telemetryService.GetLastTelemetryDate((int)well.IdTelemetry);
|
||||
return lastTelemetryDate;
|
||||
@ -155,7 +158,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
{
|
||||
1 => "В работе",
|
||||
2 => "Завершена",
|
||||
_ => "Незвестно",
|
||||
_ => "Неизвестно",
|
||||
};
|
||||
}
|
||||
|
||||
@ -190,7 +193,7 @@ namespace AsbCloudInfrastructure.Services
|
||||
dto.WellType = entity.WellType?.Caption;
|
||||
dto.Cluster = entity.Cluster?.Caption;
|
||||
dto.Deposit = entity.Cluster?.Deposit?.Caption;
|
||||
dto.LastTelemetryDate = GetLastTelemetryDate(entity.Id);
|
||||
dto.LastTelemetryDate = GetLastTelemetryDate(entity.Id).DateTime;
|
||||
dto.Companies = GetCompanies(entity.Id);
|
||||
return dto;
|
||||
}
|
||||
@ -202,5 +205,26 @@ namespace AsbCloudInfrastructure.Services
|
||||
?? cacheCompanyWellTypes.FirstOrDefault(c => c.Id == entity.IdCompanyType).Caption;
|
||||
return dto;
|
||||
}
|
||||
|
||||
public DateTimeOffset DateToUtc(int idWell, DateTime date)
|
||||
{
|
||||
var GetTimeZoneOffset(int idWell)
|
||||
}
|
||||
|
||||
public DateTime DateToTimeZone(DateTimeOffset date, double remoteTimezoneOffsetHours);
|
||||
|
||||
public double? GetTimeZoneOffset(int idWell)
|
||||
{
|
||||
// TODO: Add timeZoneOffset into Db.Well.
|
||||
var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell);
|
||||
if (idTelemetry is not null)
|
||||
{
|
||||
var timeZoneOffset = telemetryService.GetTimeZoneOffset((int)idTelemetry);
|
||||
if (timeZoneOffset is not null)
|
||||
return timeZoneOffset;
|
||||
}
|
||||
Trace.WriteLine("No timeZoneOffset");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,9 +46,6 @@ namespace AsbCloudWebApi.Controllers
|
||||
if (take > 1024)
|
||||
return BadRequest("limit mast be less then 1024");
|
||||
|
||||
if (begin > DateTime.Now)
|
||||
begin = default;
|
||||
|
||||
var result = await messageService.GetMessagesAsync(idWell,
|
||||
categoryids, begin, end, searchString,
|
||||
skip, take, isUtc, token).ConfigureAwait(false);
|
||||
|
@ -85,7 +85,7 @@ namespace AsbCloudWebApi.Controllers
|
||||
|
||||
if (!isCompanyOwnsWell)
|
||||
return Forbid();
|
||||
|
||||
|
||||
var content = await telemetryDataService.GetAsync(idWell, begin,
|
||||
intervalSec, approxPointsCount, isUtc, token).ConfigureAwait(false);
|
||||
|
||||
|
@ -132,7 +132,7 @@ namespace AsbCloudWebApi.Controllers
|
||||
/// <param name="idWell">id скважины</param>
|
||||
/// <param name="values">Данные о добавляемых операциях</param>
|
||||
/// <param name="token">Токен отмены задачи</param>
|
||||
/// <returns>Количество добавленых в БД строк</returns>
|
||||
/// <returns>Количество добавленных в БД строк</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(IEnumerable<WellOperationDto>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> InsertRangeAsync(int idWell, [FromBody] IEnumerable<WellOperationDto> values,
|
||||
@ -150,8 +150,8 @@ namespace AsbCloudWebApi.Controllers
|
||||
/// Обновляет выбранную операцию на скважине
|
||||
/// </summary>
|
||||
/// <param name="idWell">id скважины</param>
|
||||
/// <param name="idOperation">id выбраной операции</param>
|
||||
/// <param name="value">Новые данные для выбраной операции</param>
|
||||
/// <param name="idOperation">id выбранной операции</param>
|
||||
/// <param name="value">Новые данные для выбранной операции</param>
|
||||
/// <param name="token">Токен отмены задачи</param>
|
||||
/// <returns>Количество обновленных в БД строк</returns>
|
||||
[HttpPut("{idOperation}")]
|
||||
@ -168,10 +168,10 @@ namespace AsbCloudWebApi.Controllers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаляет выбраную операцию на скважине
|
||||
/// Удаляет выбранную операцию на скважине
|
||||
/// </summary>
|
||||
/// <param name="idWell">id скважины</param>
|
||||
/// <param name="idOperation">id выбраной операции</param>
|
||||
/// <param name="idOperation">id выбранной операции</param>
|
||||
/// <param name="token">Токен отмены задачи</param>
|
||||
/// <returns>Количество удаленных из БД строк</returns>
|
||||
[HttpDelete("{idOperation}")]
|
||||
@ -264,7 +264,7 @@ namespace AsbCloudWebApi.Controllers
|
||||
/// </summary>
|
||||
/// <returns>Запрашиваемый файл</returns>
|
||||
[HttpGet]
|
||||
[Route("tamplate")]
|
||||
[Route("template")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
|
||||
public IActionResult GetTamplate()
|
||||
|
34
AsbCloudWebApi/Docs/about using DateTime[Offset].md
Normal file
34
AsbCloudWebApi/Docs/about using DateTime[Offset].md
Normal file
@ -0,0 +1,34 @@
|
||||
## Проблема
|
||||
Скважины и пользователи ЕЦП расположены на различных часовых поясах.
|
||||
В БД время хранится только в UTC.
|
||||
На страницах ЕЦП время везде должно отображаться в часовом поясе скважины.
|
||||
Web Api должен понимать при обращении время как в UTC `2021-12-29T07:00:00Z`, так и с указанием часового пояса `2021-12-29T12:00:00Z5`.
|
||||
|
||||
## Решение
|
||||
В БД уже хранится часовой пояс скважины в таблице телеметрии.
|
||||
На стороне backEnd публичные методы контроллеров и методы сервисов, которые вызываются из контроллеров должны понимать параметры времени как тип DateTime, затем приводить его к UTC.
|
||||
Если DateTime.Kind == unspecified, то считается что это время указанное в часовом поясе скважины.
|
||||
При переходе на DateTimeOffset флаги isUTC не нужны
|
||||
Даты в Model - используют DateTimeOffset.
|
||||
Даты в Dto - используют DateTime без указания часового пояса во времени скважины.
|
||||
При получении Dto от фронта с kind == unspecified дата приводится к UTC как будто она в часовом поясе скважины.
|
||||
Перед отправкой клиенту в Dto все даты приводятся к часовому поясу скважины и kind устанавливается как unspecified.
|
||||
|
||||
## Affected
|
||||
ReportController
|
||||
.CreateReportAsync
|
||||
.GetReportSizeAsync
|
||||
.GetReportsDateRangeAsync
|
||||
|
||||
TelemetryDataBaseController
|
||||
.GetDataAsync
|
||||
.GetDataDatesRangeAsync
|
||||
|
||||
MessageController
|
||||
.GetMessagesAsync
|
||||
.GetMessagesDateRangeAsync
|
||||
|
||||
WellOperationController
|
||||
.GetOperationsAsync
|
||||
.InsertRangeAsync
|
||||
.UpdateAsync
|
@ -1,24 +1,40 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.fb3df553.chunk.css",
|
||||
"main.js": "/static/js/main.47b40915.chunk.js",
|
||||
"main.js.map": "/static/js/main.47b40915.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.6870c5e2.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.6870c5e2.js.map",
|
||||
"static/js/2.8306ac4d.chunk.js": "/static/js/2.8306ac4d.chunk.js",
|
||||
"static/js/2.8306ac4d.chunk.js.map": "/static/js/2.8306ac4d.chunk.js.map",
|
||||
"static/js/3.c22d92b4.chunk.js": "/static/js/3.c22d92b4.chunk.js",
|
||||
"static/js/3.c22d92b4.chunk.js.map": "/static/js/3.c22d92b4.chunk.js.map",
|
||||
"main.css": "/static/css/main.dd1fcee2.chunk.css",
|
||||
"main.js": "/static/js/main.b9f2543d.chunk.js",
|
||||
"main.js.map": "/static/js/main.b9f2543d.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.e4d23dc4.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.e4d23dc4.js.map",
|
||||
"static/js/2.c978f7e7.chunk.js": "/static/js/2.c978f7e7.chunk.js",
|
||||
"static/js/2.c978f7e7.chunk.js.map": "/static/js/2.c978f7e7.chunk.js.map",
|
||||
"static/js/3.6446ff6d.chunk.js": "/static/js/3.6446ff6d.chunk.js",
|
||||
"static/js/3.6446ff6d.chunk.js.map": "/static/js/3.6446ff6d.chunk.js.map",
|
||||
"static/js/4.eb6dbaeb.chunk.js": "/static/js/4.eb6dbaeb.chunk.js",
|
||||
"static/js/4.eb6dbaeb.chunk.js.map": "/static/js/4.eb6dbaeb.chunk.js.map",
|
||||
"static/js/5.7a9fb752.chunk.js": "/static/js/5.7a9fb752.chunk.js",
|
||||
"static/js/5.7a9fb752.chunk.js.map": "/static/js/5.7a9fb752.chunk.js.map",
|
||||
"static/js/6.61991758.chunk.js": "/static/js/6.61991758.chunk.js",
|
||||
"static/js/6.61991758.chunk.js.map": "/static/js/6.61991758.chunk.js.map",
|
||||
"static/js/7.a1c2547f.chunk.js": "/static/js/7.a1c2547f.chunk.js",
|
||||
"static/js/7.a1c2547f.chunk.js.map": "/static/js/7.a1c2547f.chunk.js.map",
|
||||
"static/js/8.2a766587.chunk.js": "/static/js/8.2a766587.chunk.js",
|
||||
"static/js/8.2a766587.chunk.js.map": "/static/js/8.2a766587.chunk.js.map",
|
||||
"static/js/9.6ba456d9.chunk.js": "/static/js/9.6ba456d9.chunk.js",
|
||||
"static/js/9.6ba456d9.chunk.js.map": "/static/js/9.6ba456d9.chunk.js.map",
|
||||
"static/js/10.f5187699.chunk.js": "/static/js/10.f5187699.chunk.js",
|
||||
"static/js/10.f5187699.chunk.js.map": "/static/js/10.f5187699.chunk.js.map",
|
||||
"static/js/11.37e8bbc7.chunk.js": "/static/js/11.37e8bbc7.chunk.js",
|
||||
"static/js/11.37e8bbc7.chunk.js.map": "/static/js/11.37e8bbc7.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"static/css/main.fb3df553.chunk.css.map": "/static/css/main.fb3df553.chunk.css.map",
|
||||
"static/js/2.8306ac4d.chunk.js.LICENSE.txt": "/static/js/2.8306ac4d.chunk.js.LICENSE.txt",
|
||||
"static/css/main.dd1fcee2.chunk.css.map": "/static/css/main.dd1fcee2.chunk.css.map",
|
||||
"static/js/2.c978f7e7.chunk.js.LICENSE.txt": "/static/js/2.c978f7e7.chunk.js.LICENSE.txt",
|
||||
"static/media/ClusterIcon.a395f860.svg": "/static/media/ClusterIcon.a395f860.svg",
|
||||
"static/media/DepositIcon.6de7c7ae.svg": "/static/media/DepositIcon.6de7c7ae.svg"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.6870c5e2.js",
|
||||
"static/js/2.8306ac4d.chunk.js",
|
||||
"static/css/main.fb3df553.chunk.css",
|
||||
"static/js/main.47b40915.chunk.js"
|
||||
"static/js/runtime-main.e4d23dc4.js",
|
||||
"static/js/2.c978f7e7.chunk.js",
|
||||
"static/css/main.dd1fcee2.chunk.css",
|
||||
"static/js/main.b9f2543d.chunk.js"
|
||||
]
|
||||
}
|
@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="manifest" href="/manifest.json"/><title>АСБ Vision</title><link href="/static/css/main.fb3df553.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,a,i=r[0],c=r[1],l=r[2],s=0,p=[];s<i.length;s++)a=i[s],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&p.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(f&&f(r);p.length;)p.shift()();return u.push.apply(u,l||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var c=t[i];0!==o[c]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+"static/js/"+({}[e]||e)+"."+{3:"c22d92b4"}[e]+".chunk.js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(l);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var l=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/",a.oe=function(e){throw console.error(e),e};var i=this.webpackJsonpasb_cloud_front_react=this.webpackJsonpasb_cloud_front_react||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var l=0;l<i.length;l++)r(i[l]);var f=c;t()}([])</script><script src="/static/js/2.8306ac4d.chunk.js"></script><script src="/static/js/main.47b40915.chunk.js"></script></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="manifest" href="/manifest.json"/><title>АСБ Vision</title><link href="/static/css/main.dd1fcee2.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,u,i=r[0],c=r[1],f=r[2],s=0,p=[];s<i.length;s++)u=i[s],Object.prototype.hasOwnProperty.call(o,u)&&o[u]&&p.push(o[u][0]),o[u]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);p.length;)p.shift()();return a.push.apply(a,f||[]),t()}function t(){for(var e,r=0;r<a.length;r++){for(var t=a[r],n=!0,i=1;i<t.length;i++){var c=t[i];0!==o[c]&&(n=!1)}n&&(a.splice(r--,1),e=u(u.s=t[0]))}return e}var n={},o={1:0},a=[];function u(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,u),t.l=!0,t.exports}u.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var a,i=document.createElement("script");i.charset="utf-8",i.timeout=120,u.nc&&i.setAttribute("nonce",u.nc),i.src=function(e){return u.p+"static/js/"+({}[e]||e)+"."+{3:"6446ff6d",4:"eb6dbaeb",5:"7a9fb752",6:"61991758",7:"a1c2547f",8:"2a766587",9:"6ba456d9",10:"f5187699",11:"37e8bbc7"}[e]+".chunk.js"}(e);var c=new Error;a=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+a+")",c.name="ChunkLoadError",c.type=n,c.request=a,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){a({type:"timeout",target:i})}),12e4);i.onerror=i.onload=a,document.head.appendChild(i)}return Promise.all(r)},u.m=e,u.c=n,u.d=function(e,r,t){u.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},u.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,r){if(1&r&&(e=u(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(u.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)u.d(t,n,function(r){return e[r]}.bind(null,n));return t},u.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(r,"a",r),r},u.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},u.p="/",u.oe=function(e){throw console.error(e),e};var i=this.webpackJsonpasb_cloud_front_react=this.webpackJsonpasb_cloud_front_react||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([])</script><script src="/static/js/2.c978f7e7.chunk.js"></script><script src="/static/js/main.b9f2543d.chunk.js"></script></body></html>
|
Loading…
Reference in New Issue
Block a user