basic support

This commit is contained in:
Lightczx
2024-03-06 11:50:55 +08:00
parent 44e7f7482c
commit 4c38bb528f
22 changed files with 185 additions and 242 deletions

View File

@@ -39,7 +39,7 @@ internal sealed partial class CultivationService : ICultivationService
List<InventoryItem> entities = cultivationDbService.GetInventoryItemListByProjectId(projectId);
List<InventoryItemView> results = [];
foreach (Material meta in context.EnumerateInventroyMaterial())
foreach (Material meta in context.EnumerateInventoryMaterial())
{
InventoryItem entity = entities.SingleOrDefault(e => e.ItemId == meta.Id) ?? InventoryItem.From(projectId, meta.Id);
results.Add(new(entity, meta, saveCommand));

View File

@@ -3,6 +3,7 @@
using Snap.Hutao.Model.Metadata.Abstraction;
using Snap.Hutao.ViewModel.GachaLog;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using Windows.UI;
@@ -25,7 +26,7 @@ internal static class GachaStatisticsExtension
bool isPreviousUp = true;
// mark the IsGuarantee
foreach (SummaryItem item in summaryItems)
foreach (ref readonly SummaryItem item in CollectionsMarshal.AsSpan(summaryItems))
{
if (item.IsUp && (!isPreviousUp))
{

View File

@@ -7,6 +7,7 @@ using Snap.Hutao.Model.Metadata;
using Snap.Hutao.Model.Metadata.Avatar;
using Snap.Hutao.Model.Metadata.Weapon;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Metadata.ContextAbstraction;
using Snap.Hutao.ViewModel.GachaLog;
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
using Snap.Hutao.Web.Hutao.GachaLog;
@@ -31,9 +32,8 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
public async ValueTask<GachaStatistics> CreateAsync(List<Model.Entity.GachaItem> items, GachaLogServiceMetadataContext context)
{
await taskContext.SwitchToBackgroundAsync();
List<GachaEvent> gachaEvents = await metadataService.GetGachaEventListAsync().ConfigureAwait(false);
List<HistoryWishBuilder> historyWishBuilders = gachaEvents.SelectList(gachaEvent => new HistoryWishBuilder(gachaEvent, context));
List<HistoryWishBuilder> historyWishBuilders = context.GachaEvents.SelectList(gachaEvent => new HistoryWishBuilder(gachaEvent, context));
return CreateCore(taskContext, homaGachaLogClient, items, historyWishBuilders, context, options.IsEmptyHistoryWishVisible);
}
@@ -70,18 +70,19 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
// Items are ordered by precise time, first is oldest
// 'ref' is not allowed here because we have lambda below
foreach (Model.Entity.GachaItem item in CollectionsMarshal.AsSpan(items))
foreach (ref readonly Model.Entity.GachaItem item in CollectionsMarshal.AsSpan(items))
{
// Find target history wish to operate. // w.From <= item.Time <= w.To
// Find target history wish to operate. // banner.From <= item.Time <= banner.To
Model.Entity.GachaItem pinned = item;
HistoryWishBuilder? targetHistoryWishBuilder = item.GachaType is not (GachaType.Standard or GachaType.NewBie)
? historyWishBuilderMap[item.GachaType].BinarySearch(w => item.Time < w.From ? -1 : item.Time > w.To ? 1 : 0)
? historyWishBuilderMap[item.GachaType].BinarySearch(banner => pinned.Time < banner.From ? -1 : pinned.Time > banner.To ? 1 : 0)
: default;
switch (item.ItemId.StringLength())
{
case 8U:
{
Avatar avatar = context.IdAvatarMap[item.ItemId];
Avatar avatar = context.GetAvatar(item.ItemId);
bool isUp = false;
switch (avatar.Quality)
@@ -142,7 +143,7 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
}
}
AsyncBarrier barrier = new(3);
AsyncBarrier barrier = new(4);
return new()
{
@@ -150,7 +151,7 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
HistoryWishes = historyWishBuilders
.Where(b => isEmptyHistoryWishVisible || (!b.IsEmpty))
.OrderByDescending(builder => builder.From)
.ThenBy(builder => builder.ConfigType, GachaConfigTypeComparer.Shared)
.ThenBy(builder => builder.ConfigType, GachaTypeComparer.Shared)
.Select(builder => builder.ToHistoryWish())
.ToList(),

View File

@@ -10,22 +10,23 @@ namespace Snap.Hutao.Service.GachaLog.Factory;
/// <summary>
/// 祈愿配置类型比较器
/// </summary>
internal sealed class GachaConfigTypeComparer : IComparer<GachaType>
internal sealed class GachaTypeComparer : IComparer<GachaType>
{
private static readonly Lazy<GachaConfigTypeComparer> LazyShared = new(() => new());
private static readonly FrozenDictionary<GachaConfigType, int> OrderMap = FrozenDictionary.ToFrozenDictionary(
private static readonly Lazy<GachaTypeComparer> LazyShared = new(() => new());
private static readonly FrozenDictionary<GachaType, int> OrderMap = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(GachaConfigType.AvatarEventWish, 0),
KeyValuePair.Create(GachaConfigType.AvatarEventWish2, 1),
KeyValuePair.Create(GachaConfigType.WeaponEventWish, 2),
KeyValuePair.Create(GachaConfigType.StandardWish, 3),
KeyValuePair.Create(GachaConfigType.NoviceWish, 4),
KeyValuePair.Create(GachaType.ActivityAvatar, 0),
KeyValuePair.Create(GachaType.SpecialActivityAvatar, 1),
KeyValuePair.Create(GachaType.ActivityWeapon, 2),
KeyValuePair.Create(GachaType.Standard, 3),
KeyValuePair.Create(GachaType.NewBie, 4),
KeyValuePair.Create(GachaType.ActivityCity, 5),
]);
/// <summary>
/// 共享的比较器
/// </summary>
public static GachaConfigTypeComparer Shared { get => LazyShared.Value; }
public static GachaTypeComparer Shared { get => LazyShared.Value; }
/// <inheritdoc/>
public int Compare(GachaType x, GachaType y)

View File

@@ -29,7 +29,6 @@ internal sealed class HistoryWishBuilder
/// </summary>
/// <param name="gachaEvent">卡池配置</param>
/// <param name="context">祈愿记录上下文</param>
[SuppressMessage("", "SH002")]
public HistoryWishBuilder(GachaEvent gachaEvent, GachaLogServiceMetadataContext context)
{
this.gachaEvent = gachaEvent;
@@ -112,13 +111,13 @@ internal sealed class HistoryWishBuilder
{
HistoryWish historyWish = new()
{
// base
// Base
Name = gachaEvent.Name,
From = gachaEvent.From,
To = gachaEvent.To,
TotalCount = totalCountTracker,
// fill
// Fill
Version = gachaEvent.Version,
BannerImage = gachaEvent.Banner,
OrangeUpList = orangeUpCounter.ToStatisticsList(),

View File

@@ -5,6 +5,7 @@ using Snap.Hutao.Core.ExceptionService;
using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Model.Metadata;
using Snap.Hutao.Model.Metadata.Abstraction;
using Snap.Hutao.Service.Metadata.ContextAbstraction;
using Snap.Hutao.ViewModel.GachaLog;
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
using Snap.Hutao.Web.Hutao.GachaLog;
@@ -56,12 +57,13 @@ internal sealed class HutaoStatisticsFactory
{
IStatisticsItemSource source = item.Item.StringLength() switch
{
8U => context.IdAvatarMap[item.Item],
5U => context.IdWeaponMap[item.Item],
8U => context.GetAvatar(item.Item),
5U => context.GetWeapon(item.Item),
_ => throw HutaoException.GachaStatisticsInvalidItemId(item.Item),
};
StatisticsItem statisticsItem = source.ToStatisticsItem(unchecked((int)item.Count));
// Put UP items to a separate list
if (gachaEvent.UpOrangeList.Contains(item.Item) || gachaEvent.UpPurpleList.Contains(item.Item))
{
upItems.Add(statisticsItem);

View File

@@ -15,21 +15,6 @@ namespace Snap.Hutao.Service.GachaLog.Factory;
[HighQuality]
internal sealed class TypedWishSummaryBuilder
{
/// <summary>
/// 常驻祈愿
/// </summary>
public static readonly Func<GachaType, bool> IsStandardWish = type => type is GachaType.Standard;
/// <summary>
/// 角色活动
/// </summary>
public static readonly Func<GachaType, bool> IsAvatarEventWish = type => type is GachaType.ActivityAvatar or GachaType.SpecialActivityAvatar;
/// <summary>
/// 武器活动
/// </summary>
public static readonly Func<GachaType, bool> IsWeaponEventWish = type => type is GachaType.ActivityWeapon;
private readonly TypedWishSummaryBuilderContext context;
private readonly List<int> averageOrangePullTracker = [];
@@ -62,52 +47,54 @@ internal sealed class TypedWishSummaryBuilder
/// <param name="isUp">是否为Up物品</param>
public void Track(GachaItem item, ISummaryItemSource source, bool isUp)
{
if (context.TypeEvaluator(item.GachaType))
if (!context.TypeEvaluator(item.GachaType))
{
++lastOrangePullTracker;
++lastPurplePullTracker;
++lastUpOrangePullTracker;
return;
}
// track total pulls
++totalCountTracker;
TrackFromToTime(item.Time);
++lastOrangePullTracker;
++lastPurplePullTracker;
++lastUpOrangePullTracker;
switch (source.Quality)
{
case QualityType.QUALITY_ORANGE:
// track total pulls
++totalCountTracker;
TrackFromToTime(item.Time);
switch (source.Quality)
{
case QualityType.QUALITY_ORANGE:
{
TrackMinMaxOrangePull(lastOrangePullTracker);
averageOrangePullTracker.Add(lastOrangePullTracker);
if (isUp)
{
TrackMinMaxOrangePull(lastOrangePullTracker);
averageOrangePullTracker.Add(lastOrangePullTracker);
if (isUp)
{
averageUpOrangePullTracker.Add(lastUpOrangePullTracker);
lastUpOrangePullTracker = 0;
}
summaryItems.Add(source.ToSummaryItem(lastOrangePullTracker, item.Time, isUp));
lastOrangePullTracker = 0;
++totalOrangePullTracker;
break;
averageUpOrangePullTracker.Add(lastUpOrangePullTracker);
lastUpOrangePullTracker = 0;
}
case QualityType.QUALITY_PURPLE:
{
lastPurplePullTracker = 0;
++totalPurplePullTracker;
break;
}
summaryItems.Add(source.ToSummaryItem(lastOrangePullTracker, item.Time, isUp));
case QualityType.QUALITY_BLUE:
{
++totalBluePullTracker;
break;
}
default:
lastOrangePullTracker = 0;
++totalOrangePullTracker;
break;
}
}
case QualityType.QUALITY_PURPLE:
{
lastPurplePullTracker = 0;
++totalPurplePullTracker;
break;
}
case QualityType.QUALITY_BLUE:
{
++totalBluePullTracker;
break;
}
default:
break;
}
}

View File

@@ -15,12 +15,14 @@ internal static class GachaArchiveOperation
{
archive = archives.SingleOrDefault(a => a.Uid == uid);
if (archive is null)
if (archive is not null)
{
GachaArchive created = GachaArchive.From(uid);
gachaLogDbService.AddGachaArchive(created);
taskContext.InvokeOnMainThread(() => archives.Add(created));
archive = created;
return;
}
GachaArchive created = GachaArchive.From(uid);
gachaLogDbService.AddGachaArchive(created);
taskContext.InvokeOnMainThread(() => archives.Add(created));
archive = created;
}
}

View File

@@ -1,60 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
namespace Snap.Hutao.Service.GachaLog;
/// <summary>
/// 祈愿物品保存上下文
/// </summary>
internal readonly struct GachaItemSaveContext
{
/// <summary>
/// 待添加物品
/// </summary>
public readonly List<GachaItem> ItemsToAdd;
/// <summary>
/// 是否懒惰
/// </summary>
public readonly bool IsLazy;
public readonly GachaType QueryType;
/// <summary>
/// 结尾 Id
/// </summary>
public readonly long EndId;
/// <summary>
/// 数据集
/// </summary>
public readonly IGachaLogDbService GachaLogDbService;
public GachaItemSaveContext(List<GachaItem> itemsToAdd, bool isLazy, GachaType queryType, long endId, IGachaLogDbService gachaLogDbService)
{
ItemsToAdd = itemsToAdd;
IsLazy = isLazy;
QueryType = queryType;
EndId = endId;
GachaLogDbService = gachaLogDbService;
}
public void SaveItems(GachaArchive archive)
{
if (ItemsToAdd.Count <= 0)
{
return;
}
// 全量刷新
if (!IsLazy)
{
GachaLogDbService.RemoveNewerGachaItemRangeByArchiveIdQueryTypeAndEndId(archive.InnerId, QueryType, EndId);
}
GachaLogDbService.AddGachaItemRange(ItemsToAdd);
}
}

View File

@@ -53,7 +53,7 @@ internal struct GachaLogFetchContext
private readonly ITaskContext taskContext;
private readonly bool isLazy;
public GachaLogFetchContext(IGachaLogDbService gachaLogDbService, ITaskContext taskContext, in GachaLogServiceMetadataContext serviceContext, bool isLazy)
public GachaLogFetchContext(IGachaLogDbService gachaLogDbService, ITaskContext taskContext, GachaLogServiceMetadataContext serviceContext, bool isLazy)
{
this.gachaLogDbService = gachaLogDbService;
this.taskContext = taskContext;
@@ -140,8 +140,18 @@ internal struct GachaLogFetchContext
// While no item is fetched, archive can be null.
if (TargetArchive is not null)
{
GachaItemSaveContext saveContext = new(ItemsToAdd, isLazy, QueryOptions.Type, QueryOptions.EndId, gachaLogDbService);
saveContext.SaveItems(TargetArchive);
if (ItemsToAdd.Count <= 0)
{
return;
}
// 全量刷新
if (!isLazy)
{
gachaLogDbService.RemoveNewerGachaItemRangeByArchiveIdQueryTypeAndEndId(TargetArchive.InnerId, QueryOptions.Type, QueryOptions.EndId);
}
gachaLogDbService.AddGachaItemRange(ItemsToAdd);
}
}

View File

@@ -6,33 +6,17 @@ using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
namespace Snap.Hutao.Service.GachaLog;
/// <summary>
/// 祈愿记录获取状态
/// </summary>
internal sealed class GachaLogFetchStatus
{
/// <summary>
/// 构造一个新的祈愿记录获取状态
/// </summary>
/// <param name="configType">卡池类型</param>
public GachaLogFetchStatus(GachaType configType)
{
ConfigType = configType;
}
/// <summary>
/// 验证密钥是否过期
/// </summary>
public bool AuthKeyTimeout { get; set; }
/// <summary>
/// 卡池类型
/// </summary>
public GachaType ConfigType { get; set; }
/// <summary>
/// 当前获取的物品
/// </summary>
public List<Item> Items { get; set; } = new(20);
public string Header

View File

@@ -56,14 +56,16 @@ internal sealed partial class GachaLogHutaoCloudService : IGachaLogHutaoCloudSer
}
/// <inheritdoc/>
public async ValueTask<ValueResult<bool, Guid>> RetrieveGachaItemsAsync(string uid, CancellationToken token = default)
public async ValueTask<ValueResult<bool, Guid>> RetrieveGachaArchiveIdAsync(string uid, CancellationToken token = default)
{
GachaArchive? archive = await gachaLogDbService
.GetGachaArchiveByUidAsync(uid, token)
.ConfigureAwait(false);
EndIds endIds = await CreateEndIdsAsync(archive, token).ConfigureAwait(false);
Response<List<Web.Hutao.GachaLog.GachaItem>> resp = await homaGachaLogClient.RetrieveGachaItemsAsync(uid, endIds, token).ConfigureAwait(false);
Response<List<Web.Hutao.GachaLog.GachaItem>> resp = await homaGachaLogClient
.RetrieveGachaItemsAsync(uid, endIds, token)
.ConfigureAwait(false);
if (!resp.IsOk())
{
@@ -76,7 +78,8 @@ internal sealed partial class GachaLogHutaoCloudService : IGachaLogHutaoCloudSer
await gachaLogDbService.AddGachaArchiveAsync(archive).ConfigureAwait(false);
}
List<Model.Entity.GachaItem> gachaItems = resp.Data.SelectList(i => Model.Entity.GachaItem.From(archive.InnerId, i));
Guid archiveId = archive.InnerId;
List<Model.Entity.GachaItem> gachaItems = resp.Data.SelectList(i => Model.Entity.GachaItem.From(archiveId, i));
await gachaLogDbService.AddGachaItemsAsync(gachaItems).ConfigureAwait(false);
return new(true, archive.InnerId);
}

View File

@@ -9,6 +9,7 @@ using Snap.Hutao.Model.Primitive;
using Snap.Hutao.Service.GachaLog.Factory;
using Snap.Hutao.Service.GachaLog.QueryProvider;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Metadata.ContextAbstraction;
using Snap.Hutao.ViewModel.GachaLog;
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
using Snap.Hutao.Web.Response;
@@ -62,13 +63,7 @@ internal sealed partial class GachaLogService : IGachaLogService
if (await metadataService.InitializeAsync().ConfigureAwait(false))
{
Dictionary<AvatarId, Model.Metadata.Avatar.Avatar> idAvatarMap = await metadataService.GetIdToAvatarMapAsync(token).ConfigureAwait(false);
Dictionary<WeaponId, Model.Metadata.Weapon.Weapon> idWeaponMap = await metadataService.GetIdToWeaponMapAsync(token).ConfigureAwait(false);
Dictionary<string, Model.Metadata.Avatar.Avatar> nameAvatarMap = await metadataService.GetNameToAvatarMapAsync(token).ConfigureAwait(false);
Dictionary<string, Model.Metadata.Weapon.Weapon> nameWeaponMap = await metadataService.GetNameToWeaponMapAsync(token).ConfigureAwait(false);
context = new(idAvatarMap, idWeaponMap, nameAvatarMap, nameWeaponMap);
context = await metadataService.GetContextAsync<GachaLogServiceMetadataContext>(token).ConfigureAwait(false);
ArchiveCollection = gachaLogDbService.GetGachaArchiveCollection();
return true;
}

View File

@@ -2,10 +2,12 @@
// Licensed under the MIT license.
using Snap.Hutao.Model;
using Snap.Hutao.Model.Metadata;
using Snap.Hutao.Model.Metadata.Abstraction;
using Snap.Hutao.Model.Metadata.Avatar;
using Snap.Hutao.Model.Metadata.Weapon;
using Snap.Hutao.Model.Primitive;
using Snap.Hutao.Service.Metadata.ContextAbstraction;
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
namespace Snap.Hutao.Service.GachaLog;
@@ -13,65 +15,28 @@ namespace Snap.Hutao.Service.GachaLog;
/// <summary>
/// 祈愿记录服务上下文
/// </summary>
internal readonly struct GachaLogServiceMetadataContext
internal sealed class GachaLogServiceMetadataContext : IMetadataContext,
IMetadataSupportInitialization,
IMetadataListGachaEventSource,
IMetadataDictionaryIdAvatarSource,
IMetadataDictionaryIdWeaponSource,
IMetadataDictionaryNameAvatarSource,
IMetadataDictionaryNameWeaponSource
{
/// <summary>
/// 物品缓存
/// </summary>
public readonly Dictionary<string, Item> ItemCache = [];
public Dictionary<string, Item> ItemCache { get; set; } = [];
/// <summary>
/// Id 角色 映射
/// </summary>
public readonly Dictionary<AvatarId, Avatar> IdAvatarMap;
public List<GachaEvent> GachaEvents { get; set; } = default!;
/// <summary>
/// Id 武器 映射
/// </summary>
public readonly Dictionary<WeaponId, Weapon> IdWeaponMap;
public Dictionary<AvatarId, Avatar> IdAvatarMap { get; set; } = default!;
/// <summary>
/// 名称 角色 映射
/// </summary>
public readonly Dictionary<string, Avatar> NameAvatarMap;
public Dictionary<WeaponId, Weapon> IdWeaponMap { get; set; } = default!;
/// <summary>
/// 名称 武器 映射
/// </summary>
public readonly Dictionary<string, Weapon> NameWeaponMap;
public Dictionary<string, Avatar> NameAvatarMap { get; set; } = default!;
/// <summary>
/// 是否初始化完成
/// </summary>
public readonly bool IsInitialized;
public Dictionary<string, Weapon> NameWeaponMap { get; set; } = default!;
/// <summary>
/// 构造一个新的祈愿记录服务上下文
/// </summary>
/// <param name="idAvatarMap">Id 角色 映射</param>
/// <param name="idWeaponMap">Id 武器 映射</param>
/// <param name="nameAvatarMap">名称 角色 映射</param>
/// <param name="nameWeaponMap">名称 武器 映射</param>
public GachaLogServiceMetadataContext(
Dictionary<AvatarId, Avatar> idAvatarMap,
Dictionary<WeaponId, Weapon> idWeaponMap,
Dictionary<string, Avatar> nameAvatarMap,
Dictionary<string, Weapon> nameWeaponMap)
{
IdAvatarMap = idAvatarMap;
IdWeaponMap = idWeaponMap;
NameAvatarMap = nameAvatarMap;
NameWeaponMap = nameWeaponMap;
public bool IsInitialized { get; set; }
IsInitialized = true;
}
/// <summary>
/// 按名称获取物品
/// </summary>
/// <param name="name">名称</param>
/// <param name="type">类型</param>
/// <returns>物品</returns>
public Item GetItemByNameAndType(string name, string type)
{
if (!ItemCache.TryGetValue(name, out Item? result))
@@ -93,11 +58,6 @@ internal readonly struct GachaLogServiceMetadataContext
return result;
}
/// <summary>
/// 按物品 Id 获取名称星级
/// </summary>
/// <param name="id">Id</param>
/// <returns>名称星级</returns>
public INameQuality GetNameQualityByItemId(uint id)
{
uint place = id.StringLength();
@@ -109,12 +69,6 @@ internal readonly struct GachaLogServiceMetadataContext
};
}
/// <summary>
/// 获取物品 Id
/// O(1)
/// </summary>
/// <param name="item">祈愿物品</param>
/// <returns>物品 Id</returns>
public uint GetItemId(GachaLogItem item)
{
if (item.ItemType == SH.ModelInterchangeUIGFItemTypeAvatar)

View File

@@ -36,7 +36,7 @@ internal interface IGachaLogHutaoCloudService
/// <param name="uid">uid</param>
/// <param name="token">取消令牌</param>
/// <returns>是否获取成功</returns>
ValueTask<ValueResult<bool, Guid>> RetrieveGachaItemsAsync(string uid, CancellationToken token = default);
ValueTask<ValueResult<bool, Guid>> RetrieveGachaArchiveIdAsync(string uid, CancellationToken token = default);
/// <summary>
/// 异步上传祈愿记录

View File

@@ -0,0 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
internal interface IMetadataDictionaryNameAvatarSource
{
public Dictionary<string, Model.Metadata.Avatar.Avatar> NameAvatarMap { get; set; }
}

View File

@@ -0,0 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
internal interface IMetadataDictionaryNameWeaponSource
{
public Dictionary<string, Model.Metadata.Weapon.Weapon> NameWeaponMap { get; set; }
}

View File

@@ -0,0 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
internal interface IMetadataSupportInitialization
{
bool IsInitialized { get; set; }
}

View File

@@ -30,27 +30,42 @@ internal static class MetadataServiceContextExtension
// Dictionary
{
if (context is IMetadataDictionaryIdAvatarSource dictionaryAvatarSource)
if (context is IMetadataDictionaryIdAvatarSource dictionaryIdAvatarSource)
{
dictionaryAvatarSource.IdAvatarMap = await metadataService.GetIdToAvatarMapAsync(token).ConfigureAwait(false);
dictionaryIdAvatarSource.IdAvatarMap = await metadataService.GetIdToAvatarMapAsync(token).ConfigureAwait(false);
}
if (context is IMetadataDictionaryIdMaterialSource dictionaryMaterialSource)
if (context is IMetadataDictionaryIdMaterialSource dictionaryIdMaterialSource)
{
dictionaryMaterialSource.IdMaterialMap = await metadataService.GetIdToMaterialMapAsync(token).ConfigureAwait(false);
dictionaryIdMaterialSource.IdMaterialMap = await metadataService.GetIdToMaterialMapAsync(token).ConfigureAwait(false);
}
if (context is IMetadataDictionaryIdWeaponSource dictionaryWeaponSource)
if (context is IMetadataDictionaryIdWeaponSource dictionaryIdWeaponSource)
{
dictionaryWeaponSource.IdWeaponMap = await metadataService.GetIdToWeaponMapAsync(token).ConfigureAwait(false);
dictionaryIdWeaponSource.IdWeaponMap = await metadataService.GetIdToWeaponMapAsync(token).ConfigureAwait(false);
}
if (context is IMetadataDictionaryNameAvatarSource dictionaryNameAvatarSource)
{
dictionaryNameAvatarSource.NameAvatarMap = await metadataService.GetNameToAvatarMapAsync(token).ConfigureAwait(false);
}
if (context is IMetadataDictionaryNameWeaponSource dictionaryNameWeaponSource)
{
dictionaryNameWeaponSource.NameWeaponMap = await metadataService.GetNameToWeaponMapAsync(token).ConfigureAwait(false);
}
}
if (context is IMetadataSupportInitialization supportInitialization)
{
supportInitialization.IsInitialized = true;
}
return context;
}
#pragma warning disable SH002
public static IEnumerable<Material> EnumerateInventroyMaterial(this IMetadataListMaterialSource context)
public static IEnumerable<Material> EnumerateInventoryMaterial(this IMetadataListMaterialSource context)
{
return context.Materials.Where(m => m.IsInventoryItem()).OrderBy(m => m.Id.Value);
}
@@ -60,6 +75,11 @@ internal static class MetadataServiceContextExtension
return context.IdAvatarMap[id];
}
public static Avatar GetAvatar(this IMetadataDictionaryNameAvatarSource context, string name)
{
return context.NameAvatarMap[name];
}
public static Material GetMaterial(this IMetadataDictionaryIdMaterialSource context, MaterialId id)
{
return context.IdMaterialMap[id];
@@ -69,5 +89,10 @@ internal static class MetadataServiceContextExtension
{
return context.IdWeaponMap[id];
}
public static Weapon GetWeapon(this IMetadataDictionaryNameWeaponSource context, string name)
{
return context.NameWeaponMap[name];
}
#pragma warning restore SH002
}

View File

@@ -60,7 +60,7 @@ internal sealed partial class HutaoCloudViewModel : Abstraction.ViewModel
using (await dialog.BlockAsync(taskContext).ConfigureAwait(false))
{
return await hutaoCloudService.RetrieveGachaItemsAsync(uid).ConfigureAwait(false);
return await hutaoCloudService.RetrieveGachaArchiveIdAsync(uid).ConfigureAwait(false);
}
}

View File

@@ -34,6 +34,12 @@ internal sealed class EndIds
[JsonPropertyName("302")]
public long WeaponEventWish { get; set; }
/// <summary>
/// 集录祈愿
/// </summary>
[JsonPropertyName("500")]
public long ChronicledWish { get; set; }
/// <summary>
/// 获取 Last Id
/// </summary>
@@ -83,5 +89,6 @@ internal sealed class EndIds
yield return new(GachaType.Standard, StandardWish);
yield return new(GachaType.ActivityAvatar, AvatarEventWish);
yield return new(GachaType.ActivityWeapon, WeaponEventWish);
yield return new(GachaType.ActivityCity, ChronicledWish);
}
}

View File

@@ -10,6 +10,11 @@ internal sealed class GachaEntry
/// </summary>
public string Uid { get; set; } = default!;
/// <summary>
/// 是否被排除出了全球统计
/// </summary>
public bool Excluded { get; set; }
/// <summary>
/// 物品个数
/// </summary>