mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
add delta rate
This commit is contained in:
@@ -9,6 +9,7 @@ using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
using Snap.Hutao.Web.Hutao.SpiralAbyss;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Snap.Hutao.Service.Hutao;
|
||||
|
||||
@@ -124,6 +125,32 @@ internal sealed partial class HutaoSpiralAbyssStatisticsCache : IHutaoSpiralAbys
|
||||
return false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static IEnumerable<TResult> CurrentLeftJoinLast<TElement, TKey, TResult>(IEnumerable<TElement> current, IEnumerable<TElement>? last, Func<TElement, TKey> keySelector, Func<TElement, TElement?, TResult> resultSelector)
|
||||
where TKey : notnull
|
||||
{
|
||||
if (last is null)
|
||||
{
|
||||
foreach (TElement element in current)
|
||||
{
|
||||
yield return resultSelector(element, default);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Dictionary<TKey, TElement> lastMap = [];
|
||||
foreach (TElement element in last)
|
||||
{
|
||||
lastMap[keySelector(element)] = element;
|
||||
}
|
||||
|
||||
foreach (TElement element in current)
|
||||
{
|
||||
yield return resultSelector(element, lastMap.GetValueOrDefault(keySelector(element)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask<Dictionary<AvatarId, Avatar>> GetIdAvatarMapExtendedAsync()
|
||||
{
|
||||
if (idAvatarExtendedMap is null)
|
||||
@@ -137,86 +164,91 @@ internal sealed partial class HutaoSpiralAbyssStatisticsCache : IHutaoSpiralAbys
|
||||
|
||||
private async ValueTask AvatarCollocationsAsync(Dictionary<AvatarId, Avatar> idAvatarMap, Dictionary<WeaponId, Weapon> idWeaponMap, Dictionary<ExtendedEquipAffixId, Model.Metadata.Reliquary.ReliquarySet> idReliquarySetMap)
|
||||
{
|
||||
List<AvatarCollocation> avatarCollocationsRaw;
|
||||
List<AvatarCollocation> raw, rawLast;
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
IHutaoSpiralAbyssService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoSpiralAbyssService>();
|
||||
avatarCollocationsRaw = await hutaoService.GetAvatarCollocationsAsync().ConfigureAwait(false);
|
||||
raw = await hutaoService.GetAvatarCollocationsAsync(false).ConfigureAwait(false);
|
||||
rawLast = await hutaoService.GetAvatarCollocationsAsync(true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
AvatarCollocations = avatarCollocationsRaw.SelectList(co => new AvatarCollocationView()
|
||||
AvatarCollocations = CurrentLeftJoinLast(raw, rawLast, data => data.AvatarId, (raw, rawLast) => new AvatarCollocationView()
|
||||
{
|
||||
AvatarId = co.AvatarId,
|
||||
Avatars = co.Avatars.SelectList(a => new AvatarView(idAvatarMap[a.Item], a.Rate)),
|
||||
Weapons = co.Weapons.SelectList(w => new WeaponView(idWeaponMap[w.Item], w.Rate)),
|
||||
ReliquarySets = co.Reliquaries.SelectList(r => new ReliquarySetView(r, idReliquarySetMap)),
|
||||
AvatarId = raw.AvatarId,
|
||||
Avatars = CurrentLeftJoinLast(raw.Avatars, rawLast?.Avatars, data => data.Item, (avatar, avatarLast) => new AvatarView(idAvatarMap[avatar.Item], avatar.Rate, avatarLast?.Rate)).ToList(),
|
||||
Weapons = CurrentLeftJoinLast(raw.Weapons, rawLast?.Weapons, data => data.Item, (weapon, weaponLast) => new WeaponView(idWeaponMap[weapon.Item], weapon.Rate, weaponLast?.Rate)).ToList(),
|
||||
ReliquarySets = CurrentLeftJoinLast(raw.Reliquaries, rawLast?.Reliquaries, data => data.Item, (relic, relicLast) => new ReliquarySetView(idReliquarySetMap, relic, relicLast)).ToList(),
|
||||
}).ToDictionary(a => a.AvatarId);
|
||||
}
|
||||
|
||||
private async ValueTask WeaponCollocationsAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||
{
|
||||
List<WeaponCollocation> weaponCollocationsRaw;
|
||||
List<WeaponCollocation> raw, rawLast;
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
IHutaoSpiralAbyssService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoSpiralAbyssService>();
|
||||
weaponCollocationsRaw = await hutaoService.GetWeaponCollocationsAsync().ConfigureAwait(false);
|
||||
raw = await hutaoService.GetWeaponCollocationsAsync(false).ConfigureAwait(false);
|
||||
rawLast = await hutaoService.GetWeaponCollocationsAsync(true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
WeaponCollocations = weaponCollocationsRaw.SelectList(co => new WeaponCollocationView()
|
||||
WeaponCollocations = CurrentLeftJoinLast(raw, rawLast, data => data.WeaponId, (raw, rawLast) => new WeaponCollocationView()
|
||||
{
|
||||
WeaponId = co.WeaponId,
|
||||
Avatars = co.Avatars.SelectList(a => new AvatarView(idAvatarMap[a.Item], a.Rate)),
|
||||
WeaponId = raw.WeaponId,
|
||||
Avatars = CurrentLeftJoinLast(raw.Avatars, rawLast?.Avatars, data => data.Item, (avatar, avatarLast) => new AvatarView(idAvatarMap[avatar.Item], avatar.Rate, avatarLast?.Rate)).ToList(),
|
||||
}).ToDictionary(w => w.WeaponId);
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SH003")]
|
||||
private async Task AvatarAppearanceRankAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||
{
|
||||
List<AvatarAppearanceRank> avatarAppearanceRanksRaw;
|
||||
List<AvatarAppearanceRank> raw, rawLast;
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
IHutaoSpiralAbyssService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoSpiralAbyssService>();
|
||||
avatarAppearanceRanksRaw = await hutaoService.GetAvatarAppearanceRanksAsync().ConfigureAwait(false);
|
||||
raw = await hutaoService.GetAvatarAppearanceRanksAsync(false).ConfigureAwait(false);
|
||||
rawLast = await hutaoService.GetAvatarAppearanceRanksAsync(true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
AvatarAppearanceRanks = avatarAppearanceRanksRaw.SortByDescending(r => r.Floor).SelectList(rank => new AvatarRankView
|
||||
AvatarAppearanceRanks = CurrentLeftJoinLast(raw.SortByDescending(r => r.Floor), rawLast, data => data.Floor, (raw, rawLast) => new AvatarRankView
|
||||
{
|
||||
Floor = SH.FormatModelBindingHutaoComplexRankFloor(rank.Floor),
|
||||
Avatars = rank.Ranks.SortByDescending(r => r.Rate).SelectList(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)),
|
||||
});
|
||||
Floor = SH.FormatModelBindingHutaoComplexRankFloor(raw.Floor),
|
||||
Avatars = CurrentLeftJoinLast(raw.Ranks, rawLast?.Ranks, data => data.Item, (rank, rankLast) => new AvatarView(idAvatarMap[rank.Item], rank.Rate, rankLast?.Rate)).OrderByDescending(r => r.Rate).ToList(),
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SH003")]
|
||||
private async Task AvatarUsageRanksAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||
{
|
||||
List<AvatarUsageRank> avatarUsageRanksRaw;
|
||||
List<AvatarUsageRank> raw, rawLast;
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
IHutaoSpiralAbyssService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoSpiralAbyssService>();
|
||||
avatarUsageRanksRaw = await hutaoService.GetAvatarUsageRanksAsync().ConfigureAwait(false);
|
||||
raw = await hutaoService.GetAvatarUsageRanksAsync(false).ConfigureAwait(false);
|
||||
rawLast = await hutaoService.GetAvatarUsageRanksAsync(true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
AvatarUsageRanks = avatarUsageRanksRaw.SortByDescending(r => r.Floor).SelectList(rank => new AvatarRankView
|
||||
AvatarUsageRanks = CurrentLeftJoinLast(raw.SortByDescending(r => r.Floor), rawLast, data => data.Floor, (raw, rawLast) => new AvatarRankView
|
||||
{
|
||||
Floor = SH.FormatModelBindingHutaoComplexRankFloor(rank.Floor),
|
||||
Avatars = rank.Ranks.SortByDescending(r => r.Rate).SelectList(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)),
|
||||
});
|
||||
Floor = SH.FormatModelBindingHutaoComplexRankFloor(raw.Floor),
|
||||
Avatars = CurrentLeftJoinLast(raw.Ranks, rawLast?.Ranks, data => data.Item, (rank, rankLast) => new AvatarView(idAvatarMap[rank.Item], rank.Rate, rankLast?.Rate)).OrderByDescending(r => r.Rate).ToList(),
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SH003")]
|
||||
private async Task AvatarConstellationInfosAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||
{
|
||||
List<AvatarConstellationInfo> avatarConstellationInfosRaw;
|
||||
List<AvatarConstellationInfo> raw, rawLast;
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
IHutaoSpiralAbyssService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoSpiralAbyssService>();
|
||||
avatarConstellationInfosRaw = await hutaoService.GetAvatarConstellationInfosAsync().ConfigureAwait(false);
|
||||
raw = await hutaoService.GetAvatarConstellationInfosAsync(false).ConfigureAwait(false);
|
||||
rawLast = await hutaoService.GetAvatarConstellationInfosAsync(true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
AvatarConstellationInfos = avatarConstellationInfosRaw.SortBy(i => i.HoldingRate).SelectList(info =>
|
||||
AvatarConstellationInfos = CurrentLeftJoinLast(raw.SortBy(i => i.HoldingRate), rawLast, data => data.AvatarId, (raw, rawLast) => new AvatarConstellationInfoView(idAvatarMap[raw.AvatarId], raw.HoldingRate, rawLast?.HoldingRate)
|
||||
{
|
||||
return new AvatarConstellationInfoView(idAvatarMap[info.AvatarId], info.HoldingRate, info.Constellations.SelectList(x => x.Rate));
|
||||
});
|
||||
Rates = CurrentLeftJoinLast(raw.Constellations, rawLast?.Constellations, data => data.Item, (rate, rataLast) => new RateAndDelta(rate.Rate, rataLast?.Rate)).ToList(),
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SH003")]
|
||||
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdAchievementSource
|
||||
{
|
||||
public Dictionary<AchievementId, Model.Metadata.Achievement.Achievement> IdAchievementMap { get; set; }
|
||||
Dictionary<AchievementId, Model.Metadata.Achievement.Achievement> IdAchievementMap { get; set; }
|
||||
}
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdAvatarSource
|
||||
{
|
||||
public Dictionary<AvatarId, Model.Metadata.Avatar.Avatar> IdAvatarMap { get; set; }
|
||||
Dictionary<AvatarId, Model.Metadata.Avatar.Avatar> IdAvatarMap { get; set; }
|
||||
}
|
||||
@@ -8,5 +8,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdMaterialSource
|
||||
{
|
||||
public Dictionary<MaterialId, Material> IdMaterialMap { get; set; }
|
||||
Dictionary<MaterialId, Material> IdMaterialMap { get; set; }
|
||||
}
|
||||
@@ -8,5 +8,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdReliquaryAffixWeightSource
|
||||
{
|
||||
public Dictionary<AvatarId, ReliquaryAffixWeight> IdReliquaryAffixWeightMap { get; set; }
|
||||
Dictionary<AvatarId, ReliquaryAffixWeight> IdReliquaryAffixWeightMap { get; set; }
|
||||
}
|
||||
@@ -8,5 +8,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdReliquaryMainPropertySource
|
||||
{
|
||||
public Dictionary<ReliquaryMainAffixId, FightProperty> IdReliquaryMainPropertyMap { get; set; }
|
||||
Dictionary<ReliquaryMainAffixId, FightProperty> IdReliquaryMainPropertyMap { get; set; }
|
||||
}
|
||||
@@ -8,5 +8,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdReliquarySource
|
||||
{
|
||||
public Dictionary<ReliquaryId, Reliquary> IdReliquaryMap { get; set; }
|
||||
Dictionary<ReliquaryId, Reliquary> IdReliquaryMap { get; set; }
|
||||
}
|
||||
@@ -8,5 +8,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdReliquarySubAffixSource
|
||||
{
|
||||
public Dictionary<ReliquarySubAffixId, ReliquarySubAffix> IdReliquarySubAffixMap { get; set; }
|
||||
Dictionary<ReliquarySubAffixId, ReliquarySubAffix> IdReliquarySubAffixMap { get; set; }
|
||||
}
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdWeaponSource
|
||||
{
|
||||
public Dictionary<WeaponId, Model.Metadata.Weapon.Weapon> IdWeaponMap { get; set; }
|
||||
Dictionary<WeaponId, Model.Metadata.Weapon.Weapon> IdWeaponMap { get; set; }
|
||||
}
|
||||
@@ -5,5 +5,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryNameAvatarSource
|
||||
{
|
||||
public Dictionary<string, Model.Metadata.Avatar.Avatar> NameAvatarMap { get; set; }
|
||||
Dictionary<string, Model.Metadata.Avatar.Avatar> NameAvatarMap { get; set; }
|
||||
}
|
||||
@@ -5,5 +5,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryNameWeaponSource
|
||||
{
|
||||
public Dictionary<string, Model.Metadata.Weapon.Weapon> NameWeaponMap { get; set; }
|
||||
Dictionary<string, Model.Metadata.Weapon.Weapon> NameWeaponMap { get; set; }
|
||||
}
|
||||
@@ -5,5 +5,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataListAchievementSource
|
||||
{
|
||||
public List<Model.Metadata.Achievement.Achievement> Achievements { get; set; }
|
||||
List<Model.Metadata.Achievement.Achievement> Achievements { get; set; }
|
||||
}
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataListChapterSource
|
||||
{
|
||||
public List<Chapter> Chapters { get; set; }
|
||||
List<Chapter> Chapters { get; set; }
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataListGachaEventSource
|
||||
{
|
||||
public List<GachaEvent> GachaEvents { get; set; }
|
||||
List<GachaEvent> GachaEvents { get; set; }
|
||||
}
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataListMaterialSource
|
||||
{
|
||||
public List<Material> Materials { get; set; }
|
||||
List<Material> Materials { get; set; }
|
||||
}
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataListProfilePictureSource
|
||||
{
|
||||
public List<ProfilePicture> ProfilePictures { get; set; }
|
||||
List<ProfilePicture> ProfilePictures { get; set; }
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataListReliquaryMainAffixLevelSource
|
||||
{
|
||||
public List<ReliquaryMainAffixLevel> ReliquaryMainAffixLevels { get; set; }
|
||||
List<ReliquaryMainAffixLevel> ReliquaryMainAffixLevels { get; set; }
|
||||
}
|
||||
@@ -7,5 +7,5 @@ namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataListReliquarySource
|
||||
{
|
||||
public List<Reliquary> Reliquaries { get; set; }
|
||||
List<Reliquary> Reliquaries { get; set; }
|
||||
}
|
||||
@@ -12,20 +12,10 @@ namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
[HighQuality]
|
||||
internal sealed class AvatarConstellationInfoView : AvatarView
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的角色命座信息
|
||||
/// </summary>
|
||||
/// <param name="avatar">角色</param>
|
||||
/// <param name="rate">持有率</param>
|
||||
/// <param name="rates">命座比率</param>
|
||||
public AvatarConstellationInfoView(Avatar avatar, double rate, List<double> rates)
|
||||
: base(avatar, rate)
|
||||
public AvatarConstellationInfoView(Avatar avatar, double rate, double? lastRate)
|
||||
: base(avatar, rate, lastRate)
|
||||
{
|
||||
Rates = rates.SelectList(r => $"{r:P3}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 命座比率
|
||||
/// </summary>
|
||||
public List<string> Rates { get; }
|
||||
}
|
||||
public List<RateAndDelta> Rates { get; set; } = default!;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
@@ -12,20 +13,15 @@ namespace Snap.Hutao.ViewModel.Complex;
|
||||
/// 角色
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal class AvatarView : INameIconSide
|
||||
internal class AvatarView : RateAndDelta, INameIconSide
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个胡桃数据库角色
|
||||
/// </summary>
|
||||
/// <param name="avatar">元数据角色</param>
|
||||
/// <param name="rate">率</param>
|
||||
public AvatarView(Avatar avatar, double rate = 0)
|
||||
public AvatarView(Avatar avatar, double rate, double? lastRate = default)
|
||||
: base(rate, lastRate)
|
||||
{
|
||||
Name = avatar.Name;
|
||||
Icon = AvatarIconConverter.IconNameToUri(avatar.Icon);
|
||||
SideIcon = AvatarSideIconConverter.IconNameToUri(avatar.SideIcon);
|
||||
Quality = avatar.Quality;
|
||||
Rate = $"{rate:P3}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,9 +43,4 @@ internal class AvatarView : INameIconSide
|
||||
/// 星级
|
||||
/// </summary>
|
||||
public QualityType Quality { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 比率
|
||||
/// </summary>
|
||||
public string Rate { get; }
|
||||
}
|
||||
45
src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/RateAndDelta.cs
Normal file
45
src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/RateAndDelta.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
|
||||
internal class RateAndDelta
|
||||
{
|
||||
public RateAndDelta(double rate, double? lastRate)
|
||||
{
|
||||
Rate = $"{rate:P3}";
|
||||
|
||||
if (lastRate.HasValue)
|
||||
{
|
||||
RateDelta = FormatDelta(rate - lastRate.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
RateDelta = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public string Rate { get; }
|
||||
|
||||
public string RateDelta { get; }
|
||||
|
||||
public static RateAndDelta Create((double Rate, double? LastRate) tuple)
|
||||
{
|
||||
return new RateAndDelta(tuple.Rate, tuple.LastRate);
|
||||
}
|
||||
|
||||
public static RateAndDelta Create((double Rate, double LastRate) tuple)
|
||||
{
|
||||
return new RateAndDelta(tuple.Rate, tuple.LastRate);
|
||||
}
|
||||
|
||||
private static string FormatDelta(double value)
|
||||
{
|
||||
return value switch
|
||||
{
|
||||
>= 0 => $"+{value:P3}",
|
||||
< 0 => $"{value:P3}",
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Web.Hutao.SpiralAbyss;
|
||||
@@ -12,16 +13,12 @@ namespace Snap.Hutao.ViewModel.Complex;
|
||||
/// <summary>
|
||||
/// 圣遗物套装
|
||||
/// </summary>
|
||||
internal sealed class ReliquarySetView
|
||||
internal sealed class ReliquarySetView : RateAndDelta
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的胡桃数据库圣遗物套装
|
||||
/// </summary>
|
||||
/// <param name="reliquarySetRate">圣遗物套装率</param>
|
||||
/// <param name="idReliquarySetMap">圣遗物套装映射</param>
|
||||
public ReliquarySetView(ItemRate<ReliquarySets, double> reliquarySetRate, Dictionary<ExtendedEquipAffixId, Model.Metadata.Reliquary.ReliquarySet> idReliquarySetMap)
|
||||
public ReliquarySetView(Dictionary<ExtendedEquipAffixId, Model.Metadata.Reliquary.ReliquarySet> idReliquarySetMap, ItemRate<ReliquarySets, double> setRate, ItemRate<ReliquarySets, double>? lastSetRate)
|
||||
: base(setRate.Rate, lastSetRate?.Rate)
|
||||
{
|
||||
ReliquarySets sets = reliquarySetRate.Item;
|
||||
ReliquarySets sets = setRate.Item;
|
||||
|
||||
if (!sets.IsNullOrEmpty())
|
||||
{
|
||||
@@ -41,8 +38,6 @@ internal sealed class ReliquarySetView
|
||||
{
|
||||
Name = SH.ViewModelComplexReliquarySetViewEmptyName;
|
||||
}
|
||||
|
||||
Rate = $"{reliquarySetRate.Rate:P3}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,9 +49,4 @@ internal sealed class ReliquarySetView
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public List<Uri>? Icons { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 比率
|
||||
/// </summary>
|
||||
public string Rate { get; }
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ internal sealed class Team : List<AvatarView>
|
||||
foreach (StringSegment item in new StringTokenizer(team.Item, [',']))
|
||||
{
|
||||
uint id = uint.Parse(item.AsSpan(), CultureInfo.InvariantCulture);
|
||||
Add(new(idAvatarMap[id]));
|
||||
Add(new(idAvatarMap[id], 0));
|
||||
}
|
||||
|
||||
AddRange(new AvatarView[4 - Count]);
|
||||
@@ -33,6 +33,7 @@ internal sealed class Team : List<AvatarView>
|
||||
/// <summary>
|
||||
/// 上场次数
|
||||
/// </summary>
|
||||
[Obsolete("Name this with another name")]
|
||||
public string Rate { get; }
|
||||
|
||||
public int Rank { get; set; }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
using Snap.Hutao.Model.Metadata.Weapon;
|
||||
@@ -12,19 +13,14 @@ namespace Snap.Hutao.ViewModel.Complex;
|
||||
/// 胡桃数据库武器
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class WeaponView : INameIcon
|
||||
internal sealed class WeaponView : RateAndDelta, INameIcon
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个胡桃数据库武器
|
||||
/// </summary>
|
||||
/// <param name="weapon">元数据武器</param>
|
||||
/// <param name="rate">率</param>
|
||||
public WeaponView(Weapon weapon, double rate)
|
||||
public WeaponView(Weapon weapon, double rate, double? lastRate)
|
||||
: base(rate, lastRate)
|
||||
{
|
||||
Name = weapon.Name;
|
||||
Icon = EquipIconConverter.IconNameToUri(weapon.Icon);
|
||||
Quality = weapon.Quality;
|
||||
Rate = $"{rate:P3}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -41,9 +37,4 @@ internal sealed class WeaponView : INameIcon
|
||||
/// 星级
|
||||
/// </summary>
|
||||
public QualityType Quality { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 比率
|
||||
/// </summary>
|
||||
public string Rate { get; }
|
||||
}
|
||||
@@ -16,6 +16,7 @@ internal sealed class AvatarConstellationInfo : AvatarBuild
|
||||
|
||||
/// <summary>
|
||||
/// 命之座
|
||||
/// Order is guaranteed as ascending
|
||||
/// </summary>
|
||||
public List<ItemRate<int, double>> Constellations { get; set; } = default!;
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Snap.Hutao.Web.Hutao.SpiralAbyss;
|
||||
/// 圣遗物套装
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class ReliquarySet
|
||||
internal sealed class ReliquarySet : IEquatable<ReliquarySet>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的圣遗物套装
|
||||
@@ -34,7 +34,31 @@ internal sealed class ReliquarySet
|
||||
/// </summary>
|
||||
public int Count { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(ReliquarySet? other)
|
||||
{
|
||||
if (other is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(this, other))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return EquipAffixId == other.EquipAffixId && Count == other.Count;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return Equals(obj as ReliquarySet);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(EquipAffixId, Count);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{EquipAffixId.Value}-{Count}";
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Snap.Hutao.Web.Hutao.SpiralAbyss;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[JsonConverter(typeof(ReliquarySetsConverter))]
|
||||
internal sealed class ReliquarySets : List<ReliquarySet>
|
||||
internal sealed class ReliquarySets : List<ReliquarySet>, IEquatable<ReliquarySets>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的圣遗物包装器
|
||||
@@ -20,4 +20,35 @@ internal sealed class ReliquarySets : List<ReliquarySet>
|
||||
: base(sets)
|
||||
{
|
||||
}
|
||||
|
||||
public bool Equals(ReliquarySets? other)
|
||||
{
|
||||
if (other is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(this, other))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.SequenceEqual(other);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return Equals(obj as ReliquarySets);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
HashCode hashCode = default;
|
||||
foreach (ReliquarySet set in this)
|
||||
{
|
||||
hashCode.Add(set);
|
||||
}
|
||||
|
||||
return hashCode.ToHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user