Nullable refernce types refactoring

This commit is contained in:
Mikhail Shabanov committed 2020-12-27 12:39:25 +01:00
1 parent e5c90e03d3
commit e12734981b
85 files changed
+509 -351

No files matched your search

@@ -13,14 +13,14 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
public DateTime LastBattleSince { get; }
public AccountInfo DbAccountInfo { get; set; }
public AccountInfo? DbAccountInfo { get; set; }
public IStatistics[] History { get; set; }
public ShortStatistics OverallStatistics { get; set; }
public ShortStatistics PeriodAccountStatistics { get; set; }
public StatisticsDifference PeriodDifference { get; set; }
public StatisticsDifference[] StatisticsHistory { get; set; }
public IStatistics[]? History { get; set; }
public ShortStatistics? OverallStatistics { get; set; }
public ShortStatistics? PeriodAccountStatistics { get; set; }
public StatisticsDifference? PeriodDifference { get; set; }
public StatisticsDifference[]? StatisticsHistory { get; set; }
public AccountInfoHistoryResponse Response { get; set; }
public AccountInfoHistoryResponse? Response { get; set; }
}
}
@@ -6,17 +6,17 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
{
public class AccountInformationPipelineContextData : IDatabasePipelineContextData
{
public AccountInfo AccountInfo { get; set; }
public AccountInfo? AccountInfo { get; set; }
public AccountInfoHistory AccountInfoHistory { get; set; }
public AccountInfoHistory? AccountInfoHistory { get; set; }
public List<TankInfo> Tanks { get; set; }
public List<TankInfo>? Tanks { get; set; }
public Dictionary<long, TankInfoHistory> TanksHistory { get; set; }
public Dictionary<long, TankInfoHistory>? TanksHistory { get; set; }
public AccountInfoResponse Response { get; set; }
public AccountInfoResponse? Response { get; set; }
public AccountInfo DbAccountInfo { get; set; }
public AccountInfo? DbAccountInfo { get; set; }
}
}
@@ -5,6 +5,6 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
{
public interface IDatabasePipelineContextData
{
AccountInfo DbAccountInfo { get; set; }
AccountInfo? DbAccountInfo { get; set; }
}
}
@@ -4,15 +4,15 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline
{
public interface IStatisticsPipelineData
{
IStatistics[] History { get; set; }
IStatistics[]? History { get; set; }
ShortStatistics OverallStatistics { get; set; }
ShortStatistics? OverallStatistics { get; set; }
public ShortStatistics PeriodAccountStatistics { get; set; }
public ShortStatistics? PeriodAccountStatistics { get; set; }
public StatisticsDifference PeriodDifference { get; set; }
public StatisticsDifference? PeriodDifference { get; set; }
public StatisticsDifference[] StatisticsHistory { get; set; }
public StatisticsDifference[]? StatisticsHistory { get; set; }
}
}
@@ -2,7 +2,7 @@
{
public class OperationContext : IOperationContext
{
private object _contextData;
private object? _contextData;
public OperationContext(AccountRequest request)
@@ -21,7 +21,7 @@
{
_contextData ??= default(TContextData);
return (TContextData)_contextData;
return (TContextData)_contextData!;
}
}
}
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.Extensions.Logging;
using WotBlitzStatisticsPro.Common.Dictionaries;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.DataAccess;
@@ -17,17 +18,31 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
private readonly IMapper _mapper;
private readonly IDictionariesDataAccessor _dictionariesDataAccessor;
private readonly ILogger<BuildAccountInfoResponseOperation> _logger;
public BuildAccountInfoResponseOperation(IMapper mapper, IDictionariesDataAccessor dictionariesDataAccessor)
public BuildAccountInfoResponseOperation(
IMapper mapper,
IDictionariesDataAccessor dictionariesDataAccessor,
ILogger<BuildAccountInfoResponseOperation> logger)
{
_mapper = mapper;
_dictionariesDataAccessor = dictionariesDataAccessor;
_logger = logger;
}
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<AccountInformationPipelineContextData>();
if (contextData?.AccountInfo == null
|| contextData?.Tanks == null
|| contextData?.TanksHistory == null)
{
_logger.LogInformation(
$"contextData or AccountInfo or Tanks or TanksHistory is null");
return;
}
contextData.Response = _mapper.Map<AccountInfo, AccountInfoResponse>(contextData.AccountInfo);
contextData.Response = _mapper.Map(contextData.AccountInfoHistory, contextData.Response);
@@ -48,13 +63,23 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
opt.Items["language"] = context.Request.RequestLanguage;
opt.AfterMap((src, dest) =>
{
dest.TankType = tankTypes.ContainsKey(dest.TankTypeId) ? tankTypes[dest.TankTypeId] : "-";
dest.TankNation = nations.ContainsKey(dest.TankNationId) ? nations[dest.TankNationId] : "-";
if(dest?.TankTypeId != null)
{
dest.TankType = tankTypes.ContainsKey(dest.TankTypeId)
? tankTypes[dest.TankTypeId]
: "-";
}
if(dest?.TankNationId != null)
{
dest.TankNation = nations.ContainsKey(dest.TankNationId)
? nations[dest.TankNationId]
: "-";
}
});
});
});
await next.Invoke(context);
if (next != null) await next.Invoke(context);
}
private static IVehiclesDictionary CreateStubVehicle()
@@ -17,9 +17,16 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_dictionariesDataAccessor = dictionariesDataAccessor;
}
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<AccountInformationPipelineContextData>();
if (contextData?.AccountInfo == null ||
contextData?.AccountInfoHistory == null ||
contextData?.Tanks == null ||
contextData?.TanksHistory == null)
{
return;
}
var tankIds = contextData.Tanks.Select(t => t.TankId).ToArray();
var tankTires = await _dictionariesDataAccessor.GetTankTires(tankIds);
@@ -36,7 +43,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
contextData.AccountInfoHistory.CalculateMiddleTier(contextData.TanksHistory.Values.ToList(), tankTires);
contextData.AccountInfoHistory.CalculateWn7();
await next.Invoke(context);
if (next != null) await next.Invoke(context);
}
}
}
@@ -16,11 +16,11 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
}
public Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<IStatisticsPipelineData>();
if (contextData.History == null ||
if (contextData?.History == null ||
contextData.History.Length == 0)
{
_logger.LogInformation(
@@ -28,7 +28,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
return Task.CompletedTask;
}
return next.Invoke(context);
return next != null ? next.Invoke(context) : Task.CompletedTask;
}
}
}
@@ -15,16 +15,16 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_logger = logger;
}
public Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<AccountInformationPipelineContextData>();
if (contextData.DbAccountInfo == null ||
contextData.DbAccountInfo.LastBattleTime < contextData.AccountInfo.LastBattleTime)
contextData.DbAccountInfo.LastBattleTime < contextData.AccountInfo?.LastBattleTime)
{
return next.Invoke(context);
if (next != null) return next.Invoke(context);
}
_logger.LogInformation($"Exiting without saving. Db LastBattleTime: {contextData.DbAccountInfo.LastBattleTime}, WG LastBattleTime: {contextData.AccountInfo.LastBattleTime}");
_logger.LogInformation($"Exiting without saving. Db LastBattleTime: {contextData.DbAccountInfo?.LastBattleTime}, WG LastBattleTime: {contextData.AccountInfo?.LastBattleTime}");
return Task.CompletedTask;
}
}
@@ -9,10 +9,15 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class FillAccountInfoHistoryResponse : IOperation<IOperationContext>
{
public Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<AccountHistoryInformationPipelineContextData>();
if (contextData?.DbAccountInfo == null)
{
return next != null ? next.Invoke(context) : Task.CompletedTask;
}
contextData.Response = new AccountInfoHistoryResponse
{
AccountId = context.Request.AccountId,
@@ -24,7 +29,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
OverallAccountStatistics = contextData.OverallStatistics
};
return next.Invoke(context);
return next != null ? next.Invoke(context) : Task.CompletedTask;
}
}
}
@@ -17,13 +17,16 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
}
public Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<IStatisticsPipelineData>();
contextData.OverallStatistics = _mapper.Map<IStatistics, ShortStatistics>(contextData.History[0]);
if(contextData?.History != null)
{
contextData.OverallStatistics = _mapper.Map<IStatistics, ShortStatistics>(contextData.History[0]);
}
return next.Invoke(context);
return next != null ? next.Invoke(context) : Task.CompletedTask;
}
}
}
@@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
using AutoMapper;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Calculations;
@@ -10,11 +9,11 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class FillPeriodDifferenceOperation : IOperation<IOperationContext>
{
public Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<IStatisticsPipelineData>();
if (contextData.History.Length > 1)
if (contextData?.History != null && contextData.History.Length > 1)
{
contextData.PeriodDifference = new StatisticsDifference();
var historyLastIndex = contextData.History.Length - 1;
@@ -22,7 +21,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
contextData.PeriodDifference.FillDifference(contextData.History[0], contextData.History[historyLastIndex]);
}
return next.Invoke(context);
return next != null ? next.Invoke(context) : Task.CompletedTask;
}
}
}
@@ -18,11 +18,11 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
}
public Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<IStatisticsPipelineData>();
if (contextData.History.Length > 1)
if (contextData?.History != null && contextData.History.Length > 1)
{
var diff = new AccountInfoHistory(context.Request.AccountId, contextData.History[0].LastBattleTime);
@@ -36,7 +36,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
contextData.PeriodAccountStatistics = _mapper.Map<IStatistics, ShortStatistics>(diff);
}
return next.Invoke(context);
return next != null ? next.Invoke(context) : Task.CompletedTask;
}
}
}
@@ -10,11 +10,11 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
public class FillStatisticsDifferenceOperation : IOperation<IOperationContext>
{
public Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<IStatisticsPipelineData>();
if (contextData.History.Length > 1)
if (contextData?.History != null && contextData.History.Length > 1)
{
contextData.StatisticsHistory = new StatisticsDifference[contextData.History.Length - 1];
for (int i = 1; i < contextData.History.Length; i++)
@@ -24,7 +24,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
}
}
return next.Invoke(context);
return next != null ? next.Invoke(context) : Task.CompletedTask;
}
}
}
@@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.Extensions.Logging;
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Pipeline;
@@ -13,29 +14,39 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
private readonly IWargamingApiClient _wargamingApi;
private readonly IMapper _mapper;
private readonly ILogger<GetAccountInfoOperation> _logger;
public GetAccountInfoOperation(
IWargamingApiClient wargamingApi,
IMapper mapper)
IMapper mapper,
ILogger<GetAccountInfoOperation> logger)
{
_wargamingApi = wargamingApi;
_mapper = mapper;
_logger = logger;
}
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var accountInfo = await
_wargamingApi.GetPlayerAccountInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage);
if (accountInfo == null)
{
_logger.LogInformation(
$"Account not found for AccountId {context.Request.AccountId} and {context.Request.RealmType} realm");
return;
}
// Store info to AccountInfo and in AccountInfoHistory
var contextData = context.Get<AccountInformationPipelineContextData>();
contextData.AccountInfo = _mapper.Map<WotAccountInfo, AccountInfo>(accountInfo);
contextData.AccountInfo.Realm = context.Request.RealmType;
contextData.AccountInfoHistory = new AccountInfoHistory(context.Request.AccountId, contextData.AccountInfo.LastBattleTime);
_mapper.Map(accountInfo.Statistics.All, contextData.AccountInfoHistory);
_mapper.Map(accountInfo.Statistics?.All, contextData.AccountInfoHistory);
await next.Invoke(context);
if (next != null) await next.Invoke(context);
}
}
}
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.Extensions.Logging;
using WotBlitzStatisticsPro.DataAccess.Model.Accounts;
using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext;
using WotBlitzStatisticsPro.Logic.Pipeline;
using WotBlitzStatisticsPro.WgApiClient;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
@@ -14,26 +15,36 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
{
private readonly IWargamingTanksApiClient _wargamingApi;
private readonly IMapper _mapper;
private readonly ILogger<GetTanksInfoOperation> _logger;
public GetTanksInfoOperation(
IWargamingTanksApiClient wargamingApi,
IMapper mapper)
IMapper mapper,
ILogger<GetTanksInfoOperation> logger)
{
_wargamingApi = wargamingApi;
_mapper = mapper;
_logger = logger;
}
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<AccountInformationPipelineContextData>();
var tanksInfo = await
_wargamingApi.GetPlayerAccountTanksInfo(context.Request.AccountId, context.Request.RealmType, context.Request.RequestLanguage);
if (tanksInfo == null)
{
_logger.LogInformation(
$"Tanks not found for AccountId {context.Request.AccountId} and {context.Request.RealmType} realm");
return;
}
contextData.Tanks = new List<TankInfo>();
contextData.TanksHistory = new Dictionary<long, TankInfoHistory>();
tanksInfo.ForEach(tank =>
tanksInfo.OrderByDescending(t => t.LastBattleTime).ToList().ForEach(tank =>
{
var tankInfo = new TankInfo(tank.AccountId, tank.TankId);
_mapper.Map(tank, tankInfo);
@@ -43,7 +54,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
contextData.TanksHistory[stat.TankId] = stat;
});
await next.Invoke(context);
if (next != null) await next.Invoke(context);
}
}
}
@@ -15,12 +15,12 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_accountDataAccessor = accountDataAccessor;
}
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<IDatabasePipelineContextData>();
contextData.DbAccountInfo = await _accountDataAccessor.ReadAccountInfo(context.Request.AccountId);
await next.Invoke(context);
if (next != null) await next.Invoke(context);
}
}
}
@@ -17,12 +17,12 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_accountDataAccessor = accountDataAccessor;
}
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<AccountHistoryInformationPipelineContextData>();
contextData.History = (await _accountDataAccessor.GetAccountHistory(context.Request.AccountId, contextData.LastBattleSince.ToUnixTimestamp())).ToArray();
await next.Invoke(context);
if (next != null) await next.Invoke(context);
}
}
}
@@ -22,10 +22,18 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_logger = logger;
}
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task> next)
public async Task Invoke(IOperationContext context, Func<IOperationContext, Task>? next)
{
var contextData = context.Get<AccountInformationPipelineContextData>();
if (contextData?.AccountInfo == null ||
contextData?.AccountInfoHistory == null ||
contextData?.Tanks == null ||
contextData?.TanksHistory == null)
{
return;
}
await _accountDataAccessor.AddOurUpdateAccountInfo(contextData.AccountInfo);
await _accountDataAccessor.AddAccountInfoHistory(contextData.AccountInfoHistory);
@@ -46,7 +54,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations
_logger.LogInformation($"Updated account {contextData.AccountInfo.AccountId} and {tanksCount} tanks: {tankIdsAsString}");
await next.Invoke(context);
if (next != null) await next.Invoke(context);
}
}
}
@@ -21,7 +21,9 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
[Obsolete("Parameter-less constructor only for unit tests")]
public AchievementsDictionaryUpdater()
{
_wargamingDictionariesApiClient = null!;
_dataAccessor = null!;
_mapper = null!;
}
public AchievementsDictionaryUpdater(IWargamingDictionariesApiClient wargamingDictionariesApiClient, IDictionariesDataAccessor dataAccessor, IMapper mapper)
@@ -54,6 +56,10 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
{
var wgAchievements =
await _wargamingDictionariesApiClient.GetAchievementsDictionary(defaultRealmType, requestLanguage);
if (wgAchievements == null)
{
continue;
}
foreach (var wgAchievement in wgAchievements)
{
var mappedAchievement =
@@ -88,8 +94,8 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
wgAchievementOption);
mappedAchievement.Options.Add(mappedOption);
}
mappedOption.Name.Add(new LocalizableString { Language = requestLanguage, Value = wgAchievement.Name });
mappedOption.Description.Add(new LocalizableString { Language = requestLanguage, Value = wgAchievement.Description });
mappedOption.Name?.Add(new LocalizableString { Language = requestLanguage, Value = wgAchievement.Name });
mappedOption.Description?.Add(new LocalizableString { Language = requestLanguage, Value = wgAchievement.Description });
}
}
}
@@ -21,7 +21,9 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
[Obsolete("Parameter-less constructor only for unit tests")]
public StaticDictionariesUpdater()
{
_wargamingDictionariesApiClient = null!;
_dataAccessor = null!;
_mapper = null!;
}
public StaticDictionariesUpdater(
@@ -42,30 +44,45 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
clanRoles,
achievementsSections) = await GetAndMapDictionaries();
await _dataAccessor.UpdateLanguages(languages);
await _dataAccessor.UpdateNations(nations);
await _dataAccessor.UpdateVehicleTypes(vehicleTypes);
await _dataAccessor.UpdateClanRoles(clanRoles);
await _dataAccessor.UpdateAchievementsSections(achievementsSections);
if(languages != null)
{
await _dataAccessor.UpdateLanguages(languages);
}
if(nations != null)
{
await _dataAccessor.UpdateNations(nations);
}
if(vehicleTypes != null)
{
await _dataAccessor.UpdateVehicleTypes(vehicleTypes);
}
if(clanRoles != null)
{
await _dataAccessor.UpdateClanRoles(clanRoles);
}
if(achievementsSections != null)
{
await _dataAccessor.UpdateAchievementsSections(achievementsSections);
}
return new UpdateDictionariesResponseItem
{
DictionaryType = DictionaryType.StaticDictionaries,
Description =
$"Updated {languages.Count} items in Languages dictionary; {nations.Count} items in Nations dictionary; {vehicleTypes.Count} items in VehicleTypes dictionary; {clanRoles.Count} items in ClanRoles dictionary; {achievementsSections.Count} items in AchievementsSections dictionary"
$"Updated {languages?.Count} items in Languages dictionary; {nations?.Count} items in Nations dictionary; {vehicleTypes?.Count} items in VehicleTypes dictionary; {clanRoles?.Count} items in ClanRoles dictionary; {achievementsSections?.Count} items in AchievementsSections dictionary"
};
}
private async Task<(
List<ILanguageDictionary>,
List<INationDictionary>,
List<IVehicleTypeDictionary>,
List<IClanRoleDictionary>,
List<IAchievementSectionDictionary>)> GetAndMapDictionaries()
List<ILanguageDictionary>?,
List<INationDictionary>?,
List<IVehicleTypeDictionary>?,
List<IClanRoleDictionary>?,
List<IAchievementSectionDictionary>?)> GetAndMapDictionaries()
{
var defaultRealmType = RealmType.Eu;
List<ILanguageDictionary> languages = null;
List<ILanguageDictionary>? languages = null;
var nations = new List<INationDictionary>();
var vehicleTypes = new List<IVehicleTypeDictionary>();
var clanRoles = new List<IClanRoleDictionary>();
@@ -76,17 +93,14 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
var (wotEncyclopediaInfoResponse, wotClanMembersDictionaryResponse) =
await _wargamingDictionariesApiClient.GetStaticDictionariesAsync(defaultRealmType, requestLanguage);
if (languages == null)
{
languages =
_mapper.Map<Dictionary<string, string>, List<LanguageDictionary>>(wotEncyclopediaInfoResponse
.Languages).Cast<ILanguageDictionary>().ToList();
}
if (wotEncyclopediaInfoResponse?.Languages != null)
languages ??= _mapper
.Map<Dictionary<string, string>, List<LanguageDictionary>>(wotEncyclopediaInfoResponse.Languages).Cast<ILanguageDictionary>().ToList();
MapVehicleNations(requestLanguage, wotEncyclopediaInfoResponse.VehicleNations, nations);
MapVehicleTypes(requestLanguage, wotEncyclopediaInfoResponse.VehicleTypes, vehicleTypes);
MapClanRoles(requestLanguage, wotClanMembersDictionaryResponse.ClanRoles, clanRoles);
MapAchievementsSections(requestLanguage, wotEncyclopediaInfoResponse.AchievementSections, achievementsSections);
MapVehicleNations(requestLanguage, wotEncyclopediaInfoResponse?.VehicleNations, nations);
MapVehicleTypes(requestLanguage, wotEncyclopediaInfoResponse?.VehicleTypes, vehicleTypes);
MapClanRoles(requestLanguage, wotClanMembersDictionaryResponse?.ClanRoles, clanRoles);
MapAchievementsSections(requestLanguage, wotEncyclopediaInfoResponse?.AchievementSections, achievementsSections);
}
return (languages, nations, vehicleTypes, clanRoles, achievementsSections);
@@ -94,9 +108,13 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
private void MapVehicleNations(
RequestLanguage requestLanguage,
Dictionary<string, string> sourceDictionary,
Dictionary<string, string>? sourceDictionary,
List<INationDictionary> destinationDictionary)
{
if (sourceDictionary == null)
{
return;
}
foreach (var source in sourceDictionary)
{
var destinationItem = destinationDictionary.FirstOrDefault(d => d.NationId == source.Key);
@@ -116,9 +134,14 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
private void MapVehicleTypes(
RequestLanguage requestLanguage,
Dictionary<string, string> sourceDictionary,
Dictionary<string, string>? sourceDictionary,
List<IVehicleTypeDictionary> destinationDictionary)
{
if (sourceDictionary == null)
{
return;
}
foreach (var source in sourceDictionary)
{
var destinationItem = destinationDictionary.FirstOrDefault(d => d.VehicleTypeId == source.Key);
@@ -138,9 +161,14 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
private void MapClanRoles(
RequestLanguage requestLanguage,
Dictionary<string, string> sourceDictionary,
Dictionary<string, string>? sourceDictionary,
List<IClanRoleDictionary> destinationDictionary)
{
if (sourceDictionary == null)
{
return;
}
foreach (var source in sourceDictionary)
{
var destinationItem = destinationDictionary.FirstOrDefault(d => d.ClanRoleId == source.Key);
@@ -160,9 +188,14 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
private void MapAchievementsSections(
RequestLanguage requestLanguage,
Dictionary<string, WotEncyclopediaInfoAchievementSection> sourceSections,
Dictionary<string, WotEncyclopediaInfoAchievementSection>? sourceSections,
List<IAchievementSectionDictionary> destinationDictionary)
{
if (sourceSections == null)
{
return;
}
foreach (var section in sourceSections)
{
var destinationItem =
@@ -21,7 +21,9 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
[Obsolete("Parameter-less constructor only for unit tests")]
public VehiclesDictionaryUpdater()
{
_wargamingDictionariesApiClient = null!;
_dataAccessor = null!;
_mapper = null!;
}
public VehiclesDictionaryUpdater(IWargamingDictionariesApiClient wargamingDictionariesApiClient,
@@ -57,6 +59,11 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries
var wgVehicles =
await _wargamingDictionariesApiClient.GetVehicles(defaultRealmType, requestLanguage);
if (wgVehicles == null)
{
continue;
}
foreach (var wgVehicle in wgVehicles)
{
var mappedVehicle = vehicles.FirstOrDefault(v => v.TankId == wgVehicle.TankId);
@@ -11,7 +11,7 @@ namespace WotBlitzStatisticsPro.Logic.Mappers
CreateMap<WotAccountListResponse, AccountsSearchResponseItem>()
.ForMember(
d => d.AccountId,
o => o.MapFrom(s => s.AccountId.Value));
o => o.MapFrom(s => s.AccountId ?? -1));
}
}
}
@@ -11,7 +11,7 @@ namespace WotBlitzStatisticsPro.Logic.Mappers
CreateMap<WotClanListResponse, ClanSearchResponseItem>()
.ForMember(
d => d.ClanId,
o => o.MapFrom(s => s.ClanId.Value));
o => o.MapFrom(s => s.ClanId ?? -1));
}
}
@@ -12,11 +12,11 @@ namespace WotBlitzStatisticsPro.Logic.Mappers
.ForMember(d => d.LastBattleTime,
o => o.MapFrom(s => s.LastBattleTime.ToDateTime()))
.ForMember(d => d.AvgDamage,
o => o.MapFrom(s => s.Battles.HasValue && s.Battles > 0 ? ((decimal)s.DamageDealt / s.Battles) : 0m))
o => o.MapFrom(s => s.Battles.HasValue && s.DamageDealt.HasValue && s.Battles > 0 ? ((decimal)s.DamageDealt / s.Battles) : 0m))
.ForMember(d => d.AvgXp,
o => o.MapFrom(s => s.Battles.HasValue && s.Battles > 0 ? ((decimal)s.Xp / s.Battles) : 0m))
o => o.MapFrom(s => s.Battles.HasValue && s.Xp.HasValue && s.Battles > 0 ? ((decimal)s.Xp / s.Battles) : 0m))
.ForMember(d => d.WinRate,
o => o.MapFrom(s => s.Battles.HasValue && s.Battles > 0 ? (100 * (decimal)s.Wins / s.Battles) : 0m))
o => o.MapFrom(s => s.Battles.HasValue && s.Wins.HasValue && s.Battles > 0 ? (100 * (decimal)s.Wins / s.Battles) : 0m))
;
}
}
@@ -22,13 +22,13 @@ namespace WotBlitzStatisticsPro.Logic.Mappers
.ForMember(d => d.Tier,
o => o.MapFrom(s => s.Tier))
.ForMember(d => d.PreviewImage,
o => o.MapFrom(s => s.Images["preview"]))
o => o.MapFrom(s => s.Images == null ? string.Empty : s.Images["preview"]))
.ForMember(d => d.NormalImage,
o => o.MapFrom(s => s.Images["normal"]))
o => o.MapFrom(s => s.Images == null ? string.Empty : s.Images["normal"]))
.ForMember(d => d.PriceCredit,
o => o.MapFrom(s => s.Cost["price_credit"]))
o => o.MapFrom(s => s.Cost == null ? string.Empty : s.Cost["price_credit"]))
.ForMember(d => d.PriceGold,
o => o.MapFrom(s => s.Cost["price_gold"]))
o => o.MapFrom(s => s.Cost == null ? string.Empty : s.Cost["price_gold"]))
.ForMember(d => d.NexTanksInTree,
o =>
o.MapFrom(s => s.NextTanks))
@@ -13,6 +13,6 @@ namespace WotBlitzStatisticsPro.Logic.Pipeline
/// </summary>
/// <param name="context">Pipeline context</param>
/// <param name="next">Next operation</param>
Task Invoke(TContext context, Func<TContext, Task> next);
Task Invoke(TContext context, Func<TContext, Task>? next);
}
}
@@ -9,7 +9,7 @@
/// Builds the pipeline.
/// </summary>
/// <returns>First operation in pipeline.</returns>
IOperation<TContext> Build();
IOperation<TContext>? Build();
/// <summary>
/// Adds operation type to the pipeline
@@ -6,15 +6,15 @@ namespace WotBlitzStatisticsPro.Logic.Pipeline
public class OperationMediator<TContext>: IOperation<TContext>
{
private readonly IOperation<TContext> _current;
private readonly IOperation<TContext> _next;
private readonly IOperation<TContext>? _next;
public OperationMediator(IOperation<TContext> current, IOperation<TContext> next)
public OperationMediator(IOperation<TContext> current, IOperation<TContext>? next)
{
_current = current ?? throw new ArgumentNullException(nameof(current));
_next = next;
}
public Task Invoke(TContext context, Func<TContext, Task> next)
public Task Invoke(TContext context, Func<TContext, Task>? next)
{
return _current.Invoke(context, c => _next == null ? Task.CompletedTask : _next.Invoke(c, null));
}
@@ -14,7 +14,7 @@ namespace WotBlitzStatisticsPro.Logic.Pipeline
_operationFactory = operationFactory;
}
public IOperation<TContext> Build()
public IOperation<TContext>? Build()
{
var allOperationTypes = _operations.ToArray();
var lastOperationType = allOperationTypes.LastOrDefault();
@@ -13,7 +13,7 @@ namespace WotBlitzStatisticsPro.Logic.Pipeline
public IOperation<TContext> Create<TContext>(Type operationType)
{
return _serviceProvider.GetService(operationType) as IOperation<TContext>;
return (_serviceProvider.GetService(operationType) as IOperation<TContext>)!;
}
}
}
@@ -30,11 +30,15 @@ namespace WotBlitzStatisticsPro.Logic
.AddOperation<BuildAccountInfoResponseOperation>()
;
await pipeline.Build()
.Invoke(context, null)
.ConfigureAwait(false);
var firstOperation = pipeline.Build();
if (firstOperation != null)
{
await firstOperation
.Invoke(context, null)
.ConfigureAwait(false);
}
return contextData.Response;
return contextData?.Response ?? new AccountInfoResponse();
}
public async Task<AccountInfoResponse> GatherAndSaveAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage)
@@ -53,11 +57,15 @@ namespace WotBlitzStatisticsPro.Logic
.AddOperation<BuildAccountInfoResponseOperation>()
;
await pipeline.Build()
.Invoke(context, null)
.ConfigureAwait(false);
var firstOperation = pipeline.Build();
if (firstOperation != null)
{
await firstOperation
.Invoke(context, null)
.ConfigureAwait(false);
}
return contextData.Response;
return contextData?.Response ?? new AccountInfoResponse();
}
public async Task<AccountInfoHistoryResponse> GetAccountInfoHistory(RealmType realm, long accountId, DateTime startDate, RequestLanguage requestLanguage)
@@ -77,11 +85,15 @@ namespace WotBlitzStatisticsPro.Logic
.AddOperation<FillAccountInfoHistoryResponse>()
;
await pipeline.Build()
.Invoke(context, null)
.ConfigureAwait(false);
var firstOperation = pipeline.Build();
if (firstOperation != null)
{
await firstOperation
.Invoke(context, null)
.ConfigureAwait(false);
}
return contextData.Response;
return contextData?.Response ?? new AccountInfoHistoryResponse();
}
}
}
@@ -24,6 +24,12 @@ namespace WotBlitzStatisticsPro.Logic
RequestLanguage language)
{
var response = await _wargamingApiClient.FindAccounts(accountNick, realmType, language);
if (response == null)
{
return new AccountsSearchResponse();
}
return new AccountsSearchResponse
{
AccountsCount = response.Count,
@@ -37,6 +43,12 @@ namespace WotBlitzStatisticsPro.Logic
RequestLanguage language)
{
var response = await _wargamingApiClient.FindClans(searchString, realmType, language);
if (response == null)
{
return new ClanSearchResponse();
}
return new ClanSearchResponse
{
ClansCount = response.Count,
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
@@ -43,17 +44,13 @@ namespace WotBlitzStatisticsPro.Logic
{
services.AddTransient<DictionariesUpdaterResolver>(serviceProvider => dictionaryType =>
{
switch (dictionaryType)
return dictionaryType switch
{
case DictionaryType.StaticDictionaries:
return serviceProvider.GetService<StaticDictionariesUpdater>();
case DictionaryType.Achievements:
return serviceProvider.GetService<AchievementsDictionaryUpdater>();
case DictionaryType.Vehicles:
return serviceProvider.GetService<VehiclesDictionaryUpdater>();
default:
return null;
}
DictionaryType.StaticDictionaries => serviceProvider.GetService<StaticDictionariesUpdater>()!,
DictionaryType.Achievements => serviceProvider.GetService<AchievementsDictionaryUpdater>()!,
DictionaryType.Vehicles => serviceProvider.GetService<VehiclesDictionaryUpdater>()!,
_ => throw new ApplicationException($"Unknown dictionary type '{dictionaryType}'")
};
});
}
@@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>