mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
refactor model
This commit is contained in:
20
src/Snap.Hutao/Snap.Hutao/Extension/NullableExtension.cs
Normal file
20
src/Snap.Hutao/Snap.Hutao/Extension/NullableExtension.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
|
||||
internal static class NullableExtension
|
||||
{
|
||||
public static bool TryGetValue<T>(this in T? nullable, out T value)
|
||||
where T : struct
|
||||
{
|
||||
if (nullable.HasValue)
|
||||
{
|
||||
value = nullable.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -33,4 +33,22 @@ internal static class SpanExtension
|
||||
|
||||
return maxIndex;
|
||||
}
|
||||
|
||||
public static bool TrySplitIntoTwo<T>(this in ReadOnlySpan<T> span, T separator, out ReadOnlySpan<T> left, out ReadOnlySpan<T> right)
|
||||
where T : IEquatable<T>?
|
||||
{
|
||||
int indexOfSeparator = span.IndexOf(separator);
|
||||
|
||||
if (indexOfSeparator > 0)
|
||||
{
|
||||
left = span[..indexOfSeparator];
|
||||
right = span[(indexOfSeparator + 1)..];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
left = default;
|
||||
right = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Entity.Abstraction;
|
||||
using Snap.Hutao.Model.InterChange.GachaLog;
|
||||
using Snap.Hutao.Model.Metadata.Abstraction;
|
||||
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
|
||||
@@ -14,7 +15,11 @@ namespace Snap.Hutao.Model.Entity;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Table("gacha_items")]
|
||||
internal sealed class GachaItem
|
||||
internal sealed partial class GachaItem
|
||||
: IDbMappingForeignKeyFrom<GachaItem, GachaLogItem, uint>,
|
||||
IDbMappingForeignKeyFrom<GachaItem, UIGFItem, uint>,
|
||||
IDbMappingForeignKeyFrom<GachaItem, UIGFItem>,
|
||||
IDbMappingForeignKeyFrom<GachaItem, Web.Hutao.GachaLog.GachaItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部Id
|
||||
@@ -61,21 +66,6 @@ internal sealed class GachaItem
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取物品类型字符串
|
||||
/// </summary>
|
||||
/// <param name="itemId">物品Id</param>
|
||||
/// <returns>物品类型字符串</returns>
|
||||
public static string GetItemTypeStringByItemId(uint itemId)
|
||||
{
|
||||
return itemId.Place() switch
|
||||
{
|
||||
8U => "角色",
|
||||
5U => "武器",
|
||||
_ => "未知",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的数据库祈愿物品
|
||||
/// </summary>
|
||||
@@ -83,13 +73,13 @@ internal sealed class GachaItem
|
||||
/// <param name="item">祈愿物品</param>
|
||||
/// <param name="itemId">物品Id</param>
|
||||
/// <returns>新的祈愿物品</returns>
|
||||
public static GachaItem Create(in Guid archiveId, GachaLogItem item, uint itemId)
|
||||
public static GachaItem From(in Guid archiveId, in GachaLogItem item, in uint itemId)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
ArchiveId = archiveId,
|
||||
GachaType = item.GachaType,
|
||||
QueryType = ToQueryType(item.GachaType),
|
||||
QueryType = item.GachaType.ToQueryType(),
|
||||
ItemId = itemId,
|
||||
Time = item.Time,
|
||||
Id = item.Id,
|
||||
@@ -103,7 +93,7 @@ internal sealed class GachaItem
|
||||
/// <param name="item">祈愿物品</param>
|
||||
/// <param name="itemId">物品Id</param>
|
||||
/// <returns>新的祈愿物品</returns>
|
||||
public static GachaItem CreateForMajor2Minor2OrLower(in Guid archiveId, UIGFItem item, uint itemId)
|
||||
public static GachaItem From(in Guid archiveId, in UIGFItem item, in uint itemId)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
@@ -122,7 +112,7 @@ internal sealed class GachaItem
|
||||
/// <param name="archiveId">存档Id</param>
|
||||
/// <param name="item">祈愿物品</param>
|
||||
/// <returns>新的祈愿物品</returns>
|
||||
public static GachaItem CreateForMajor2Minor3OrHigher(in Guid archiveId, UIGFItem item)
|
||||
public static GachaItem From(in Guid archiveId, in UIGFItem item)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
@@ -141,7 +131,7 @@ internal sealed class GachaItem
|
||||
/// <param name="archiveId">存档Id</param>
|
||||
/// <param name="item">祈愿物品</param>
|
||||
/// <returns>新的祈愿物品</returns>
|
||||
public static GachaItem Create(in Guid archiveId, Web.Hutao.GachaLog.GachaItem item)
|
||||
public static GachaItem From(in Guid archiveId, in Web.Hutao.GachaLog.GachaItem item)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
@@ -153,39 +143,4 @@ internal sealed class GachaItem
|
||||
Id = item.Id,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将祈愿配置类型转换到祈愿查询类型
|
||||
/// </summary>
|
||||
/// <param name="configType">配置类型</param>
|
||||
/// <returns>祈愿查询类型</returns>
|
||||
public static GachaConfigType ToQueryType(GachaConfigType configType)
|
||||
{
|
||||
return configType switch
|
||||
{
|
||||
GachaConfigType.AvatarEventWish2 => GachaConfigType.AvatarEventWish,
|
||||
_ => configType,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换到UIGF物品
|
||||
/// </summary>
|
||||
/// <param name="nameQuality">物品</param>
|
||||
/// <returns>UIGF 物品</returns>
|
||||
public UIGFItem ToUIGFItem(INameQuality nameQuality)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
GachaType = GachaType,
|
||||
ItemId = $"{ItemId}",
|
||||
Count = 1,
|
||||
Time = Time,
|
||||
Name = nameQuality.Name,
|
||||
ItemType = GetItemTypeStringByItemId(ItemId),
|
||||
Rank = nameQuality.Quality,
|
||||
Id = Id,
|
||||
UIGFGachaType = QueryType,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
using Snap.Hutao.Model.Entity.Primitive;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
@@ -13,7 +14,7 @@ namespace Snap.Hutao.Model.Entity;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Table("game_accounts")]
|
||||
internal sealed class GameAccount : ObservableObject
|
||||
internal sealed class GameAccount : ObservableObject, IMappingFrom<GameAccount, string, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部Id
|
||||
@@ -48,7 +49,7 @@ internal sealed class GameAccount : ObservableObject
|
||||
/// <param name="name">名称</param>
|
||||
/// <param name="sdk">sdk</param>
|
||||
/// <returns>游戏内账号</returns>
|
||||
public static GameAccount Create(string name, string sdk)
|
||||
public static GameAccount From(string name, string sdk)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Entity.Abstraction;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
@@ -11,7 +12,7 @@ namespace Snap.Hutao.Model.Entity;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Table("inventory_items")]
|
||||
internal sealed class InventoryItem
|
||||
internal sealed class InventoryItem : IDbMappingForeignKeyFrom<InventoryItem, uint>
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部Id
|
||||
@@ -47,7 +48,7 @@ internal sealed class InventoryItem
|
||||
/// <param name="projectId">项目Id</param>
|
||||
/// <param name="itemId">物品Id</param>
|
||||
/// <returns>新的个数为0的物品</returns>
|
||||
public static InventoryItem Create(in Guid projectId, uint itemId)
|
||||
public static InventoryItem From(in Guid projectId, in uint itemId)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
@@ -12,7 +13,8 @@ namespace Snap.Hutao.Model.Entity;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Table("spiral_abysses")]
|
||||
internal sealed class SpiralAbyssEntry : ObservableObject
|
||||
internal sealed class SpiralAbyssEntry : ObservableObject,
|
||||
IMappingFrom<SpiralAbyssEntry, string, Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss>
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部Id
|
||||
@@ -48,7 +50,7 @@ internal sealed class SpiralAbyssEntry : ObservableObject
|
||||
/// <param name="uid">uid</param>
|
||||
/// <param name="spiralAbyss">深渊信息</param>
|
||||
/// <returns>新的深渊信息</returns>
|
||||
public static SpiralAbyssEntry Create(string uid, Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss spiralAbyss)
|
||||
public static SpiralAbyssEntry From(string uid, Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss spiralAbyss)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
@@ -13,7 +14,7 @@ namespace Snap.Hutao.Model.Entity;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Table("users")]
|
||||
internal sealed class User : ISelectable
|
||||
internal sealed class User : ISelectable, IMappingFrom<User, Cookie, bool>
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部Id
|
||||
@@ -65,7 +66,7 @@ internal sealed class User : ISelectable
|
||||
/// <param name="cookie">cookie</param>
|
||||
/// <param name="isOversea">是否为国际服</param>
|
||||
/// <returns>新创建的用户</returns>
|
||||
public static User Create(Cookie cookie, bool isOversea)
|
||||
public static User From(Cookie cookie, bool isOversea)
|
||||
{
|
||||
_ = cookie.TryGetSToken(isOversea, out Cookie? sToken);
|
||||
_ = cookie.TryGetLToken(out Cookie? lToken);
|
||||
|
||||
@@ -24,8 +24,7 @@ internal sealed class UIAF
|
||||
/// 信息
|
||||
/// </summary>
|
||||
[JsonPropertyName("info")]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public UIAFInfo Info { get; set; } = default!;
|
||||
public required UIAFInfo Info { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 列表
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Model.InterChange.Achievement;
|
||||
|
||||
@@ -9,7 +10,7 @@ namespace Snap.Hutao.Model.InterChange.Achievement;
|
||||
/// UIAF格式的信息
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class UIAFInfo
|
||||
internal sealed class UIAFInfo : IMappingFrom<UIAFInfo, RuntimeOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// 导出的 App 名称
|
||||
@@ -47,17 +48,15 @@ internal sealed class UIAFInfo
|
||||
/// <summary>
|
||||
/// 构造一个新的专用 UIAF 信息
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
/// <param name="runtimeOptions">运行时信息</param>
|
||||
/// <returns>专用 UIAF 信息</returns>
|
||||
public static UIAFInfo Create(IServiceProvider serviceProvider)
|
||||
public static UIAFInfo From(RuntimeOptions runtimeOptions)
|
||||
{
|
||||
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
|
||||
return new()
|
||||
{
|
||||
ExportTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds(),
|
||||
ExportApp = SH.AppName,
|
||||
ExportAppVersion = hutaoOptions.Version.ToString(),
|
||||
ExportAppVersion = runtimeOptions.Version.ToString(),
|
||||
UIAFVersion = UIAF.CurrentVersion,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -53,8 +53,7 @@ internal sealed class UIGF
|
||||
{
|
||||
foreach (UIGFItem item in List)
|
||||
{
|
||||
// Hard coded type name
|
||||
if (item.ItemType != "角色" && item.ItemType != "武器")
|
||||
if (item.ItemType != SH.ModelInterchangeUIGFItemTypeAvatar && item.ItemType != SH.ModelInterchangeUIGFItemTypeWeapon)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
|
||||
namespace Snap.Hutao.Model.InterChange.GachaLog;
|
||||
|
||||
@@ -9,7 +11,7 @@ namespace Snap.Hutao.Model.InterChange.GachaLog;
|
||||
/// UIGF格式的信息
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class UIGFInfo
|
||||
internal sealed class UIGFInfo : IMappingFrom<UIGFInfo, IServiceProvider, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户Uid
|
||||
@@ -62,17 +64,18 @@ internal sealed class UIGFInfo
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
/// <param name="uid">uid</param>
|
||||
/// <returns>专用 UIGF 信息</returns>
|
||||
public static UIGFInfo Create(IServiceProvider serviceProvider, string uid)
|
||||
public static UIGFInfo From(IServiceProvider serviceProvider, string uid)
|
||||
{
|
||||
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
MetadataOptions metadataOptions = serviceProvider.GetRequiredService<MetadataOptions>();
|
||||
|
||||
return new()
|
||||
{
|
||||
Uid = uid,
|
||||
Language = "zh-cn",
|
||||
Language = metadataOptions.LanguageCode,
|
||||
ExportTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds(),
|
||||
ExportApp = SH.AppName,
|
||||
ExportAppVersion = hutaoOptions.Version.ToString(),
|
||||
ExportAppVersion = runtimeOptions.Version.ToString(),
|
||||
UIGFVersion = UIGF.CurrentVersion,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
using Snap.Hutao.Core.Json.Annotation;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Metadata.Abstraction;
|
||||
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
|
||||
|
||||
namespace Snap.Hutao.Model.InterChange.GachaLog;
|
||||
@@ -10,7 +13,7 @@ namespace Snap.Hutao.Model.InterChange.GachaLog;
|
||||
/// UIGF物品
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class UIGFItem : GachaLogItem
|
||||
internal sealed class UIGFItem : GachaLogItem, IMappingFrom<UIGFItem, GachaItem, INameQuality>
|
||||
{
|
||||
/// <summary>
|
||||
/// 额外祈愿映射
|
||||
@@ -18,4 +21,30 @@ internal sealed class UIGFItem : GachaLogItem
|
||||
[JsonPropertyName("uigf_gacha_type")]
|
||||
[JsonEnum(JsonSerializeType.NumberString)]
|
||||
public GachaConfigType UIGFGachaType { get; set; } = default!;
|
||||
|
||||
public static UIGFItem From(GachaItem item, INameQuality nameQuality)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
GachaType = item.GachaType,
|
||||
ItemId = $"{item.ItemId:D}",
|
||||
Count = 1,
|
||||
Time = item.Time,
|
||||
Name = nameQuality.Name,
|
||||
ItemType = GetItemTypeStringByItemId(item.ItemId),
|
||||
Rank = nameQuality.Quality,
|
||||
Id = item.Id,
|
||||
UIGFGachaType = item.QueryType,
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetItemTypeStringByItemId(uint itemId)
|
||||
{
|
||||
return itemId.Place() switch
|
||||
{
|
||||
8U => SH.ModelInterchangeUIGFItemTypeAvatar,
|
||||
5U => SH.ModelInterchangeUIGFItemTypeWeapon,
|
||||
_ => SH.ModelInterchangeUIGFItemTypeUnknown,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -62,16 +62,15 @@ internal sealed class UIIFInfo
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
/// <param name="uid">uid</param>
|
||||
/// <returns>专用 UIGF 信息</returns>
|
||||
public static UIIFInfo Create(IServiceProvider serviceProvider, string uid)
|
||||
public static UIIFInfo From(IServiceProvider serviceProvider, string uid)
|
||||
{
|
||||
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
|
||||
return new()
|
||||
{
|
||||
Uid = uid,
|
||||
Language = "zh-cn",
|
||||
ExportTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds(),
|
||||
ExportApp = "胡桃",
|
||||
ExportApp = SH.AppName,
|
||||
ExportAppVersion = hutaoOptions.Version.ToString(),
|
||||
UIIFVersion = UIIF.CurrentVersion,
|
||||
};
|
||||
|
||||
@@ -51,13 +51,13 @@ internal static class IntrinsicImmutable
|
||||
}.ToImmutableHashSet();
|
||||
|
||||
public static readonly ImmutableHashSet<string> MaterialTypeDescriptions = new HashSet<string>(7)
|
||||
{
|
||||
SH.ModelMetadataMaterialCharacterAndWeaponEnhancementMaterial,
|
||||
SH.ModelMetadataMaterialCharacterEXPMaterial,
|
||||
SH.ModelMetadataMaterialCharacterAscensionMaterial,
|
||||
SH.ModelMetadataMaterialCharacterTalentMaterial,
|
||||
SH.ModelMetadataMaterialCharacterLevelUpMaterial,
|
||||
SH.ModelMetadataMaterialWeaponEnhancementMaterial,
|
||||
SH.ModelMetadataMaterialWeaponAscensionMaterial,
|
||||
}.ToImmutableHashSet();
|
||||
{
|
||||
SH.ModelMetadataMaterialCharacterAndWeaponEnhancementMaterial,
|
||||
SH.ModelMetadataMaterialCharacterEXPMaterial,
|
||||
SH.ModelMetadataMaterialCharacterAscensionMaterial,
|
||||
SH.ModelMetadataMaterialCharacterTalentMaterial,
|
||||
SH.ModelMetadataMaterialCharacterLevelUpMaterial,
|
||||
SH.ModelMetadataMaterialWeaponEnhancementMaterial,
|
||||
SH.ModelMetadataMaterialWeaponAscensionMaterial,
|
||||
}.ToImmutableHashSet();
|
||||
}
|
||||
@@ -30,8 +30,9 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IName
|
||||
public CookBonusView? CookBonusView { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 养成物品视图
|
||||
/// [非元数据] 养成物品视图
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public List<Material>? CultivationItemsView { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Avatar;
|
||||
|
||||
/// <summary>
|
||||
/// 描述与参数
|
||||
/// 通常用于技能
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class DescriptionsParameters
|
||||
@@ -17,5 +20,5 @@ internal sealed class DescriptionsParameters
|
||||
/// <summary>
|
||||
/// 参数
|
||||
/// </summary>
|
||||
public List<LevelParameters<int, float>> Parameters { get; set; } = default!;
|
||||
public List<LevelParameters<SkillLevel, float>> Parameters { get; set; } = default!;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,12 @@ internal static class AvatarIds
|
||||
return avatarId == PlayerBoy || avatarId == PlayerGirl;
|
||||
}
|
||||
|
||||
public static Dictionary<AvatarId, Avatar.Avatar> InsertPlayers(Dictionary<AvatarId, Avatar.Avatar> idAvatarMap)
|
||||
/// <summary>
|
||||
/// 复制一个映射并加入旅行者的基本信息
|
||||
/// </summary>
|
||||
/// <param name="idAvatarMap">映射</param>
|
||||
/// <returns>加入旅行者基本信息的映射</returns>
|
||||
public static Dictionary<AvatarId, Avatar.Avatar> WithPlayers(Dictionary<AvatarId, Avatar.Avatar> idAvatarMap)
|
||||
{
|
||||
return new(idAvatarMap)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -22,8 +24,8 @@ internal sealed partial class DescriptionsParametersDescriptor : ValueConverter<
|
||||
/// <returns>特定等级的解释</returns>
|
||||
public static LevelParameters<string, ParameterDescription> Convert(DescriptionsParameters from, uint level)
|
||||
{
|
||||
LevelParameters<int, float> param = from.Parameters.Single(param => param.Level == level);
|
||||
return new LevelParameters<string, ParameterDescription>($"Lv.{param.Level}", GetParameterDescription(from.Descriptions, param.Parameters));
|
||||
LevelParameters<SkillLevel, float> param = from.Parameters.Single(param => param.Level == level);
|
||||
return new LevelParameters<string, ParameterDescription>($"Lv.{param.Level.Value}", GetParameterDescription(from.Descriptions, param.Parameters));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -35,36 +37,36 @@ internal sealed partial class DescriptionsParametersDescriptor : ValueConverter<
|
||||
return parameters;
|
||||
}
|
||||
|
||||
[GeneratedRegex("{param[0-9]+.*?}")]
|
||||
[GeneratedRegex("{param([1-9][0-9]*?):(.+?)}")]
|
||||
private static partial Regex ParamRegex();
|
||||
|
||||
private static List<ParameterDescription> GetParameterDescription(List<string> descriptions, List<float> param)
|
||||
private static List<ParameterDescription> GetParameterDescription(List<string> descriptions, List<float> paramList)
|
||||
{
|
||||
Span<string> span = CollectionsMarshal.AsSpan(descriptions);
|
||||
List<ParameterDescription> results = new(span.Length);
|
||||
|
||||
foreach (ReadOnlySpan<char> desc in span)
|
||||
foreach (string desc in span)
|
||||
{
|
||||
int indexOfSeparator = desc.IndexOf('|');
|
||||
ReadOnlySpan<char> description = desc[..indexOfSeparator];
|
||||
ReadOnlySpan<char> format = desc[(indexOfSeparator + 1)..];
|
||||
|
||||
string resultFormatted = ParamRegex().Replace(format.ToString(), match => ReplaceParamInMatch(match, param));
|
||||
results.Add(new ParameterDescription { Description = description.ToString(), Parameter = resultFormatted });
|
||||
if (desc.AsSpan().TrySplitIntoTwo('|', out ReadOnlySpan<char> description, out ReadOnlySpan<char> format))
|
||||
{
|
||||
string resultFormatted = ParamRegex().Replace(format.ToString(), match => ReplaceParamInMatch(match, paramList));
|
||||
results.Add(new ParameterDescription { Description = description.ToString(), Parameter = resultFormatted });
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowHelper.InvalidOperation($"ParameterFormat failed, value: `{desc}`", default);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static string ReplaceParamInMatch(Match match, List<float> param)
|
||||
private static string ReplaceParamInMatch(Match match, List<float> paramList)
|
||||
{
|
||||
if (match.Success)
|
||||
{
|
||||
// remove parentheses and split by {value:format} like {param1:F}
|
||||
string[] parts = match.Value[1..^1].Split(':', 2);
|
||||
|
||||
int index = int.Parse(parts[0]["param".Length..]) - 1;
|
||||
return ParameterFormat.Format($"{{0:{parts[1]}}}", param[index]);
|
||||
int index = int.Parse(match.Groups[1].Value) - 1;
|
||||
return ParameterFormat.Format($"{{0:{match.Groups[2].Value}}}", paramList[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -34,22 +34,13 @@ internal static class FightPropertyFormat
|
||||
return new(property.GetLocalizedDescription(), FormatValue(property, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化有绿字的角色属性
|
||||
/// </summary>
|
||||
/// <param name="property">战斗属性</param>
|
||||
/// <param name="baseValue">白字</param>
|
||||
/// <param name="addValue">绿字</param>
|
||||
/// <returns>对2</returns>
|
||||
public static AvatarProperty ToAvatarProperty(FightProperty property, float baseValue, float addValue)
|
||||
public static ParameterDescription ToParameterDescription(FightProperty property, float value)
|
||||
{
|
||||
string name = property.GetLocalizedDescription();
|
||||
FormatMethod method = property.GetFormatMethod();
|
||||
|
||||
string value = FormatValue(method, baseValue + addValue);
|
||||
string addedValue = $"[{FormatValue(method, baseValue)}+{FormatValue(method, addValue)}]";
|
||||
|
||||
return new(property, name, value, addedValue);
|
||||
return new()
|
||||
{
|
||||
Description = property.GetLocalizedDescription(),
|
||||
Parameter = FormatValue(property, value),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -82,6 +73,24 @@ internal static class FightPropertyFormat
|
||||
return new(property, name, FormatValue(method, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化有绿字的角色属性
|
||||
/// </summary>
|
||||
/// <param name="property">战斗属性</param>
|
||||
/// <param name="baseValue">白字</param>
|
||||
/// <param name="addValue">绿字</param>
|
||||
/// <returns>对2</returns>
|
||||
public static AvatarProperty ToAvatarProperty(FightProperty property, float baseValue, float addValue)
|
||||
{
|
||||
string name = property.GetLocalizedDescription();
|
||||
FormatMethod method = property.GetFormatMethod();
|
||||
|
||||
string value = FormatValue(method, baseValue + addValue);
|
||||
string addedValue = $"[{FormatValue(method, baseValue)}+{FormatValue(method, addValue)}]";
|
||||
|
||||
return new(property, name, value, addedValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化战斗属性
|
||||
/// </summary>
|
||||
|
||||
@@ -24,15 +24,11 @@ internal sealed class PropertiesParametersDescriptor : ValueConverter<Properties
|
||||
|
||||
private static List<ParameterDescription> GetParameterDescriptions(List<float> parameters, List<FightProperty> properties)
|
||||
{
|
||||
List<ParameterDescription> results = new();
|
||||
List<ParameterDescription> results = new(parameters.Count);
|
||||
|
||||
foreach ((float param, FightProperty property) in parameters.Zip(properties))
|
||||
{
|
||||
results.Add(new ParameterDescription
|
||||
{
|
||||
Description = property.GetLocalizedDescription(),
|
||||
Parameter = FightPropertyFormat.FormatValue(property, param),
|
||||
});
|
||||
results.Add(FightPropertyFormat.ToParameterDescription(property, param));
|
||||
}
|
||||
|
||||
return results;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Snap.Hutao.Model.Metadata;
|
||||
[HighQuality]
|
||||
internal sealed class GrowCurve
|
||||
{
|
||||
private Dictionary<GrowCurveType, float>? curveMap;
|
||||
private Dictionary<GrowCurveType, float>? map;
|
||||
|
||||
/// <summary>
|
||||
/// 等级
|
||||
@@ -27,8 +27,8 @@ internal sealed class GrowCurve
|
||||
/// <summary>
|
||||
/// 曲线映射
|
||||
/// </summary>
|
||||
public Dictionary<GrowCurveType, float> CurveMap
|
||||
public Dictionary<GrowCurveType, float> Map
|
||||
{
|
||||
get => curveMap ??= Curves.ToDictionary(v => v.Type, v => v.Value);
|
||||
get => map ??= Curves.ToDictionary(v => v.Type, v => v.Value);
|
||||
}
|
||||
}
|
||||
@@ -420,6 +420,33 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 角色 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ModelInterchangeUIGFItemTypeAvatar {
|
||||
get {
|
||||
return ResourceManager.GetString("ModelInterchangeUIGFItemTypeAvatar", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 未知 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ModelInterchangeUIGFItemTypeUnknown {
|
||||
get {
|
||||
return ResourceManager.GetString("ModelInterchangeUIGFItemTypeUnknown", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 武器 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ModelInterchangeUIGFItemTypeWeapon {
|
||||
get {
|
||||
return ResourceManager.GetString("ModelInterchangeUIGFItemTypeWeapon", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 愚人众 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -2063,4 +2063,13 @@
|
||||
<data name="ServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale" xml:space="preserve">
|
||||
<value>Url 中的语言:{0} 与胡桃的语言:{1} 不匹配,请切换到对应语言重试</value>
|
||||
</data>
|
||||
<data name="ModelInterchangeUIGFItemTypeAvatar" xml:space="preserve">
|
||||
<value>角色</value>
|
||||
</data>
|
||||
<data name="ModelInterchangeUIGFItemTypeWeapon" xml:space="preserve">
|
||||
<value>武器</value>
|
||||
</data>
|
||||
<data name="ModelInterchangeUIGFItemTypeUnknown" xml:space="preserve">
|
||||
<value>未知</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Model.InterChange.Achievement;
|
||||
@@ -63,7 +64,7 @@ internal sealed partial class AchievementService
|
||||
|
||||
return new()
|
||||
{
|
||||
Info = UIAFInfo.Create(serviceProvider),
|
||||
Info = UIAFInfo.From(scope.ServiceProvider.GetRequiredService<RuntimeOptions>()),
|
||||
List = list,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -68,16 +68,16 @@ internal sealed partial class AchievementService : IAchievementService
|
||||
List<AchievementStatistics> results = new();
|
||||
foreach (AchievementArchive archive in appDbContext.AchievementArchives)
|
||||
{
|
||||
int finished = await appDbContext.Achievements
|
||||
int finishedCount = await appDbContext.Achievements
|
||||
.Where(a => a.ArchiveId == archive.InnerId)
|
||||
.Where(a => (int)a.Status >= (int)Model.Intrinsic.AchievementStatus.STATUS_FINISHED)
|
||||
.Where(a => a.Status >= Model.Intrinsic.AchievementStatus.STATUS_FINISHED)
|
||||
.CountAsync()
|
||||
.ConfigureAwait(false);
|
||||
int totalCount = achievementMap.Count;
|
||||
|
||||
List<EntityAchievement> achievements = await appDbContext.Achievements
|
||||
.Where(a => a.ArchiveId == archive.InnerId)
|
||||
.Where(a => (int)a.Status >= (int)Model.Intrinsic.AchievementStatus.STATUS_FINISHED)
|
||||
.Where(a => a.Status >= Model.Intrinsic.AchievementStatus.STATUS_FINISHED)
|
||||
.OrderByDescending(a => a.Time.ToString())
|
||||
.Take(2)
|
||||
.ToListAsync()
|
||||
@@ -86,7 +86,7 @@ internal sealed partial class AchievementService : IAchievementService
|
||||
results.Add(new()
|
||||
{
|
||||
DisplayName = archive.Name,
|
||||
FinishDescription = AchievementStatistics.Format(finished, totalCount, out _),
|
||||
FinishDescription = AchievementStatistics.Format(finishedCount, totalCount, out _),
|
||||
Achievements = achievements.SelectList(entity => new AchievementView(entity, achievementMap[entity.Id])),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
List<InventoryItemView> results = new();
|
||||
foreach (Material meta in metadata.Where(m => m.IsInventoryItem()).OrderBy(m => m.Id.Value))
|
||||
{
|
||||
InventoryItem entity = entities.SingleOrDefault(e => e.ItemId == meta.Id) ?? InventoryItem.Create(projectId, meta.Id);
|
||||
InventoryItem entity = entities.SingleOrDefault(e => e.ItemId == meta.Id) ?? InventoryItem.From(projectId, meta.Id);
|
||||
results.Add(new(entity, meta, saveCommand));
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ internal struct GachaLogFetchContext
|
||||
/// <param name="item">物品</param>
|
||||
public void AddItem(GachaLogItem item)
|
||||
{
|
||||
ItemsToAdd.Add(GachaItem.Create(TargetArchive!.InnerId, item, serviceContext.GetItemId(item)));
|
||||
ItemsToAdd.Add(GachaItem.From(TargetArchive!.InnerId, item, serviceContext.GetItemId(item)));
|
||||
FetchStatus.Items.Add(serviceContext.GetItemByNameAndType(item.Name, item.ItemType));
|
||||
QueryOptions.EndId = item.Id;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ internal sealed partial class HutaoCloudService : IHutaoCloudService
|
||||
await appDbContext.GachaArchives.AddAndSaveAsync(archive).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
List<Model.Entity.GachaItem> gachaItems = resp.Data.SelectList(i => Model.Entity.GachaItem.Create(archive.InnerId, i));
|
||||
List<Model.Entity.GachaItem> gachaItems = resp.Data.SelectList(i => Model.Entity.GachaItem.From(archive.InnerId, i));
|
||||
await appDbContext.GachaItems.AddRangeAndSaveAsync(gachaItems).ConfigureAwait(false);
|
||||
return new(true, archive);
|
||||
}
|
||||
|
||||
@@ -53,41 +53,41 @@ internal sealed partial class GachaLogQueryWebCacheProvider : IGachaLogQueryProv
|
||||
|
||||
using (TempFile? tempFile = TempFile.CopyFrom(cacheFile))
|
||||
{
|
||||
if (tempFile == null)
|
||||
if (tempFile.TryGetValue(out TempFile file))
|
||||
{
|
||||
return new(false, string.Format(Regex.Unescape(SH.ServiceGachaLogUrlProviderCachePathNotFound), cacheFile));
|
||||
}
|
||||
|
||||
using (FileStream fileStream = new(tempFile.Path, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
using (MemoryStream memoryStream = new())
|
||||
using (FileStream fileStream = new(file.Path, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
string? result = Match(memoryStream, cacheFile.Contains(GameConstants.GenshinImpactData));
|
||||
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
using (MemoryStream memoryStream = new())
|
||||
{
|
||||
QueryString query = QueryString.Parse(result.TrimEnd("#/log"));
|
||||
string queryLanguageCode = query["lang"];
|
||||
if (metadataOptions.IsCurrentLocale(queryLanguageCode))
|
||||
await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
string? result = Match(memoryStream, cacheFile.Contains(GameConstants.GenshinImpactData));
|
||||
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
{
|
||||
return new(true, new(result));
|
||||
QueryString query = QueryString.Parse(result.TrimEnd("#/log"));
|
||||
string queryLanguageCode = query["lang"];
|
||||
if (metadataOptions.IsCurrentLocale(queryLanguageCode))
|
||||
{
|
||||
return new(true, new(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = string.Format(
|
||||
SH.ServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale,
|
||||
queryLanguageCode,
|
||||
metadataOptions.LocaleName);
|
||||
return new(false, message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = string.Format(
|
||||
SH.ServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale,
|
||||
queryLanguageCode,
|
||||
metadataOptions.LocaleName);
|
||||
return new(false, message);
|
||||
return new(false, SH.ServiceGachaLogUrlProviderCacheUrlNotFound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(false, SH.ServiceGachaLogUrlProviderCacheUrlNotFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new(false, string.Format(Regex.Unescape(SH.ServiceGachaLogUrlProviderCachePathNotFound), cacheFile));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -28,12 +28,12 @@ internal sealed partial class UIGFExportService : IUIGFExportService
|
||||
List<UIGFItem> list = appDbContext.GachaItems
|
||||
.Where(i => i.ArchiveId == archive.InnerId)
|
||||
.AsEnumerable()
|
||||
.Select(i => i.ToUIGFItem(context.GetNameQualityByItemId(i.ItemId)))
|
||||
.Select(i => UIGFItem.From(i, context.GetNameQualityByItemId(i.ItemId)))
|
||||
.ToList();
|
||||
|
||||
UIGF uigf = new()
|
||||
{
|
||||
Info = UIGFInfo.Create(serviceProvider, archive.Uid),
|
||||
Info = UIGFInfo.From(serviceProvider, archive.Uid),
|
||||
List = list,
|
||||
};
|
||||
|
||||
|
||||
@@ -45,11 +45,11 @@ internal sealed partial class UIGFImportService : IUIGFImportService
|
||||
UIGFVersion.Major2Minor3OrHigher => uigf.List
|
||||
.OrderByDescending(i => i.Id)
|
||||
.Where(i => i.Id < trimId)
|
||||
.Select(i => GachaItem.CreateForMajor2Minor3OrHigher(archiveId, i)),
|
||||
.Select(i => GachaItem.From(archiveId, i)),
|
||||
UIGFVersion.Major2Minor2OrLower => uigf.List
|
||||
.OrderByDescending(i => i.Id)
|
||||
.Where(i => i.Id < trimId)
|
||||
.Select(i => GachaItem.CreateForMajor2Minor2OrLower(archiveId, i, context.GetItemId(i))),
|
||||
.Select(i => GachaItem.From(archiveId, i, context.GetItemId(i))),
|
||||
_ => Enumerable.Empty<GachaItem>(),
|
||||
};
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ internal sealed partial class GameService : IGameService
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
account = GameAccount.Create(name, registrySdk);
|
||||
account = GameAccount.From(name, registrySdk);
|
||||
|
||||
// sync database
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
|
||||
@@ -158,7 +158,7 @@ internal sealed partial class HutaoCache : IHutaoCache
|
||||
if (idAvatarExtendedMap == null)
|
||||
{
|
||||
Dictionary<AvatarId, Avatar> idAvatarMap = await metadataService.GetIdToAvatarMapAsync().ConfigureAwait(false);
|
||||
idAvatarExtendedMap = AvatarIds.InsertPlayers(idAvatarMap);
|
||||
idAvatarExtendedMap = AvatarIds.WithPlayers(idAvatarMap);
|
||||
}
|
||||
|
||||
return idAvatarExtendedMap;
|
||||
|
||||
@@ -94,19 +94,19 @@ internal sealed partial class MetadataService
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<Dictionary<Level, Dictionary<GrowCurveType, float>>> GetLevelToAvatarCurveMapAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheAsDictionaryAsync<Level, Dictionary<GrowCurveType, float>, GrowCurve>(FileNameAvatarCurve, a => a.Level, a => a.CurveMap, token);
|
||||
return FromCacheAsDictionaryAsync<Level, Dictionary<GrowCurveType, float>, GrowCurve>(FileNameAvatarCurve, a => a.Level, a => a.Map, token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<Dictionary<Level, Dictionary<GrowCurveType, float>>> GetLevelToMonsterCurveMapAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheAsDictionaryAsync<Level, Dictionary<GrowCurveType, float>, GrowCurve>(FileNameMonsterCurve, m => m.Level, m => m.CurveMap, token);
|
||||
return FromCacheAsDictionaryAsync<Level, Dictionary<GrowCurveType, float>, GrowCurve>(FileNameMonsterCurve, m => m.Level, m => m.Map, token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<Dictionary<Level, Dictionary<GrowCurveType, float>>> GetLevelToWeaponCurveMapAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheAsDictionaryAsync<Level, Dictionary<GrowCurveType, float>, GrowCurve>(FileNameWeaponCurve, w => w.Level, w => w.CurveMap, token);
|
||||
return FromCacheAsDictionaryAsync<Level, Dictionary<GrowCurveType, float>, GrowCurve>(FileNameWeaponCurve, w => w.Level, w => w.Map, token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -88,7 +88,7 @@ internal sealed partial class SpiralAbyssRecordService : ISpiralAbyssRecordServi
|
||||
}
|
||||
else
|
||||
{
|
||||
SpiralAbyssEntry newEntry = SpiralAbyssEntry.Create(userAndUid.Uid.Value, webSpiralAbyss);
|
||||
SpiralAbyssEntry newEntry = SpiralAbyssEntry.From(userAndUid.Uid.Value, webSpiralAbyss);
|
||||
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
spiralAbysses!.Insert(0, newEntry);
|
||||
|
||||
@@ -82,7 +82,7 @@ internal sealed partial class SpiralAbyssRecordViewModel : Abstraction.ViewModel
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
idAvatarMap = await metadataService.GetIdToAvatarMapAsync().ConfigureAwait(false);
|
||||
idAvatarMap = AvatarIds.InsertPlayers(idAvatarMap);
|
||||
idAvatarMap = AvatarIds.WithPlayers(idAvatarMap);
|
||||
|
||||
if (UserAndUid.TryFromUser(userService.Current, out UserAndUid? userAndUid))
|
||||
{
|
||||
|
||||
@@ -126,7 +126,7 @@ internal sealed class User : ObservableObject
|
||||
internal static async Task<User?> CreateAsync(Cookie cookie, bool isOversea, CancellationToken token = default)
|
||||
{
|
||||
// 这里只负责创建实体用户,稍后在用户服务中保存到数据库
|
||||
EntityUser entity = EntityUser.Create(cookie, isOversea);
|
||||
EntityUser entity = EntityUser.From(cookie, isOversea);
|
||||
|
||||
entity.Aid = cookie.GetValueOrDefault(Cookie.STUID);
|
||||
entity.Mid = isOversea ? entity.Aid : cookie.GetValueOrDefault(Cookie.MID);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
|
||||
|
||||
internal static class GachaConfigTypeExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 将祈愿配置类型转换到祈愿查询类型
|
||||
/// </summary>
|
||||
/// <param name="configType">配置类型</param>
|
||||
/// <returns>祈愿查询类型</returns>
|
||||
public static GachaConfigType ToQueryType(this GachaConfigType configType)
|
||||
{
|
||||
return configType switch
|
||||
{
|
||||
GachaConfigType.AvatarEventWish2 => GachaConfigType.AvatarEventWish,
|
||||
_ => configType,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user