persistence/DD.Persistence/Services/WitsDataService.cs

174 lines
5.0 KiB
C#

using DD.Persistence.Models;
using DD.Persistence.Models.Configurations;
using DD.Persistence.Models.Enumerations;
using DD.Persistence.Repositories;
using DD.Persistence.Services.Interfaces;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace DD.Persistence.Services;
public class WitsDataService : IWitsDataService
{
private readonly IParameterRepository witsDataRepository;
private readonly WitsInfo[] witsInfo;
private const int multiplier = 1000;
private const string witsConfigPath = "DD.Persistence.Services.Config.WitsConfig.json";
public WitsDataService(IParameterRepository witsDataRepository)
{
this.witsDataRepository = witsDataRepository;
this.witsInfo = GetWitsInfo();
}
public Task<DatesRangeDto> GetDatesRangeAsync(Guid idDiscriminator, CancellationToken token)
{
var result = witsDataRepository.GetDatesRangeAsync(idDiscriminator, token);
return result;
}
public async Task<IEnumerable<WitsDataDto>> GetPart(Guid idDiscriminator, DateTimeOffset dateBegin, int take, CancellationToken token)
{
var dtos = await witsDataRepository.GetPart(idDiscriminator, dateBegin, take, token);
var result = AdaptToWitsData(dtos);
return result;
}
public async Task<IEnumerable<WitsDataDto>> GetValuesForGraph(Guid discriminatorId, DateTimeOffset dateFrom, DateTimeOffset dateTo,
int approxPointsCount, CancellationToken token)
{
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> AddRange(IEnumerable<WitsDataDto> dtos, CancellationToken token)
{
var parameterDtos = dtos.SelectMany(e => e.Values.Select(t => new ParameterDto()
{
DiscriminatorId = e.DiscriminatorId,
ParameterId = EncodeId(t.RecordId, t.ItemId),
Value = t.Value.ToString()!,
Timestamp = e.Timestamped
}));
var result = await witsDataRepository.AddRange(parameterDtos, token);
return result;
}
private int EncodeId(int recordId, int itemId)
{
var resultId = multiplier * recordId + itemId;
return resultId;
}
private int DecodeRecordId(int id)
{
var resultId = id / multiplier;
return resultId;
}
private int DecodeItemId(int id)
{
var resultId = id % multiplier;
return resultId;
}
private IEnumerable<WitsDataDto> AdaptToWitsData(IEnumerable<ParameterDto> dtos)
{
var result = new List<WitsDataDto>();
var witsGroup = dtos
.GroupBy(e => new { e.DiscriminatorId, e.Timestamp });
foreach (var witsInGroup in witsGroup)
{
var witsDataDto = new WitsDataDto()
{
DiscriminatorId = witsInGroup.Key.DiscriminatorId,
Timestamped = witsInGroup.Key.Timestamp
};
witsDataDto.Values = witsInGroup.Select(e =>
{
var recordId = DecodeRecordId(e.ParameterId);
var itemId = DecodeItemId(e.ParameterId);
return new WitsValueDto()
{
RecordId = recordId,
ItemId = itemId,
Value = ConvertValue(recordId, itemId, e.Value)
};
});
result.Add(witsDataDto);
}
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;
}
}