mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67a1d5dc74 | ||
|
|
6e6d125814 |
@@ -3,7 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Core.Threading;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
@@ -17,7 +17,7 @@ internal static class CoreEnvironment
|
||||
/// <summary>
|
||||
/// 动态密钥1的盐
|
||||
/// </summary>
|
||||
public const string DynamicSecret1Salt = "Qqx8cyv7kuyD8fTw11SmvXSFHp7iZD29";
|
||||
public const string DynamicSecret1Salt = "yUZ3s0Sna1IrSNfk29Vo6vRapdOyqyhB";
|
||||
|
||||
/// <summary>
|
||||
/// 动态密钥2的盐
|
||||
@@ -32,7 +32,7 @@ internal static class CoreEnvironment
|
||||
/// <summary>
|
||||
/// 米游社 Rpc 版本
|
||||
/// </summary>
|
||||
public const string HoyolabXrpcVersion = "2.37.1";
|
||||
public const string HoyolabXrpcVersion = "2.38.1";
|
||||
|
||||
/// <summary>
|
||||
/// 标准UA
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using Snap.Hutao.Core.Threading;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
|
||||
|
||||
@@ -70,9 +70,8 @@ public sealed class LogEntryQueue : IDisposable
|
||||
logDbContext.Database.Migrate();
|
||||
}
|
||||
|
||||
logDbContext.Logs.RemoveRange(logDbContext.Logs);
|
||||
logDbContext.SaveChanges();
|
||||
|
||||
// only raw sql can pass
|
||||
logDbContext.Database.ExecuteSqlRaw("DELETE FROM logs WHERE Exception IS NULL");
|
||||
return logDbContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 信号量扩展
|
||||
@@ -15,7 +15,7 @@ public static class SemaphoreSlimExtensions
|
||||
/// <returns>可释放的对象,用于释放信号量</returns>
|
||||
public static async Task<IDisposable> EnterAsync(this SemaphoreSlim semaphoreSlim)
|
||||
{
|
||||
await semaphoreSlim.WaitAsync();
|
||||
await semaphoreSlim.WaitAsync().ConfigureAwait(false);
|
||||
return new SemaphoreSlimReleaser(semaphoreSlim);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Snap.Hutao.Extension;
|
||||
/// <summary>
|
||||
/// <see cref="BinaryReader"/> 扩展
|
||||
/// </summary>
|
||||
public static class BinaryReaderExtensions
|
||||
public static class BinaryReaderExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断是否处于流的结尾
|
||||
@@ -6,7 +6,7 @@ namespace Snap.Hutao.Extension;
|
||||
/// <summary>
|
||||
/// <see cref="DateTimeOffset"/> 扩展
|
||||
/// </summary>
|
||||
public static class DateTimeOffsetExtensions
|
||||
public static class DateTimeOffsetExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the current <see cref="DateTimeOffset"/> to a <see cref="DateTimeOffset"/> that represents the local time.
|
||||
@@ -8,7 +8,7 @@ namespace Snap.Hutao.Extension;
|
||||
/// <summary>
|
||||
/// 枚举拓展
|
||||
/// </summary>
|
||||
public static class EnumExtensions
|
||||
public static class EnumExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取枚举的描述
|
||||
@@ -9,7 +9,7 @@ namespace Snap.Hutao.Extension;
|
||||
/// <summary>
|
||||
/// <see cref="IEnumerable{T}"/> 扩展
|
||||
/// </summary>
|
||||
public static partial class EnumerableExtensions
|
||||
public static partial class EnumerableExtension
|
||||
{
|
||||
/// <inheritdoc cref="Enumerable.Average(IEnumerable{int})"/>
|
||||
public static double AverageNoThrow(this List<int> source)
|
||||
@@ -6,7 +6,7 @@ namespace Snap.Hutao.Extension;
|
||||
/// <summary>
|
||||
/// 数高性能扩展
|
||||
/// </summary>
|
||||
public static class NumberExtensions
|
||||
public static class NumberExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取从右向左某位上的数字
|
||||
@@ -6,7 +6,7 @@ namespace Snap.Hutao.Extension;
|
||||
/// <summary>
|
||||
/// 对象扩展
|
||||
/// </summary>
|
||||
public static class ObjectExtensions
|
||||
public static class ObjectExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// <see langword="as"/> 的链式调用扩展
|
||||
@@ -8,7 +8,7 @@ namespace Snap.Hutao.Extension;
|
||||
/// <summary>
|
||||
/// 包版本扩展
|
||||
/// </summary>
|
||||
public static class PackageVersionExtensions
|
||||
public static class PackageVersionExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 将包版本转换为版本
|
||||
@@ -28,7 +28,7 @@ public class UIAFInfo
|
||||
public DateTimeOffset ExportDateTime
|
||||
{
|
||||
// Hot fix | 1.0.31 | UIAF.Info.ExportTimestamp can be milliseconds
|
||||
get => DateTimeOffsetExtensions.FromUnixTime(ExportTimestamp, DateTimeOffset.MinValue);
|
||||
get => DateTimeOffsetExtension.FromUnixTime(ExportTimestamp, DateTimeOffset.MinValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -34,7 +34,7 @@ public class UIGFInfo
|
||||
/// </summary>
|
||||
public DateTimeOffset ExportDateTime
|
||||
{
|
||||
get => DateTimeOffsetExtensions.FromUnixTime(ExportTimestamp, DateTimeOffset.MinValue);
|
||||
get => DateTimeOffsetExtension.FromUnixTime(ExportTimestamp, DateTimeOffset.MinValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -117,6 +117,11 @@ internal class AvatarInfoService : IAvatarInfoService
|
||||
|
||||
foreach (Web.Enka.Model.AvatarInfo webInfo in webInfos)
|
||||
{
|
||||
if (webInfo.AvatarId == 10000005 || webInfo.AvatarId == 10000007)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Model.Entity.AvatarInfo? entity = dbInfos.SingleOrDefault(i => i.Info.AvatarId == webInfo.AvatarId);
|
||||
|
||||
if (entity == null)
|
||||
@@ -141,8 +146,9 @@ internal class AvatarInfoService : IAvatarInfoService
|
||||
return appDbContext.AvatarInfos
|
||||
.Where(i => i.Uid == uid)
|
||||
.Select(i => i.Info)
|
||||
.AsEnumerable()
|
||||
.OrderByDescending(i => i.AvatarId)
|
||||
|
||||
// .AsEnumerable()
|
||||
// .OrderByDescending(i => i.AvatarId)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,6 @@ internal class AnnouncementClient
|
||||
.GetFromJsonAsync<Response<ListWrapper<AnnouncementContent>>>(ApiEndpoints.AnnContent, jsonSerializerOptions, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data?.List);
|
||||
return EnumerableExtension.EmptyIfNull(resp?.Data?.List);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Snap.Hutao.Web.Hoyolab;
|
||||
/// </summary>
|
||||
public struct PlayerUid
|
||||
{
|
||||
private string? region = null;
|
||||
private string? region = default;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的玩家 Uid 结构
|
||||
|
||||
@@ -45,6 +45,6 @@ internal class BindingClient
|
||||
.TryCatchGetFromJsonAsync<Response<ListWrapper<UserGameRole>>>(ApiEndpoints.UserGameRoles, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data?.List);
|
||||
return EnumerableExtension.EmptyIfNull(resp?.Data?.List);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ internal class GameRecordClient
|
||||
.TryCatchPostAsJsonAsync<Response<CharacterWrapper>>(logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data?.Avatars);
|
||||
return EnumerableExtension.EmptyIfNull(resp?.Data?.Avatars);
|
||||
}
|
||||
|
||||
private class CharacterData
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
@@ -21,57 +20,25 @@ namespace Snap.Hutao.Web.Hutao;
|
||||
/// </summary>
|
||||
// [Injection(InjectAs.Transient)]
|
||||
[HttpClient(HttpClientConfigration.Default)]
|
||||
internal class HutaoClient : ISupportAsyncInitialization
|
||||
internal class HutaoClient
|
||||
{
|
||||
private const string AuthHost = "https://auth.snapgenshin.com";
|
||||
private const string HutaoAPI = "https://hutao-api.snapgenshin.com";
|
||||
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly GameRecordClient gameRecordClient;
|
||||
private readonly JsonSerializerOptions jsonSerializerOptions;
|
||||
|
||||
private bool isInitialized = false;
|
||||
private readonly JsonSerializerOptions options;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的胡桃API客户端
|
||||
/// </summary>
|
||||
/// <param name="httpClient">http客户端</param>
|
||||
/// <param name="gameRecordClient">游戏记录客户端</param>
|
||||
/// <param name="jsonSerializerOptions">json序列化选项</param>
|
||||
public HutaoClient(
|
||||
HttpClient httpClient,
|
||||
GameRecordClient gameRecordClient,
|
||||
JsonSerializerOptions jsonSerializerOptions)
|
||||
/// <param name="options">json序列化选项</param>
|
||||
public HutaoClient(HttpClient httpClient, GameRecordClient gameRecordClient, JsonSerializerOptions options)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.gameRecordClient = gameRecordClient;
|
||||
this.jsonSerializerOptions = jsonSerializerOptions;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsInitialized { get => isInitialized; private set => isInitialized = value; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<bool> InitializeAsync(CancellationToken token = default)
|
||||
{
|
||||
if (!IsInitialized)
|
||||
{
|
||||
Auth auth = new(
|
||||
"08da6c59-da3b-48dd-8cf3-e3935a7f1d4f",
|
||||
"ox5dwglSXYgenK2YBc8KrAVPoQbIJ4eHfUciE+05WfI=");
|
||||
|
||||
HttpResponseMessage response = await httpClient
|
||||
.PostAsJsonAsync($"{AuthHost}/Auth/Login", auth, jsonSerializerOptions, token)
|
||||
.ConfigureAwait(false);
|
||||
Response<Token>? resp = await response.Content
|
||||
.ReadFromJsonAsync<Response<Token>>(jsonSerializerOptions, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
httpClient.DefaultRequestHeaders.Authorization = new("Bearer", Must.NotNull(resp?.Data?.AccessToken!));
|
||||
IsInitialized = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -81,15 +48,13 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
/// <param name="uid">uid</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>当前是否上传了数据</returns>
|
||||
public async Task<bool> CheckPeriodRecordUploadedAsync(PlayerUid uid, CancellationToken token = default)
|
||||
public async Task<bool> CheckRecordUploadedAsync(PlayerUid uid, CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<UploadStatus>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<UploadStatus>>($"{HutaoAPI}/Record/CheckRecord/{uid}", token)
|
||||
Response<bool>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<bool>>($"{HutaoAPI}/Record/Check?uid={uid}", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp is { Data: not null, Data.PeriodUploaded: true };
|
||||
return resp?.Data == true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -99,12 +64,10 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
/// <param name="uid">uid</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>排行信息</returns>
|
||||
public async Task<RankInfoWrapper?> GetRankInfoAsync(PlayerUid uid, CancellationToken token = default)
|
||||
public async Task<RankInfo?> GetRankAsync(PlayerUid uid, CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<RankInfoWrapper>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<RankInfoWrapper>>($"{HutaoAPI}/Record/Rank/{uid}", token)
|
||||
Response<RankInfo>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<RankInfo>>($"{HutaoAPI}/Record/Rank?uid={uid}", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp?.Data;
|
||||
@@ -118,8 +81,6 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
/// <returns>总览信息</returns>
|
||||
public async Task<Overview?> GetOverviewAsync(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<Overview>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<Overview>>($"{HutaoAPI}/Statistics/Overview", token)
|
||||
.ConfigureAwait(false);
|
||||
@@ -129,19 +90,17 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取角色出场率
|
||||
/// GET /Statistics/AvatarParticipation
|
||||
/// GET /Statistics/Avatar/AttendanceRate
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色出场率</returns>
|
||||
public async Task<IEnumerable<AvatarParticipation>> GetAvatarParticipationsAsync(CancellationToken token = default)
|
||||
public async Task<IEnumerable<AvatarAppearanceRank>> GetAvatarAttendanceRatesAsync(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<IEnumerable<AvatarParticipation>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarParticipation>>>($"{HutaoAPI}/Statistics/AvatarParticipation", token)
|
||||
Response<IEnumerable<AvatarAppearanceRank>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarAppearanceRank>>>($"{HutaoAPI}/Statistics/Avatar/AttendanceRate", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
return EnumerableExtension.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -150,66 +109,28 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色出场率</returns>
|
||||
public async Task<IEnumerable<AvatarParticipation>> GetAvatarParticipations2Async(CancellationToken token = default)
|
||||
public async Task<IEnumerable<AvatarUsageRank>> GetAvatarParticipations2Async(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<IEnumerable<AvatarParticipation>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarParticipation>>>($"{HutaoAPI}/Statistics2/AvatarParticipation", token)
|
||||
Response<IEnumerable<AvatarUsageRank>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarUsageRank>>>($"{HutaoAPI}/Statistics/Avatar/HoldingRate", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
return EnumerableExtension.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取角色圣遗物搭配
|
||||
/// 异步获取角色/武器/圣遗物搭配
|
||||
/// GET /Statistics/AvatarReliquaryUsage
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色圣遗物搭配</returns>
|
||||
public async Task<IEnumerable<AvatarReliquaryUsage>> GetAvatarReliquaryUsagesAsync(CancellationToken token = default)
|
||||
/// <returns>角色/武器/圣遗物搭配</returns>
|
||||
public async Task<IEnumerable<AvatarCollocation>> GetAvatarCollocationsAsync(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<IEnumerable<AvatarReliquaryUsage>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarReliquaryUsage>>>($"{HutaoAPI}/Statistics/AvatarReliquaryUsage", token)
|
||||
Response<IEnumerable<AvatarCollocation>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarCollocation>>>($"{HutaoAPI}/Statistics/Avatar/AvatarCollocation", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取角色搭配数据
|
||||
/// GET /Statistics/TeamCollocation
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色搭配数据</returns>
|
||||
public async Task<IEnumerable<TeamCollocation>> GetTeamCollocationsAsync(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<IEnumerable<TeamCollocation>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<TeamCollocation>>>($"{HutaoAPI}/Statistics/TeamCollocation", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取角色武器搭配数据
|
||||
/// GET /Statistics/AvatarWEaponUsage
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色武器搭配数据</returns>
|
||||
public async Task<IEnumerable<AvatarWeaponUsage>> GetAvatarWeaponUsagesAsync(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<IEnumerable<AvatarWeaponUsage>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarWeaponUsage>>>($"{HutaoAPI}/Statistics/AvatarWeaponUsage", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
return EnumerableExtension.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -218,74 +139,28 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色图片列表</returns>
|
||||
public async Task<IEnumerable<AvatarConstellation>> GetAvatarConstellationsAsync(CancellationToken token = default)
|
||||
public async Task<IEnumerable<AvatarConstellationInfo>> GetAvatarConstellationInfosAsync(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<IEnumerable<AvatarConstellation>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarConstellation>>>($"{HutaoAPI}/Statistics/Constellation", token)
|
||||
Response<IEnumerable<AvatarConstellationInfo>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<AvatarConstellationInfo>>>($"{HutaoAPI}/Statistics/Constellation", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
return EnumerableExtension.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取队伍出场次数 层间
|
||||
/// 异步获取队伍出场次数
|
||||
/// GET /Statistics/TeamCombination
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>队伍出场列表</returns>
|
||||
public async Task<IEnumerable<TeamCombination>> GetTeamCombinationsAsync(CancellationToken token = default)
|
||||
public async Task<IEnumerable<TeamAppearance>> GetTeamCombinationsAsync(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<IEnumerable<TeamCombination>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<TeamCombination>>>($"{HutaoAPI}/Statistics/TeamCombination", token)
|
||||
Response<IEnumerable<TeamAppearance>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<TeamAppearance>>>($"{HutaoAPI}/Team/Combination", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取队伍出场次数 层
|
||||
/// GET /Statistics2/TeamCombination
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>队伍出场列表</returns>
|
||||
public async Task<IEnumerable<TeamCombination2>> GetTeamCombinations2Async(CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
Response<IEnumerable<TeamCombination2>>? resp = await httpClient
|
||||
.GetFromJsonAsync<Response<IEnumerable<TeamCombination2>>>($"{HutaoAPI}/Statistics2/TeamCombination", token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步按角色列表异步获取推荐队伍
|
||||
/// POST /Statistics2/TeamRecommanded
|
||||
/// </summary>
|
||||
/// <param name="floor">楼层</param>
|
||||
/// <param name="avatarIds">期望的角色,按期望出现顺序排序</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>队伍出场列表</returns>
|
||||
public async Task<IEnumerable<TeamCombination2>> GetRecommandedTeamCombination2sAsync(int floor, IEnumerable<string> avatarIds, CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
DesiredInfo desiredInfo = new(floor, avatarIds);
|
||||
|
||||
HttpResponseMessage response = await httpClient
|
||||
.PostAsJsonAsync($"{HutaoAPI}/Statistics2/TeamRecommanded", desiredInfo, jsonSerializerOptions, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Response<IEnumerable<TeamCombination2>>? resp = await response.Content
|
||||
.ReadFromJsonAsync<Response<IEnumerable<TeamCombination2>>>(jsonSerializerOptions, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return EnumerableExtensions.EmptyIfNull(resp?.Data);
|
||||
return EnumerableExtension.EmptyIfNull(resp?.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -294,7 +169,7 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>玩家记录</returns>
|
||||
public async Task<PlayerRecord> GetPlayerRecordAsync(Snap.Hutao.Model.Binding.User user, CancellationToken token = default)
|
||||
public async Task<SimpleRecord> GetPlayerRecordAsync(Snap.Hutao.Model.Binding.User user, CancellationToken token = default)
|
||||
{
|
||||
PlayerInfo? playerInfo = await gameRecordClient
|
||||
.GetPlayerInfoAsync(user, token)
|
||||
@@ -310,7 +185,7 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
.ConfigureAwait(false);
|
||||
Must.NotNull(spiralAbyssInfo!);
|
||||
|
||||
return PlayerRecord.Create(Must.NotNull(user.SelectedUserGameRole!).GameUid, characters, spiralAbyssInfo);
|
||||
return new(Must.NotNull(user.SelectedUserGameRole!).GameUid, characters, spiralAbyssInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -320,35 +195,14 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
/// <param name="playerRecord">玩家记录</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
internal async Task<Response<string>?> UploadRecordAsync(PlayerRecord playerRecord, CancellationToken token = default)
|
||||
public async Task<Response<string>?> UploadRecordAsync(SimpleRecord playerRecord, CancellationToken token = default)
|
||||
{
|
||||
Verify.Operation(IsInitialized, "必须在初始化后才能调用其他方法");
|
||||
|
||||
HttpResponseMessage response = await httpClient
|
||||
.PostAsJsonAsync($"{HutaoAPI}/Record/Upload", playerRecord, jsonSerializerOptions, token)
|
||||
.PostAsJsonAsync($"{HutaoAPI}/Record/Upload", playerRecord, options, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return await response.Content
|
||||
.ReadFromJsonAsync<Response<string>>(jsonSerializerOptions, token)
|
||||
.ReadFromJsonAsync<Response<string>>(options, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private class Auth
|
||||
{
|
||||
public Auth(string appid, string secret)
|
||||
{
|
||||
Appid = appid;
|
||||
Secret = secret;
|
||||
}
|
||||
|
||||
public string Appid { get; }
|
||||
|
||||
public string Secret { get; }
|
||||
}
|
||||
|
||||
private class Token
|
||||
{
|
||||
public string AccessToken { get; } = default!;
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,17 @@
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 出场数据
|
||||
/// 出场率
|
||||
/// </summary>
|
||||
public class AvatarParticipation
|
||||
public class AvatarAppearanceRank
|
||||
{
|
||||
/// <summary>
|
||||
/// 层
|
||||
/// 楼层
|
||||
/// </summary>
|
||||
public int Floor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色比率
|
||||
/// 排行
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<int>> AvatarUsage { get; set; } = default!;
|
||||
public List<ItemRate<int, double>> Ranks { get; set; } = default!;
|
||||
}
|
||||
15
src/Snap.Hutao/Snap.Hutao/Web/Hutao/Model/AvatarBuild.cs
Normal file
15
src/Snap.Hutao/Snap.Hutao/Web/Hutao/Model/AvatarBuild.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 角色相关解构
|
||||
/// </summary>
|
||||
public abstract class AvatarBuild
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// </summary>
|
||||
public int AvatarId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 角色搭配
|
||||
/// </summary>
|
||||
public class AvatarCollocation : AvatarBuild
|
||||
{
|
||||
/// <summary>
|
||||
/// 其他角色
|
||||
/// </summary>
|
||||
public List<ItemRate<int, double>> Avatars { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 武器
|
||||
/// </summary>
|
||||
public List<ItemRate<int, double>> Weapons { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物
|
||||
/// </summary>
|
||||
public List<ItemRate<ReliquarySets, double>> Reliquaries { get; set; } = default!;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 命座比例
|
||||
/// </summary>
|
||||
public class AvatarConstellation
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色ID
|
||||
/// </summary>
|
||||
public int Avatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 持有率
|
||||
/// </summary>
|
||||
public decimal HoldingRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 各命座比率
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<int>> Rate { get; set; } = default!;
|
||||
}
|
||||
@@ -4,18 +4,17 @@
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 比率
|
||||
/// 角色命座信息
|
||||
/// </summary>
|
||||
/// <typeparam name="T"><see cref="Id"/> 的类型</typeparam>
|
||||
public class Rate<T>
|
||||
public class AvatarConstellationInfo : AvatarBuild
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示唯一标识符的实例
|
||||
/// 持有率
|
||||
/// </summary>
|
||||
public T Id { get; set; } = default!;
|
||||
public double HoldingRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 比率
|
||||
/// 命之座
|
||||
/// </summary>
|
||||
public decimal Value { get; set; }
|
||||
public List<ItemRate<int, double>> Constellations { get; set; } = default!;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物配置数据
|
||||
/// </summary>
|
||||
public class AvatarReliquaryUsage
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// </summary>
|
||||
public int Avatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物比率
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<ReliquarySets>> ReliquaryUsage { get; set; } = default!;
|
||||
}
|
||||
@@ -4,17 +4,17 @@
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 带有层的间编号
|
||||
/// 使用率
|
||||
/// </summary>
|
||||
public class LevelInfo
|
||||
public class AvatarUsageRank
|
||||
{
|
||||
/// <summary>
|
||||
/// 层
|
||||
/// 楼层
|
||||
/// </summary>
|
||||
public int Floor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上下半 0,1
|
||||
/// 排行
|
||||
/// </summary>
|
||||
public int Index { get; set; }
|
||||
public List<ItemRate<int, double>> Ranks { get; set; } = default!;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 胡桃数据库物品
|
||||
/// </summary>
|
||||
public class Item
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的胡桃数据库物品
|
||||
/// </summary>
|
||||
/// <param name="id">物品Id</param>
|
||||
/// <param name="name">名称</param>
|
||||
/// <param name="url">链接</param>
|
||||
[JsonConstructor]
|
||||
public Item(int id, string name, string url)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Url = url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 物品Id
|
||||
/// </summary>
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 链接
|
||||
/// </summary>
|
||||
public string Url { get; }
|
||||
}
|
||||
33
src/Snap.Hutao/Snap.Hutao/Web/Hutao/Model/ItemRate.cs
Normal file
33
src/Snap.Hutao/Snap.Hutao/Web/Hutao/Model/ItemRate.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 物品与率
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">物品类型</typeparam>
|
||||
/// <typeparam name="TRate">率类型</typeparam>
|
||||
public class ItemRate<TItem, TRate>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的物品与率
|
||||
/// </summary>
|
||||
/// <param name="item">物品</param>
|
||||
/// <param name="rate">率</param>
|
||||
public ItemRate(TItem item, TRate rate)
|
||||
{
|
||||
Item = item;
|
||||
Rate = rate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 物品
|
||||
/// </summary>
|
||||
public TItem Item { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 率
|
||||
/// </summary>
|
||||
public TRate Rate { get; set; }
|
||||
}
|
||||
@@ -9,17 +9,22 @@ namespace Snap.Hutao.Web.Hutao.Model;
|
||||
public class Overview
|
||||
{
|
||||
/// <summary>
|
||||
/// 所有用户数量
|
||||
/// 规划Id
|
||||
/// </summary>
|
||||
public int TotalPlayerCount { get; set; }
|
||||
public int ScheduleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当期提交深渊数据用户数量
|
||||
/// 总记录数
|
||||
/// </summary>
|
||||
public int CollectedPlayerCount { get; set; }
|
||||
public int RecordTotal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当期满星用户数量
|
||||
/// 总深渊计数
|
||||
/// </summary>
|
||||
public int FullStarPlayerCount { get; set; }
|
||||
public int SpiralAbyssTotal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 满星数
|
||||
/// </summary>
|
||||
public int SpiralAbyssFullStar { get; set; }
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 角色圣遗物套装
|
||||
/// </summary>
|
||||
public class AvatarReliquarySet
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的角色圣遗物套装
|
||||
/// </summary>
|
||||
/// <param name="id">套装Id</param>
|
||||
/// <param name="count">个数</param>
|
||||
public AvatarReliquarySet(int id, int count)
|
||||
{
|
||||
Id = id;
|
||||
Count = count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的角色圣遗物套装
|
||||
/// </summary>
|
||||
/// <param name="kvp">键值对</param>
|
||||
public AvatarReliquarySet(KeyValuePair<int, int> kvp)
|
||||
: this(kvp.Key, kvp.Value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 套装Id
|
||||
/// </summary>
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 个数
|
||||
/// </summary>
|
||||
public int Count { get; }
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 角色武器
|
||||
/// </summary>
|
||||
public class AvatarWeapon
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的角色武器
|
||||
/// </summary>
|
||||
/// <param name="id">武器Id</param>
|
||||
/// <param name="level">武器等级</param>
|
||||
/// <param name="affixLevel">精炼等级</param>
|
||||
public AvatarWeapon(int id, int level, int affixLevel)
|
||||
{
|
||||
Id = id;
|
||||
Level = level;
|
||||
AffixLevel = affixLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 武器等级
|
||||
/// </summary>
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 武器等级
|
||||
/// </summary>
|
||||
public int Level { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 精炼
|
||||
/// </summary>
|
||||
public int AffixLevel { get; }
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 封装期望楼层与角色列表
|
||||
/// </summary>
|
||||
public class DesiredInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的封装类
|
||||
/// </summary>
|
||||
/// <param name="floor">楼层</param>
|
||||
/// <param name="desiredAvatars">期望角色,按期望顺序排序</param>
|
||||
public DesiredInfo(int floor, IEnumerable<string> desiredAvatars)
|
||||
{
|
||||
Floor = floor;
|
||||
DesiredAvatars = desiredAvatars;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 层
|
||||
/// </summary>
|
||||
public int Floor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 期望角色
|
||||
/// </summary>
|
||||
public IEnumerable<string> DesiredAvatars { get; set; }
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 原神物品包装器
|
||||
/// </summary>
|
||||
public class GenshinItemWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的原神物品包装器
|
||||
/// </summary>
|
||||
/// <param name="avatars">角色</param>
|
||||
/// <param name="weapons">武器</param>
|
||||
/// <param name="reliquaries">圣遗物</param>
|
||||
public GenshinItemWrapper(IEnumerable<Item> avatars, IEnumerable<Item> weapons, IEnumerable<Item> reliquaries)
|
||||
{
|
||||
Avatars = avatars;
|
||||
Weapons = weapons;
|
||||
Reliquaries = reliquaries;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 角色列表
|
||||
/// </summary>
|
||||
public IEnumerable<Item> Avatars { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 武器列表
|
||||
/// </summary>
|
||||
public IEnumerable<Item> Weapons { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物列表
|
||||
/// </summary>
|
||||
public IEnumerable<Item> Reliquaries { get; }
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.SpiralAbyss;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 带有层信息的间
|
||||
/// </summary>
|
||||
internal class IndexedLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的带有层信息的间
|
||||
/// </summary>
|
||||
/// <param name="floorIndex">层号</param>
|
||||
/// <param name="level">间信息</param>
|
||||
public IndexedLevel(int floorIndex, Level level)
|
||||
{
|
||||
FloorIndex = floorIndex;
|
||||
Level = level;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 层号
|
||||
/// </summary>
|
||||
public int FloorIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 层信息
|
||||
/// </summary>
|
||||
public Level Level { get; }
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.Avatar;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 玩家角色
|
||||
/// </summary>
|
||||
public class PlayerAvatar
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的玩家角色
|
||||
/// </summary>
|
||||
/// <param name="avatar">角色</param>
|
||||
internal PlayerAvatar(Character avatar)
|
||||
{
|
||||
Id = avatar.Id;
|
||||
Level = avatar.Level;
|
||||
ActivedConstellationNum = avatar.ActivedConstellationNum;
|
||||
Weapon = new(avatar.Weapon.Id, avatar.Weapon.Level, avatar.Weapon.AffixLevel);
|
||||
ReliquarySets = avatar.Reliquaries
|
||||
.CountBy(relic => relic.ReliquarySet.Id)
|
||||
.Select(kvp => new AvatarReliquarySet(kvp))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// </summary>
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色等级
|
||||
/// </summary>
|
||||
public int Level { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 命座
|
||||
/// </summary>
|
||||
public int ActivedConstellationNum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 武器
|
||||
/// </summary>
|
||||
public AvatarWeapon Weapon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物套装
|
||||
/// </summary>
|
||||
public List<AvatarReliquarySet> ReliquarySets { get; }
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.Avatar;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.SpiralAbyss;
|
||||
using Snap.Hutao.Web.Response;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 玩家记录
|
||||
/// 使用 <see cref="CreateAsync(string, List{Character}, SpiralAbyss)"/> 来构建一个实例
|
||||
/// </summary>
|
||||
public class PlayerRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// 防止从外部构造一个新的玩家记录
|
||||
/// </summary>
|
||||
private PlayerRecord()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// uid
|
||||
/// </summary>
|
||||
public string Uid { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 玩家角色
|
||||
/// </summary>
|
||||
public IEnumerable<PlayerAvatar> PlayerAvatars { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 玩家深渊信息
|
||||
/// </summary>
|
||||
public IEnumerable<PlayerSpiralAbyssLevel> PlayerSpiralAbyssesLevels { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 造成最多伤害
|
||||
/// </summary>
|
||||
public Damage? DamageMost { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 承受最多伤害
|
||||
/// </summary>
|
||||
public Damage? TakeDamageMost { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 建造玩家记录
|
||||
/// </summary>
|
||||
/// <param name="uid">玩家的uid</param>
|
||||
/// <param name="detailAvatars">角色详情信息</param>
|
||||
/// <param name="spiralAbyss">深渊信息</param>
|
||||
/// <returns>玩家记录</returns>
|
||||
internal static PlayerRecord Create(string uid, List<Character> detailAvatars, SpiralAbyss spiralAbyss)
|
||||
{
|
||||
IEnumerable<PlayerAvatar> playerAvatars = detailAvatars
|
||||
.Select(avatar => new PlayerAvatar(avatar));
|
||||
|
||||
IEnumerable<PlayerSpiralAbyssLevel> playerSpiralAbyssLevels = spiralAbyss.Floors
|
||||
.SelectMany(f => f.Levels, (f, level) => new IndexedLevel(f.Index, level))
|
||||
.Select(indexedLevel => new PlayerSpiralAbyssLevel(indexedLevel));
|
||||
|
||||
return new()
|
||||
{
|
||||
Uid = uid,
|
||||
PlayerAvatars = playerAvatars,
|
||||
PlayerSpiralAbyssesLevels = playerSpiralAbyssLevels,
|
||||
DamageMost = GetDamage(spiralAbyss.DamageRank),
|
||||
TakeDamageMost = GetDamage(spiralAbyss.TakeDamageRank),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传记录
|
||||
/// </summary>
|
||||
/// <param name="hutaoClient">使用的客户端</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>上传结果</returns>
|
||||
internal Task<Response<string>?> UploadAsync(HutaoClient hutaoClient, CancellationToken token = default)
|
||||
{
|
||||
return hutaoClient.UploadRecordAsync(this, token);
|
||||
}
|
||||
|
||||
private static Damage? GetDamage(List<Rank> ranks)
|
||||
{
|
||||
if (ranks.Count > 0)
|
||||
{
|
||||
Rank rank = ranks[0];
|
||||
return new Damage(rank.AvatarId, rank.Value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 玩家深渊战斗间信息
|
||||
/// </summary>
|
||||
public class PlayerSpiralAbyssLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的玩家深渊战斗间信息
|
||||
/// </summary>
|
||||
/// <param name="indexedLevel">楼层</param>
|
||||
internal PlayerSpiralAbyssLevel(IndexedLevel indexedLevel)
|
||||
{
|
||||
FloorIndex = indexedLevel.FloorIndex;
|
||||
LevelIndex = indexedLevel.Level.Index;
|
||||
Star = indexedLevel.Level.Star;
|
||||
Battles = indexedLevel.Level.Battles
|
||||
.Select(battle => new PlayerSpiralAbyssBattle(battle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 层号
|
||||
/// </summary>
|
||||
public int FloorIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 间号
|
||||
/// </summary>
|
||||
public int LevelIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 星数
|
||||
/// </summary>
|
||||
public int Star { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 战斗列表 分上下半间
|
||||
/// </summary>
|
||||
public IEnumerable<PlayerSpiralAbyssBattle> Battles { get; }
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.Avatar;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 角色详情 角色
|
||||
/// </summary>
|
||||
public class SimpleAvatar
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的角色详情 角色
|
||||
/// </summary>
|
||||
/// <param name="character">角色</param>
|
||||
public SimpleAvatar(Character character)
|
||||
{
|
||||
AvatarId = character.Id;
|
||||
WeaponId = character.Weapon.Id;
|
||||
ReliquarySetIds = character.Reliquaries.Select(r => r.ReliquarySet.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 角色 Id
|
||||
/// </summary>
|
||||
public int AvatarId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 武器 Id
|
||||
/// </summary>
|
||||
public int WeaponId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物套装Id
|
||||
/// </summary>
|
||||
public IEnumerable<int> ReliquarySetIds { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 命座
|
||||
/// </summary>
|
||||
public int ActivedConstellationNumber { get; set; }
|
||||
}
|
||||
@@ -6,27 +6,27 @@ using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.SpiralAbyss;
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 玩家深渊某间的战斗信息
|
||||
/// 上下半信息
|
||||
/// </summary>
|
||||
public class PlayerSpiralAbyssBattle
|
||||
public class SimpleBattle
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的战斗信息
|
||||
/// 构造一个新的战斗
|
||||
/// </summary>
|
||||
/// <param name="battle">战斗</param>
|
||||
internal PlayerSpiralAbyssBattle(Battle battle)
|
||||
public SimpleBattle(Battle battle)
|
||||
{
|
||||
BattleIndex = battle.Index;
|
||||
AvatarIds = battle.Avatars.Select(a => a.Id);
|
||||
Index = battle.Index;
|
||||
Avatars = battle.Avatars.Select(a => a.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 战斗上下半间 0,1
|
||||
/// 上下半遍号 1-2
|
||||
/// </summary>
|
||||
public int BattleIndex { get; }
|
||||
public int Index { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色Id列表
|
||||
/// 角色列表
|
||||
/// </summary>
|
||||
public IEnumerable<int> AvatarIds { get; }
|
||||
public IEnumerable<int> Avatars { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.SpiralAbyss;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 层信息
|
||||
/// </summary>
|
||||
public class SimpleFloor
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的层信息
|
||||
/// </summary>
|
||||
/// <param name="floor">层信息</param>
|
||||
public SimpleFloor(Floor floor)
|
||||
{
|
||||
Index = floor.Index;
|
||||
Star = floor.Star;
|
||||
Levels = floor.Levels.Select(l => new SimpleLevel(l));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 层遍号 1-12|9-12
|
||||
/// </summary>
|
||||
public int Index { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 星数
|
||||
/// </summary>
|
||||
public int Star { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 间
|
||||
/// </summary>
|
||||
public IEnumerable<SimpleLevel> Levels { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.SpiralAbyss;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 间信息
|
||||
/// </summary>
|
||||
public class SimpleLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的间信息
|
||||
/// </summary>
|
||||
/// <param name="level">间信息</param>
|
||||
public SimpleLevel(Level level)
|
||||
{
|
||||
Index = level.Index;
|
||||
Star = level.Star;
|
||||
Battles = level.Battles.Select(b => new SimpleBattle(b));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 间遍号 1-3
|
||||
/// </summary>
|
||||
public int Index { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 星数
|
||||
/// </summary>
|
||||
public int Star { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上下半信息
|
||||
/// </summary>
|
||||
public IEnumerable<SimpleBattle> Battles { get; set; } = default!;
|
||||
}
|
||||
@@ -1,22 +1,23 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.SpiralAbyss;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 伤害信息
|
||||
/// 数值
|
||||
/// </summary>
|
||||
public class Damage
|
||||
public class SimpleRank
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的伤害信息
|
||||
/// 构造一个新的数值
|
||||
/// </summary>
|
||||
/// <param name="avatarId">角色Id</param>
|
||||
/// <param name="value">值</param>
|
||||
public Damage(int avatarId, int value)
|
||||
/// <param name="rank">排行</param>
|
||||
public SimpleRank(Rank rank)
|
||||
{
|
||||
AvatarId = avatarId;
|
||||
Value = value;
|
||||
AvatarId = rank.AvatarId;
|
||||
Value = rank.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.Avatar;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.SpiralAbyss;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 记录
|
||||
/// </summary>
|
||||
public class SimpleRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的记录
|
||||
/// </summary>
|
||||
/// <param name="uid">uid</param>
|
||||
/// <param name="characters">详细的角色信息</param>
|
||||
/// <param name="spiralAbyss">深渊信息</param>
|
||||
public SimpleRecord(string uid, List<Character> characters, SpiralAbyss spiralAbyss)
|
||||
{
|
||||
Uid = uid;
|
||||
Identity = "Snap Hutao";
|
||||
SpiralAbyss = new(spiralAbyss);
|
||||
Avatars = characters.Select(a => new SimpleAvatar(a));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uid
|
||||
/// </summary>
|
||||
public string Uid { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 上传者身份
|
||||
/// </summary>
|
||||
public string Identity { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 深境螺旋
|
||||
/// </summary>
|
||||
public SimpleSpiralAbyss SpiralAbyss { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 角色
|
||||
/// </summary>
|
||||
public IEnumerable<SimpleAvatar> Avatars { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.SpiralAbyss;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 深渊数据
|
||||
/// </summary>
|
||||
public class SimpleSpiralAbyss
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的深渊信息
|
||||
/// </summary>
|
||||
/// <param name="spiralAbyss">深渊信息</param>
|
||||
public SimpleSpiralAbyss(SpiralAbyss spiralAbyss)
|
||||
{
|
||||
ScheduleId = spiralAbyss.ScheduleId;
|
||||
Damage = new(spiralAbyss.DamageRank.Single());
|
||||
TakeDamage = new(spiralAbyss.TakeDamageRank.Single());
|
||||
Floors = spiralAbyss.Floors.Select(f => new SimpleFloor(f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计划Id
|
||||
/// </summary>
|
||||
public int ScheduleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 造成伤害
|
||||
/// </summary>
|
||||
public SimpleRank Damage { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 受到伤害
|
||||
/// </summary>
|
||||
public SimpleRank TakeDamage { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 层
|
||||
/// </summary>
|
||||
public IEnumerable<SimpleFloor> Floors { get; set; } = default!;
|
||||
}
|
||||
@@ -4,27 +4,17 @@
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 排行信息
|
||||
/// 排行包装
|
||||
/// </summary>
|
||||
public class RankInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// 造成伤害
|
||||
/// </summary>
|
||||
public int AvatarId { get; set; }
|
||||
public ItemRate<int, double> Damage { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// 受到伤害
|
||||
/// </summary>
|
||||
public int Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 百分比
|
||||
/// </summary>
|
||||
public double Percent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总体百分比
|
||||
/// </summary>
|
||||
public double PercentTotal { get; set; }
|
||||
public ItemRate<int, double> TakeDamage { get; set; } = default!;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 排行包装
|
||||
/// </summary>
|
||||
public class RankInfoWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// 伤害
|
||||
/// </summary>
|
||||
public RankInfo? Damage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 承受伤害
|
||||
/// </summary>
|
||||
public RankInfo? TakeDamage { get; set; }
|
||||
}
|
||||
@@ -2,19 +2,18 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 武器使用数据
|
||||
/// 队伍出场次数
|
||||
/// </summary>
|
||||
public class AvatarWeaponUsage
|
||||
public class TeamAppearance
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// 上半
|
||||
/// </summary>
|
||||
public int Avatar { get; set; }
|
||||
public List<ItemRate<string, int>> Up { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 武器比率
|
||||
/// 下半
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<int>> Weapons { get; set; } = default!;
|
||||
public List<ItemRate<string, int>> Down { get; set; } = default!;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 组队数据
|
||||
/// </summary>
|
||||
public class TeamCollocation
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// </summary>
|
||||
public int Avatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色搭配比率
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<int>> Collocations { get; set; } = default!;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 队伍上场率
|
||||
/// 层间上场率
|
||||
/// </summary>
|
||||
public record TeamCombination
|
||||
{
|
||||
/// <summary>
|
||||
/// 带有层的间
|
||||
/// </summary>
|
||||
public LevelInfo Level { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 队伍
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<Team>> Teams { get; set; } = null!;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 队伍上场率2
|
||||
/// 层上场率
|
||||
/// </summary>
|
||||
public record TeamCombination2
|
||||
{
|
||||
/// <summary>
|
||||
/// 带有层的间
|
||||
/// </summary>
|
||||
public int Floor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 队伍
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<Team>> Teams { get; set; } = null!;
|
||||
}
|
||||
Reference in New Issue
Block a user