#408 Репозиторий хранения данных WITS0 #7
@ -6,6 +6,9 @@ using Persistence.Services.Interfaces;
|
||||
|
||||
namespace Persistence.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Работа с параметрами Wits
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("api/[controller]")]
|
||||
@ -51,15 +54,17 @@ public class WitsDataController : ControllerBase, IWitsDataApi
|
||||
/// <summary>
|
||||
/// Получить набор параметров (Wits) для построения графика
|
||||
/// </summary>
|
||||
/// <param name="dateFrom"></param>
|
||||
/// <param name="dateTo"></param>
|
||||
/// <param name="limit"></param>
|
||||
/// <param name="discriminatorId">Дискриминатор системы</param>
|
||||
/// <param name="dateFrom">Начало временного интервала</param>
|
||||
/// <param name="dateTo">Конец временного интервала</param>
|
||||
/// <param name="approxPointsCount">Количество точек</param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("graph")]
|
||||
public async Task<ActionResult<IEnumerable<WitsDataDto>>> GetValuesForGraph([FromQuery] DateTimeOffset dateFrom, [FromQuery] DateTimeOffset dateTo, [FromQuery] int limit, CancellationToken token)
|
||||
public async Task<ActionResult<IEnumerable<WitsDataDto>>> GetValuesForGraph([FromQuery] int discriminatorId,
|
||||
|
||||
[FromQuery] DateTimeOffset dateFrom, [FromQuery] DateTimeOffset dateTo, [FromQuery] int approxPointsCount, CancellationToken token)
|
||||
{
|
||||
var result = await witsDataService.GetValuesForGraph(dateFrom, dateTo);
|
||||
var result = await witsDataService.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointsCount, token);
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
@ -72,10 +77,10 @@ public class WitsDataController : ControllerBase, IWitsDataApi
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)]
|
||||
public async Task<IActionResult> InsertRange([FromBody] IEnumerable<WitsDataDto> dtos, CancellationToken token)
|
||||
public async Task<IActionResult> AddRange([FromBody] IEnumerable<WitsDataDto> dtos, CancellationToken token)
|
||||
{
|
||||
var result = await witsDataService.InsertRange(dtos, token);
|
||||
var result = await witsDataService.AddRange(dtos, token);
|
||||
|
||||
return CreatedAtAction(nameof(InsertRange), result);
|
||||
return CreatedAtAction(nameof(AddRange), result);
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,10 @@ public interface IWitsDataClient
|
||||
private const string BaseRoute = "/api/witsData";
|
||||
|
||||
[Get($"{BaseRoute}/graph")]
|
||||
Task<IApiResponse<IEnumerable<WitsDataDto>>> GetValuesForGraph([Query] DateTimeOffset dateFrom, [Query] DateTimeOffset dateTo, [Query] int limit, CancellationToken token);
|
||||
Task<IApiResponse<IEnumerable<WitsDataDto>>> GetValuesForGraph([Query] int discriminatorId, [Query] DateTimeOffset dateFrom, [Query] DateTimeOffset dateTo, [Query] int approxPointsCount, CancellationToken token);
|
||||
on.nemtina
commented
discriminatorId лучше добавить в роут discriminatorId лучше добавить в роут
|
||||
|
||||
[Post($"{BaseRoute}/")]
|
||||
Task<IApiResponse<int>> InsertRange([Body] IEnumerable<WitsDataDto> dtos, CancellationToken token);
|
||||
Task<IApiResponse<int>> AddRange([Body] IEnumerable<WitsDataDto> dtos, CancellationToken token);
|
||||
|
||||
[Get($"{BaseRoute}/part")]
|
||||
Task<IApiResponse<IEnumerable<WitsDataDto>>> GetPart([Query] int discriminatorId, [Query] DateTimeOffset dateBegin, [Query] int take = 24 * 60 * 60, CancellationToken token = default);
|
||||
|
@ -62,7 +62,7 @@ public class WitsDataControllerTest : BaseIntegrationTest
|
||||
dbContext.CleanupDbSet<ParameterData>();
|
||||
|
||||
//act
|
||||
await InsertRange();
|
||||
await AddRange();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -71,19 +71,27 @@ public class WitsDataControllerTest : BaseIntegrationTest
|
||||
//arrange
|
||||
dbContext.CleanupDbSet<ParameterData>();
|
||||
|
||||
var discriminatorId = 1;
|
||||
var dateFrom = DateTimeOffset.UtcNow;
|
||||
var dateTo = DateTimeOffset.UtcNow;
|
||||
var approxPointCount = 12;
|
||||
|
||||
//act
|
||||
var response = await witsDataClient.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointCount, new CancellationToken());
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
Assert.Empty(response.Content);
|
||||
}
|
||||
|
||||
#region AfterSave
|
||||
[Fact]
|
||||
public async Task GetDatesRangeAsync_AfterSave_returns_success()
|
||||
{
|
||||
//arrange
|
||||
dbContext.CleanupDbSet<ParameterData>();
|
||||
|
||||
var dtos = await InsertRange();
|
||||
var dtos = await AddRange();
|
||||
var discriminatorId = dtos.FirstOrDefault()!.DiscriminatorId;
|
||||
|
||||
//act
|
||||
@ -116,7 +124,7 @@ public class WitsDataControllerTest : BaseIntegrationTest
|
||||
//arrange
|
||||
dbContext.CleanupDbSet<ParameterData>();
|
||||
|
||||
var dtos = await InsertRange();
|
||||
var dtos = await AddRange();
|
||||
var discriminatorId = dtos.FirstOrDefault()!.DiscriminatorId;
|
||||
var dateBegin = dtos.FirstOrDefault()!.Timestamped;
|
||||
var take = 1;
|
||||
@ -134,11 +142,24 @@ public class WitsDataControllerTest : BaseIntegrationTest
|
||||
[Fact]
|
||||
public async Task GetValuesForGraph_AfterSave_returns_success()
|
||||
{
|
||||
//arrange
|
||||
dbContext.CleanupDbSet<ParameterData>();
|
||||
|
||||
var dtos = await AddRange(37);
|
||||
var discriminatorId = dtos.FirstOrDefault()!.DiscriminatorId;
|
||||
var dateFrom = dtos.Select(e => e.Timestamped).Min();
|
||||
var dateTo = dtos.Select(e => e.Timestamped).Max();
|
||||
var approxPointCount = 12;
|
||||
|
||||
//act
|
||||
var response = await witsDataClient.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointCount, new CancellationToken());
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
Assert.Equal(approxPointCount, response.Content.Count());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BadRequest
|
||||
[Fact]
|
||||
public async Task InsertRange_returns_BadRequest()
|
||||
on.nemtina
commented
AddRange_returns_BadRequest AddRange_returns_BadRequest
|
||||
{
|
||||
@ -155,63 +176,43 @@ public class WitsDataControllerTest : BaseIntegrationTest
|
||||
{
|
||||
RecordId = -1, // < 0
|
||||
ItemId = 101, // > 100
|
||||
Value = "string value"
|
||||
Value = string.Empty
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//act
|
||||
var response = await witsDataClient.InsertRange(dtos, new CancellationToken());
|
||||
var response = await witsDataClient.AddRange(dtos, new CancellationToken());
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private async Task<IEnumerable<WitsDataDto>> InsertRange()
|
||||
private async Task<IEnumerable<WitsDataDto>> AddRange(int countToCreate = 10)
|
||||
{
|
||||
//arrange
|
||||
var dtos = new List<WitsDataDto>()
|
||||
var dtos = new List<WitsDataDto>();
|
||||
var timestamped = DateTimeOffset.UtcNow;
|
||||
for (var i = 0; i < countToCreate && i < 100; i++)
|
||||
on.nemtina
commented
i < countToCreate && i < 100 i < countToCreate && i < 100
А это так и нужно?
rs.efremov
commented
По сути нет, это на всякий случай - вдруг кому то когда нибудь придёт идея написать в этом контроллере тест и передать в качестве count >100. Хотя, наверное, лучше тогда человеку сразу увидеть ошибку, чем гадать - почему он говорит создать 150 записей, а создаётся 100 )) По сути нет, это на всякий случай - вдруг кому то когда нибудь придёт идея написать в этом контроллере тест и передать в качестве count >100. Хотя, наверное, лучше тогда человеку сразу увидеть ошибку, чем гадать - почему он говорит создать 150 записей, а создаётся 100 ))
|
||||
{
|
||||
new WitsDataDto()
|
||||
dtos.Add(new WitsDataDto()
|
||||
{
|
||||
DiscriminatorId = 1,
|
||||
Timestamped = DateTimeOffset.UtcNow,
|
||||
Timestamped = timestamped.AddSeconds(i),
|
||||
Values = new List<WitsValueDto>()
|
||||
{
|
||||
new WitsValueDto()
|
||||
{
|
||||
RecordId = 11,
|
||||
ItemId = 22,
|
||||
Value = "string value"
|
||||
},
|
||||
new WitsValueDto()
|
||||
{
|
||||
RecordId = 11,
|
||||
ItemId = 27,
|
||||
Value = 2.22
|
||||
RecordId = i + 1,
|
||||
ItemId = i + 1,
|
||||
Value = new Random().Next(1, 100)
|
||||
on.nemtina
commented
Лучше new Random() вынести на уровень выше, чтобы в цикле не создавался каждый раз новый экземпляр Лучше new Random() вынести на уровень выше, чтобы в цикле не создавался каждый раз новый экземпляр
|
||||
}
|
||||
}
|
||||
},
|
||||
new WitsDataDto()
|
||||
{
|
||||
DiscriminatorId = 2,
|
||||
Timestamped = DateTimeOffset.UtcNow,
|
||||
Values = new List<WitsValueDto>()
|
||||
{
|
||||
new WitsValueDto()
|
||||
{
|
||||
RecordId = 13,
|
||||
ItemId = 14,
|
||||
Value = "string value"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
//act
|
||||
var response = await witsDataClient.InsertRange(dtos, new CancellationToken());
|
||||
var response = await witsDataClient.AddRange(dtos, new CancellationToken());
|
||||
|
||||
//assert
|
||||
var count = dtos.SelectMany(e => e.Values).Count();
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Persistence.Database.Entity;
|
||||
using Persistence.Models;
|
||||
using Persistence.Repositories;
|
||||
@ -49,12 +50,31 @@ public class ParameterRepository : IParameterRepository
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public Task<ParameterDto> GetValuesForGraph(DateTimeOffset dateFrom, DateTimeOffset dateTo)
|
||||
public async Task<IEnumerable<ParameterDto>> GetValuesForGraph(int discriminatorId, DateTimeOffset dateFrom, DateTimeOffset dateTo,
|
||||
int approxPointsCount, int? ratio, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var query = db.Set<ParameterData>().AsNoTracking();
|
||||
var universalDateFrom = dateFrom.ToUniversalTime();
|
||||
var universalDateTo = dateTo.ToUniversalTime();
|
||||
|
||||
query = query
|
||||
.Where(e => e.DiscriminatorId == discriminatorId && e.Timestamp >= universalDateFrom && e.Timestamp <= universalDateTo)
|
||||
on.nemtina
commented
Тут для удобства чтения лучше разделиnь Where на 2 части: Тут для удобства чтения лучше разделиnь Where на 2 части:
.Where(e => e.DiscriminatorId == discriminatorId)
.Where(e => e.Timestamp >= universalDateFrom && e.Timestamp <= universalDateTo)
|
||||
.OrderBy(e => e.Timestamp);
|
||||
if (ratio != null)
|
||||
{
|
||||
query = query.Where(e => ((int) (e.Timestamp - dateFrom).TotalSeconds) % ratio == 0);
|
||||
}
|
||||
|
||||
var entities = await query
|
||||
.Take((int)(2.5 * approxPointsCount))
|
||||
.ToListAsync(token);
|
||||
|
||||
var dtos = entities.Select(e => e.Adapt<ParameterDto>());
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task<int> InsertRange(IEnumerable<ParameterDto> dtos, CancellationToken token)
|
||||
public async Task<int> AddRange(IEnumerable<ParameterDto> dtos, CancellationToken token)
|
||||
{
|
||||
var entities = dtos.Select(e => e.Adapt<ParameterData>());
|
||||
|
||||
|
@ -11,10 +11,14 @@ public interface IWitsDataApi : ISyncWithDiscriminatorApi<WitsDataDto>
|
||||
/// <summary>
|
||||
/// Получить набор параметров (Wits) для построения графика
|
||||
/// </summary>
|
||||
/// <param name="discriminatorId"></param>
|
||||
/// <param name="dateFrom"></param>
|
||||
/// <param name="dateTo"></param>
|
||||
/// <param name="approxPointsCount"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<ActionResult<IEnumerable<WitsDataDto>>> GetValuesForGraph(DateTimeOffset dateFrom, DateTimeOffset dateTo, int limit, CancellationToken token);
|
||||
Task<ActionResult<IEnumerable<WitsDataDto>>> GetValuesForGraph(int discriminatorId, DateTimeOffset dateFrom, DateTimeOffset dateTo,
|
||||
int approxPointsCount, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Сохранить набор параметров (Wits)
|
||||
@ -22,5 +26,5 @@ public interface IWitsDataApi : ISyncWithDiscriminatorApi<WitsDataDto>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IActionResult> InsertRange(IEnumerable<WitsDataDto> dtos, CancellationToken token);
|
||||
Task<IActionResult> AddRange(IEnumerable<WitsDataDto> dtos, CancellationToken token);
|
||||
}
|
||||
|
12
Persistence/Models/Configurations/WitsInfo.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Persistence.Models.Enumerations;
|
||||
|
||||
namespace Persistence.Models.Configurations;
|
||||
|
||||
public class WitsInfo
|
||||
on.nemtina
commented
Тут нужны комментарии, без комментариев не очень понятно Тут нужны комментарии, без комментариев не очень понятно
|
||||
{
|
||||
public int RecordId { get; set; }
|
||||
|
||||
public int ItemId { get; set; }
|
||||
|
||||
public WitsType ValueType { get; set; }
|
||||
}
|
24
Persistence/Models/Enumerations/WitsType.cs
Normal file
@ -0,0 +1,24 @@
|
||||
namespace Persistence.Models.Enumerations;
|
||||
|
||||
/// <summary>
|
||||
/// WITS Data Type Codes
|
||||
/// </summary>
|
||||
public enum WitsType
|
||||
{
|
||||
/// <summary>
|
||||
/// Alphanumeric, Rep Code = 65
|
||||
/// </summary>
|
||||
A,
|
||||
/// <summary>
|
||||
/// 32 bit 2's complement signed integer, Rep Code = 73
|
||||
/// </summary>
|
||||
L,
|
||||
/// <summary>
|
||||
/// 16 bit 2's complement signed integer, Rep Code = 79
|
||||
/// </summary>
|
||||
S,
|
||||
/// <summary>
|
||||
/// 32 bit IEEE single precision floating point, Rep Code = 128
|
||||
/// </summary>
|
||||
F,
|
||||
}
|
@ -6,6 +6,14 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Services\Config\WitsConfig.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Services\Config\WitsConfig.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||
|
@ -22,10 +22,15 @@ public interface IParameterRepository
|
||||
/// <summary>
|
||||
/// Получить набор параметров (Wits) для построения графика
|
||||
/// </summary>
|
||||
/// <param name="discriminatorId"></param>
|
||||
/// <param name="dateFrom"></param>
|
||||
/// <param name="dateTo"></param>
|
||||
/// <param name="approxPointsCount"></param>
|
||||
/// <param name="ratio"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<ParameterDto> GetValuesForGraph(DateTimeOffset dateFrom, DateTimeOffset dateTo);
|
||||
Task<IEnumerable<ParameterDto>> GetValuesForGraph(int discriminatorId, DateTimeOffset dateFrom, DateTimeOffset dateTo,
|
||||
int approxPointsCount, int? ratio, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Сохранить набор параметров (Wits)
|
||||
@ -34,5 +39,5 @@ public interface IParameterRepository
|
||||
/// <param name="witsIds"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> InsertRange(IEnumerable<ParameterDto> dtos, CancellationToken token);
|
||||
Task<int> AddRange(IEnumerable<ParameterDto> dtos, CancellationToken token);
|
||||
}
|
||||
|
12866
Persistence/Services/Config/WitsConfig.json
Normal file
@ -1,10 +1,46 @@
|
||||
using Persistence.Models;
|
||||
|
||||
namespace Persistence.Services.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Сервис для работы с параметрами Wits
|
||||
/// </summary>
|
||||
public interface IWitsDataService
|
||||
{
|
||||
Task<DatesRangeDto> GetDatesRangeAsync(int idDiscriminator, CancellationToken token);
|
||||
/// <summary>
|
||||
/// Получить набор параметров для построения графика
|
||||
/// </summary>
|
||||
/// <param name="idDiscriminator"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<DatesRangeDto> GetDatesRangeAsync(int idDiscriminator, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получить порцию записей, начиная с заданной даты
|
||||
/// </summary>
|
||||
/// <param name="idDiscriminator"></param>
|
||||
/// <param name="dateBegin"></param>
|
||||
/// <param name="take"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<WitsDataDto>> GetPart(int idDiscriminator, DateTimeOffset dateBegin, int take, CancellationToken token);
|
||||
Task<WitsDataDto> GetValuesForGraph(DateTimeOffset dateFrom, DateTimeOffset dateTo);
|
||||
Task<int> InsertRange(IEnumerable<WitsDataDto> dtos, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получить диапазон дат, для которых есть данные в репозитории
|
||||
/// </summary>
|
||||
/// <param name="discriminatorId"></param>
|
||||
/// <param name="dateFrom"></param>
|
||||
/// <param name="dateTo"></param>
|
||||
/// <param name="approxPointsCount"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<WitsDataDto>> GetValuesForGraph(int discriminatorId, DateTimeOffset dateFrom, DateTimeOffset dateTo, int approxPointsCount, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Сохранить набор параметров
|
||||
/// </summary>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> AddRange(IEnumerable<WitsDataDto> dtos, CancellationToken token);
|
||||
}
|
@ -1,15 +1,28 @@
|
||||
using Persistence.Models;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Persistence.Models;
|
||||
using Persistence.Repositories;
|
||||
using Persistence.Services.Interfaces;
|
||||
using Persistence.Models.Configurations;
|
||||
using Persistence.Models.Enumerations;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Persistence.Services;
|
||||
public class WitsDataService : IWitsDataService
|
||||
{
|
||||
private readonly IParameterRepository witsDataRepository;
|
||||
|
||||
private readonly WitsInfo[] witsInfo;
|
||||
|
||||
private const int multiplier = 1000;
|
||||
public WitsDataService(IParameterRepository witsDataRepository)
|
||||
private const string witsConfigPath = "Persistence.Services.Config.WitsConfig.json";
|
||||
|
||||
public WitsDataService(IParameterRepository witsDataRepository, IConfiguration configuration)
|
||||
on.nemtina
commented
IConfiguration configuration можно удалить, он нигде не используется IConfiguration configuration можно удалить, он нигде не используется
|
||||
{
|
||||
this.witsDataRepository = witsDataRepository;
|
||||
|
||||
this.witsInfo = GetWitsInfo();
|
||||
}
|
||||
|
||||
public Task<DatesRangeDto> GetDatesRangeAsync(int idDiscriminator, CancellationToken token)
|
||||
@ -23,37 +36,30 @@ public class WitsDataService : IWitsDataService
|
||||
{
|
||||
var dtos = await witsDataRepository.GetPart(idDiscriminator, dateBegin, take, token);
|
||||
|
||||
var result = new List<WitsDataDto>();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var witsDataDto = result.FirstOrDefault(e => e.DiscriminatorId == dto.DiscriminatorId && e.Timestamped == dto.Timestamp);
|
||||
if (witsDataDto == null)
|
||||
{
|
||||
witsDataDto = new WitsDataDto()
|
||||
{
|
||||
DiscriminatorId = dto.DiscriminatorId,
|
||||
Timestamped = dto.Timestamp
|
||||
};
|
||||
result.Add(witsDataDto);
|
||||
}
|
||||
var witsValueDto = new WitsValueDto()
|
||||
{
|
||||
RecordId = DecodeRecordId(dto.ParameterId),
|
||||
ItemId = DecodeItemId(dto.ParameterId),
|
||||
Value = dto.Value
|
||||
};
|
||||
witsDataDto.Values.Append(witsValueDto);
|
||||
}
|
||||
var result = AdaptToWitsData(dtos);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Task<WitsDataDto> GetValuesForGraph(DateTimeOffset dateFrom, DateTimeOffset dateTo)
|
||||
public async Task<IEnumerable<WitsDataDto>> GetValuesForGraph(int discriminatorId, DateTimeOffset dateFrom, DateTimeOffset dateTo,
|
||||
int approxPointsCount, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var intervalSec = (dateTo - dateFrom).TotalSeconds;
|
||||
|
||||
int? ratio = null;
|
||||
if (intervalSec > 2 * approxPointsCount)
|
||||
{
|
||||
ratio = (int) intervalSec / approxPointsCount;
|
||||
}
|
||||
|
||||
var dtos = await witsDataRepository.GetValuesForGraph(discriminatorId, dateFrom, dateTo, approxPointsCount, ratio, token);
|
||||
|
||||
var result = AdaptToWitsData(dtos);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<int> InsertRange(IEnumerable<WitsDataDto> dtos, CancellationToken token)
|
||||
public async Task<int> AddRange(IEnumerable<WitsDataDto> dtos, CancellationToken token)
|
||||
{
|
||||
var parameterDtos = dtos.SelectMany(e => e.Values.Select(t => new ParameterDto()
|
||||
{
|
||||
@ -62,7 +68,7 @@ public class WitsDataService : IWitsDataService
|
||||
Value = t.Value.ToString()!,
|
||||
Timestamp = e.Timestamped
|
||||
}));
|
||||
var result = await witsDataRepository.InsertRange(parameterDtos, token);
|
||||
var result = await witsDataRepository.AddRange(parameterDtos, token);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -86,4 +92,81 @@ public class WitsDataService : IWitsDataService
|
||||
|
||||
return resultId;
|
||||
}
|
||||
|
||||
private IEnumerable<WitsDataDto> AdaptToWitsData(IEnumerable<ParameterDto> dtos)
|
||||
{
|
||||
var result = new List<WitsDataDto>();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var witsDataDto = result.FirstOrDefault(e => e.DiscriminatorId == dto.DiscriminatorId && e.Timestamped == dto.Timestamp);
|
||||
on.nemtina
commented
Тут тоже лучше разделить на 2 подзапроса: Тут тоже лучше разделить на 2 подзапроса:
result.Where(e => e.DiscriminatorId == dto.DiscriminatorId)
.Where(e => e.Timestamped == dto.Timestamp)
.FirstOrDefault();
|
||||
if (witsDataDto == null)
|
||||
{
|
||||
witsDataDto = new WitsDataDto()
|
||||
{
|
||||
DiscriminatorId = dto.DiscriminatorId,
|
||||
Timestamped = dto.Timestamp
|
||||
};
|
||||
result.Add(witsDataDto);
|
||||
}
|
||||
var recordId = DecodeRecordId(dto.ParameterId);
|
||||
var itemId = DecodeItemId(dto.ParameterId);
|
||||
var witsValueDto = new WitsValueDto()
|
||||
{
|
||||
RecordId = recordId,
|
||||
ItemId = itemId,
|
||||
Value = ConvertValue(recordId, itemId, dto.Value)
|
||||
};
|
||||
|
||||
witsDataDto.Values.Append(witsValueDto);
|
||||
on.nemtina
commented
1. Тут внутрь witsDataDto ничего не добавляется потому что Append возвращает новую последовательность, поэтому писать нужно так:
witsDataDto.Values = witsDataDto.Values.Append(witsValueDto)
2. Не совсем понятный код: цикл по dto, потом поиск еще не добавленных элементов внутрь result и Append.
Это лучше бы отрефакторить. Ниже приложила вариант того, как можно читаемость (по моему мнению) улучшить.
3. И еще параметр take. Желательно иметь значение по умолчанию, а то если пользователь нечаянно null отправит, то запрос ничего не выдаст
![image](/attachments/0dc037f6-7cac-40a5-a8cf-2ca8c60acd5c)
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private object ConvertValue(int recordId, int itemId, string value)
|
||||
{
|
||||
var witsType = witsInfo.FirstOrDefault(e => e.ItemId == itemId
|
||||
&& e.RecordId == recordId)?.ValueType;
|
||||
|
||||
switch(witsType)
|
||||
{
|
||||
default:
|
||||
{
|
||||
return value;
|
||||
}
|
||||
case WitsType.S:
|
||||
{
|
||||
var result = Int16.Parse(value);
|
||||
|
||||
return result;
|
||||
}
|
||||
case WitsType.L:
|
||||
{
|
||||
var result = Int32.Parse(value);
|
||||
|
||||
return result;
|
||||
}
|
||||
case WitsType.F:
|
||||
{
|
||||
var result = float.Parse(value, CultureInfo.InvariantCulture);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private WitsInfo[] GetWitsInfo()
|
||||
{
|
||||
var stream = System.Reflection.Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceStream(witsConfigPath);
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
Converters =
|
||||
{
|
||||
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
|
||||
},
|
||||
};
|
||||
var records = JsonSerializer.Deserialize<WitsInfo[]>(stream!, options) ?? [];
|
||||
return records;
|
||||
}
|
||||
}
|
||||
|
discriminatorId лучше добавить в роут