feat: achievements queries added

This commit is contained in:
Mikhail Shabanov committed 2021-03-23 13:44:03 +01:00
1 parent b4e28506ba
commit 310f46b1e7
18 files changed
+505 -45

No files matched your search

@@ -0,0 +1,21 @@
using System.Collections.Generic;
using WotBlitzStatisticsPro.Common.Model.Achievements;
namespace WotBlitzStatisticsPro.Common.Model
{
/// <summary>
/// Represents information about player's achievements
/// </summary>
public class AccountAchievementsResponse
{
/// <summary>
/// Player Id
/// </summary>
public long AccountId { get; set; }
/// <summary>
/// Player Achievements by sections
/// </summary>
public List<AchievementSection>? AchievementSections { get; set; }
}
}
@@ -0,0 +1,64 @@
namespace WotBlitzStatisticsPro.Common.Model.Achievements
{
/// <summary>
/// Player's achievement information
/// </summary>
public class Achievement
{
/// <summary>
/// Achievement Id
/// </summary>
public string Id { get; set; } = string.Empty;
/// <summary>
/// Achievement value
/// </summary>
public int AchievementValue { get; set; }
/// <summary>
/// Achievement max series value
/// </summary>
public int? MaxSeriesValue { get; set; }
/// <summary>
/// Achievement condition
/// </summary>
public string? Condition { get; set; }
/// <summary>
/// Achievement description
/// </summary>
public string? Description { get; set; }
/// <summary>
/// Achievement normal sized image
/// </summary>
public string? Image { get; set; }
/// <summary>
/// Achievement big image
/// </summary>
public string? ImageBig { get; set; }
/// <summary>
/// Achievement name
/// </summary>
public string? Name { get; set; }
/// <summary>
/// Order
/// </summary>
public long? Order { get; set; }
/// <summary>
/// Section Id
/// </summary>
public string SectionId { get; set; } = string.Empty;
/// <summary>
/// Achievement type
/// </summary>
public string Type { get; set; } = string.Empty;
}
}
@@ -0,0 +1,30 @@
using System.Collections.Generic;
namespace WotBlitzStatisticsPro.Common.Model.Achievements
{
/// <summary>
/// Represents achievement section info and it's achievements list
/// </summary>
public class AchievementSection
{
/// <summary>
/// Section Identifier
/// </summary>
public string SectionId { get; set; } = string.Empty;
/// <summary>
/// Section order
/// </summary>
public int Order { get; set; }
/// <summary>
/// Section Name
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// Achievements in the section
/// </summary>
public List<Achievement>? Achievements { get; set; }
}
}
@@ -18,10 +18,15 @@ namespace WotBlitzStatisticsPro.Common.Model
public DateTime JoinedAt { get; set; } = new DateTime(1970, 1, 1);
///<summary>
/// Player clan role
/// Player clan role ID
///</summary>
public string? Role { get; set; }
///<summary>
/// Player clan role
///</summary>
public string RoleLocalized { get; set; }
/// <summary>
/// Clan name
@@ -153,5 +153,21 @@ namespace WotBlitzStatisticsPro.DataAccess
return collection.ToDictionary(n => n.ClanRoleId, n => n.ClanRoleValueValue);
}
public async Task<List<AchievementSectionDictionary>> GetAchievementSections()
{
var collection = await _database.GetCollection<AchievementSectionDictionary>(AchievementsSectionsCollectionName)
.FindAsync(Builders<AchievementSectionDictionary>.Filter.Empty);
return collection.ToList();
}
public async Task<Dictionary<string, AchievementDictionary>> GetAchievements(string[] achievementIds)
{
var collection = await _database.GetCollection<AchievementDictionary>(AchievementsCollectionName)
.Find(Builders<AchievementDictionary>.Filter.In(v => v.AchievementId, achievementIds))
.ToListAsync();
return collection.ToDictionary(a => a.AchievementId, a => a);
}
}
}
@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using WotBlitzStatisticsPro.Common.Dictionaries;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.DataAccess.Model;
namespace WotBlitzStatisticsPro.DataAccess
{
@@ -32,5 +33,9 @@ namespace WotBlitzStatisticsPro.DataAccess
Task<Dictionary<string, string>> GetTankTypes(RequestLanguage language);
Task<Dictionary<string, string>> GetClanRoles(RequestLanguage language);
Task<List<AchievementSectionDictionary>> GetAchievementSections();
Task<Dictionary<string, AchievementDictionary>> GetAchievements(string[] achievementIds);
}
}
@@ -0,0 +1,49 @@
using System.Threading.Tasks;
using HotChocolate.Types;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.Logic;
namespace WotBlitzStatisticsPro.GraphQl.Query
{
[ExtendObjectType(Name = "Query")]
public class WotBlitzAchievementsQuery
{
private readonly IWargamingAchievements _achievementsService;
public WotBlitzAchievementsQuery(IWargamingAchievements achievementsService)
{
_achievementsService = achievementsService;
}
/// <summary>
/// Returns information about player's achievements
/// </summary>
/// <param name="realmType">Account region</param>
/// <param name="accountId">AccountId</param>
/// <param name="requestLanguage">Request language</param>
public Task<AccountAchievementsResponse> GetAccountAchievements(
long accountId,
RealmType? realmType,
RequestLanguage? requestLanguage)
{
return _achievementsService.GetAccountAchievements(realmType ?? RealmType.Ru, accountId, requestLanguage ?? RequestLanguage.En);
}
/// <summary>
/// Returns information about player's tank achievements
/// </summary>
/// <param name="tankId">Account tank Id</param>
/// <param name="realmType">Account region</param>
/// <param name="accountId">AccountId</param>
/// <param name="requestLanguage">Request language</param>
public Task<AccountAchievementsResponse> GetTankAchievements(
long accountId,
long tankId,
RealmType? realmType,
RequestLanguage? requestLanguage)
{
return _achievementsService.GetTankAchievements(realmType ?? RealmType.Ru, accountId, tankId, requestLanguage ?? RequestLanguage.En);
}
}
}
+1
View File
@@ -45,6 +45,7 @@ namespace WotBlitzStatisticsPro.GraphQl
.AddQueryType(d => d.Name("Query"))
.AddType<WotBlitzStatisticsQuery>()
.AddType<AccountInfoResolver>()
.AddType<WotBlitzAchievementsQuery>()
.AddMutationType<WotBlitzStatisticsMutation>()
.AddType<AccountsSearchItemObjectType>()
.AddType<AccountsSearchObjectType>()
@@ -0,0 +1,15 @@
using System.Threading.Tasks;
using WotBlitzStatisticsPro.Common.Model;
namespace WotBlitzStatisticsPro.Logic
{
public interface IWargamingAchievements
{
Task<AccountAchievementsResponse> GetAccountAchievements(RealmType realm, long accountId,
RequestLanguage requestLanguage);
Task<AccountAchievementsResponse> GetTankAchievements(RealmType realm, long accountId,
long tankId,
RequestLanguage requestLanguage);
}
}
@@ -1,23 +0,0 @@
using System.Collections.Generic;
using AutoMapper;
using WotBlitzStatisticsPro.Common.Dictionaries;
using WotBlitzStatisticsPro.DataAccess.Model;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.Logic.Mappers
{
public class AchievementDictionaryProfile : Profile
{
public AchievementDictionaryProfile()
{
CreateMap<WotEncyclopediaAchievementsResponse, AchievementDictionary>()
.ForMember(d => d.Name, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.Condition, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.Description, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.HeroInfo, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.SectionId, o => o.MapFrom(s => s.Section))
.ForMember(d => d.Options, o => o.Ignore());
}
}
}
@@ -1,17 +0,0 @@
using System.Collections.Generic;
using AutoMapper;
using WotBlitzStatisticsPro.Common.Dictionaries;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.Logic.Mappers
{
public class AchievementOptionProfile : Profile
{
public AchievementOptionProfile()
{
CreateMap<WotEncyclopediaAchievementsOptions, AchievementOption>()
.ForMember(d => d.Name, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.Description, o => o.MapFrom(_ => new List<LocalizableString>()));
}
}
}
@@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using WotBlitzStatisticsPro.Common.Dictionaries;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.Common.Model.Achievements;
using WotBlitzStatisticsPro.DataAccess.Model;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.Logic.Mappers
{
public class AchievementsProfile: Profile
{
public AchievementsProfile()
{
CreateMap<WotEncyclopediaAchievementsOptions, AchievementOption>()
.ForMember(d => d.Name, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.Description, o => o.MapFrom(_ => new List<LocalizableString>()));
CreateMap<WotEncyclopediaAchievementsResponse, AchievementDictionary>()
.ForMember(d => d.Name, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.Condition, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.Description, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.HeroInfo, o => o.MapFrom(_ => new List<LocalizableString>()))
.ForMember(d => d.SectionId, o => o.MapFrom(s => s.Section))
.ForMember(d => d.Options, o => o.Ignore());
CreateMap<AchievementSectionDictionary, AchievementSection>()
.ForMember(s => s.SectionId,
o => o.MapFrom(d => d.AchievementSectionId))
.ForMember(d => d.Name,
o => o.MapFrom((src, dest, destMember, context) =>
src.AchievementSectionNames
.FirstOrDefault(l => l.Language == (RequestLanguage) context.Items["language"])?.Value));
CreateMap<KeyValuePair<string, int>, Achievement>()
.ForMember(d => d.Id, o => o.MapFrom(s => s.Key))
.ForMember(d => d.AchievementValue, o => o.MapFrom(s => s.Value));
CreateMap<AchievementDictionary, Achievement>()
.ForMember(d => d.Condition,
o => o.MapFrom((src, dest, destMember, context) =>
src.Condition
.FirstOrDefault(l => l.Language == (RequestLanguage) context.Items["language"])?.Value))
.ForMember(d => d.Description,
o => o.MapFrom((src, dest, destMember, context) =>
src.Description
.FirstOrDefault(l => l.Language == (RequestLanguage) context.Items["language"])?.Value))
.ForMember(d => d.Name,
o => o.MapFrom((src, dest, destMember, context) =>
src.Name
.FirstOrDefault(l => l.Language == (RequestLanguage) context.Items["language"])?.Value))
.ForMember(d => d.Id, o => o.Ignore())
.ForMember(d => d.AchievementValue, o => o.Ignore())
.ForMember(d => d.MaxSeriesValue, s => s.Ignore())
;
}
}
}
@@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using WotBlitzStatisticsPro.Common.Dictionaries;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.DataAccess.Model;
using WotBlitzStatisticsPro.WgApiClient.Model;
using WotBlitzStatisticsPro.Logic.Calculations;
@@ -18,7 +15,7 @@ namespace WotBlitzStatisticsPro.Logic.Mappers
CreateMap<ClanAccountInfo, ClanInfoResponse>()
.ForMember(d => d.JoinedAt,
o => o.MapFrom(s => s.JoinedAt.HasValue ? s.JoinedAt.Value.ToDateTime() : new DateTime(1970, 1, 1)))
.ForMember(d => d.Role,
.ForMember(d => d.RoleLocalized,
o => o.MapFrom((src, dest, destMember, context) =>
{
var dictionary = context.Items["roles"] as Dictionary<string, string>;
@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.Extensions.Logging;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.Common.Model.Achievements;
using WotBlitzStatisticsPro.DataAccess;
using WotBlitzStatisticsPro.DataAccess.Model;
using WotBlitzStatisticsPro.WgApiClient;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.Logic
{
public class WargamingAchievements: IWargamingAchievements
{
private readonly IDictionariesDataAccessor _dictionariesDataAccessor;
private readonly IWargamingAchievementsApiClient _wargamingAchievementsService;
private readonly IMapper _mapper;
private readonly ILogger<WargamingAchievements> _logger;
public WargamingAchievements(
IDictionariesDataAccessor dictionariesDataAccessor,
IWargamingAchievementsApiClient wargamingAchievementsService,
IMapper mapper,
ILogger<WargamingAchievements> logger)
{
_dictionariesDataAccessor = dictionariesDataAccessor;
_wargamingAchievementsService = wargamingAchievementsService;
_mapper = mapper;
_logger = logger;
}
public async Task<AccountAchievementsResponse> GetAccountAchievements(RealmType realm, long accountId, RequestLanguage requestLanguage)
{
try
{
// Get account achievements from WG API
var wgAchievements =
await _wargamingAchievementsService.GetAccountAchievements(accountId, realm, requestLanguage);
return await FillAchievements(accountId, wgAchievements, requestLanguage);
}
catch (Exception e)
{
_logger.LogError(e, "GetAccountAchievements error");
throw;
}
}
public async Task<AccountAchievementsResponse> GetTankAchievements(RealmType realm, long accountId, long tankId, RequestLanguage requestLanguage)
{
try
{
// Get account achievements from WG API
var wgAchievements =
await _wargamingAchievementsService.GetTankAchievements(accountId, tankId, realm, requestLanguage);
return await FillAchievements(accountId, wgAchievements, requestLanguage);
}
catch (Exception e)
{
_logger.LogError(e, "GetTankAchievements error");
throw;
}
}
private async Task<AccountAchievementsResponse> FillAchievements(long accountId, WotAccountAchievementResponse? wgAchievements,
RequestLanguage requestLanguage)
{
// Read achievement sections from DB
var sectionsDictionary = await _dictionariesDataAccessor.GetAchievementSections();
var sections =
_mapper.Map<List<AchievementSectionDictionary>, List<AchievementSection>>(sectionsDictionary,
context => context.Items["language"] = requestLanguage);
var response = new AccountAchievementsResponse
{
AccountId = accountId,
AchievementSections = sections
};
if (wgAchievements?.Achievements == null)
{
return response;
}
// Map ID And value
var achievements = _mapper.Map<Dictionary<string, int>, List<Achievement>>(wgAchievements.Achievements);
// Add Max series
if (wgAchievements.MaxSeries != null)
{
foreach (var achievementsMaxSeries in wgAchievements.MaxSeries)
{
if (achievementsMaxSeries.Value == 0)
{
continue;
}
var existing = achievements.FirstOrDefault(a => a.Id == achievementsMaxSeries.Key);
if (existing == null)
{
achievements.Add(new Achievement
{ Id = achievementsMaxSeries.Key, MaxSeriesValue = achievementsMaxSeries.Value });
}
else
{
existing.MaxSeriesValue = achievementsMaxSeries.Value;
}
}
}
// Read achievements dictionaries from DB
var achievementDictionaries =
await _dictionariesDataAccessor.GetAchievements(achievements.Select(a => a.Id).ToArray());
// Map achievements dictionaries
foreach (var achievement in achievements)
{
_mapper.Map(achievementDictionaries[achievement.Id], achievement,
context => context.Items["language"] = requestLanguage);
// Map achievement option if exists
if (achievementDictionaries[achievement.Id].Options.Count > 0)
{
if (achievement.AchievementValue < achievementDictionaries[achievement.Id].Options.Count)
{
achievement.Image = achievementDictionaries[achievement.Id]
.Options[achievement.AchievementValue - 1].Image;
achievement.ImageBig = achievementDictionaries[achievement.Id]
.Options[achievement.AchievementValue - 1].ImageBig;
}
}
}
// Sort achievements by sections
foreach (var section in response.AchievementSections)
{
section.Achievements = achievements.Where(a => a.SectionId == section.SectionId).ToList();
}
return response;
}
}
}
@@ -26,10 +26,12 @@ namespace WotBlitzStatisticsPro.Logic
services.AddHttpClient<IWargamingApiClient, WargamingApiClient>();
services.AddHttpClient<IWargamingDictionariesApiClient, WargamingApiClient>();
services.AddHttpClient<IWargamingTanksApiClient, WargamingApiClient>();
services.AddHttpClient<IWargamingAchievementsApiClient, WargamingAchievementsApiClient>();
services.AddTransient<IWargamingSearch, WargamingSearch>();
services.AddTransient<IWargamingDictionaries, WargamingDictionaries>();
services.AddTransient<IWargamingAccounts, WargamingAccounts>();
services.AddTransient<IWargamingClans, WargamingClans>();
services.AddTransient<IWargamingAchievements, WargamingAchievements>();
}
private static void ConfigureDictionariesFactory(IServiceCollection services)
@@ -0,0 +1,20 @@
using System.Threading.Tasks;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.WgApiClient
{
public interface IWargamingAchievementsApiClient
{
Task<WotAccountAchievementResponse?> GetAccountAchievements(
long accountId,
RealmType realmType = RealmType.Ru,
RequestLanguage language = RequestLanguage.En);
Task<WotAccountAchievementResponse?> GetTankAchievements(
long accountId,
long tankId,
RealmType realmType = RealmType.Ru,
RequestLanguage language = RequestLanguage.En);
}
}
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace WotBlitzStatisticsPro.WgApiClient.Model
{
public class WotAccountAchievementResponse
{
///<summary>
/// Achievements
///</summary>
[JsonProperty("achievements")]
public Dictionary<string, int>? Achievements { get; set; }
///<summary>
/// Max values if series achievements
///</summary>
[JsonProperty("max_series")]
public Dictionary<string, int>? MaxSeries { get; set; }
}
}
@@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using WotBlitzStatisticsPro.Common;
using WotBlitzStatisticsPro.Common.Model;
using WotBlitzStatisticsPro.WgApiClient.Model;
namespace WotBlitzStatisticsPro.WgApiClient
{
public class WargamingAchievementsApiClient: WagramingApiClientBase,
IWargamingAchievementsApiClient
{
public WargamingAchievementsApiClient(HttpClient httpClient, IWargamingApiSettings wargamingApiSettings) : base(httpClient, wargamingApiSettings)
{
}
public async Task<WotAccountAchievementResponse?> GetAccountAchievements(long accountId, RealmType realmType = RealmType.Ru,
RequestLanguage language = RequestLanguage.En)
{
var accountAchievements = await GetFromBlitzApi<Dictionary<string, WotAccountAchievementResponse>>(
realmType,
language,
"account/achievements/",
$"account_id={accountId}").ConfigureAwait(false);
return accountAchievements?[accountId.ToString()];
}
public async Task<WotAccountAchievementResponse?> GetTankAchievements(long accountId, long tankId, RealmType realmType = RealmType.Ru,
RequestLanguage language = RequestLanguage.En)
{
var accountAchievements = await GetFromBlitzApi<Dictionary<string, WotAccountAchievementResponse[]>>(
realmType,
language,
"tanks/achievements/",
$"account_id={accountId}",
$"tank_id={tankId}").ConfigureAwait(false);
if (accountAchievements?[accountId.ToString()] != null &&
accountAchievements?[accountId.ToString()].Length == 1)
{
return accountAchievements?[accountId.ToString()][0];
}
return null;
}
}
}