[skip ci] [skip ci] uigf 4 support part 2

This commit is contained in:
DismissedLight
2024-07-13 19:19:18 +08:00
parent d866c46646
commit 71e0452c6e
23 changed files with 353 additions and 207 deletions

View File

@@ -10,60 +10,29 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Snap.Hutao.Model.Entity;
/// <summary>
/// 成就
/// </summary>
[HighQuality]
[Table("achievements")]
internal sealed class Achievement : IAppDbEntityHasArchive,
IEquatable<Achievement>,
IDbMappingForeignKeyFrom<Achievement, AchievementId>,
IDbMappingForeignKeyFrom<Achievement, UIAFItem>
{
/// <summary>
/// 内部Id
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid InnerId { get; set; }
/// <summary>
/// 存档 Id
/// </summary>
public Guid ArchiveId { get; set; }
/// <summary>
/// 存档
/// </summary>
[ForeignKey(nameof(ArchiveId))]
public AchievementArchive Archive { get; set; } = default!;
/// <summary>
/// Id
/// </summary>
public uint Id { get; set; }
/// <summary>
/// 当前进度
/// </summary>
public uint Current { get; set; }
/// <summary>
/// 完成时间
/// </summary>
public DateTimeOffset Time { get; set; }
/// <summary>
/// 状态
/// </summary>
public AchievementStatus Status { get; set; }
/// <summary>
/// 创建一个新的成就
/// </summary>
/// <param name="archiveId">对应的用户id</param>
/// <param name="id">成就Id</param>
/// <returns>新创建的成就</returns>
public static Achievement From(in Guid archiveId, in AchievementId id)
{
return new()
@@ -75,12 +44,6 @@ internal sealed class Achievement : IAppDbEntityHasArchive,
};
}
/// <summary>
/// 创建一个新的成就
/// </summary>
/// <param name="userId">对应的用户id</param>
/// <param name="uiaf">uiaf项</param>
/// <returns>新创建的成就</returns>
public static Achievement From(in Guid userId, in UIAFItem uiaf)
{
return new()
@@ -93,32 +56,27 @@ internal sealed class Achievement : IAppDbEntityHasArchive,
};
}
/// <inheritdoc/>
public bool Equals(Achievement? other)
{
if (other is null)
{
return false;
}
else
{
return ArchiveId == other.ArchiveId
&& Id == other.Id
&& Current == other.Current
&& Status == other.Status
&& Time == other.Time;
}
return ArchiveId == other.ArchiveId
&& Id == other.Id
&& Current == other.Current
&& Status == other.Status
&& Time == other.Time;
}
#region Object
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return Equals(obj as Achievement);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(ArchiveId, Id, Current, Status, Time);

View File

@@ -7,28 +7,15 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Snap.Hutao.Model.Entity;
/// <summary>
/// 角色信息表
/// </summary>
[HighQuality]
[Table("avatar_infos")]
internal sealed class AvatarInfo : IMappingFrom<AvatarInfo, string, Web.Enka.Model.AvatarInfo>
{
/// <summary>
/// 内部 Id
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid InnerId { get; set; }
/// <summary>
/// Uid
/// </summary>
public string Uid { get; set; } = default!;
/// <summary>
/// 角色的信息
/// </summary>
public Web.Enka.Model.AvatarInfo Info { get; set; } = default!;
public DateTimeOffset ShowcaseRefreshTime { get; set; }
@@ -37,12 +24,6 @@ internal sealed class AvatarInfo : IMappingFrom<AvatarInfo, string, Web.Enka.Mod
public DateTimeOffset CalculatorRefreshTime { get; set; }
/// <summary>
/// 创建一个新的实体角色信息
/// </summary>
/// <param name="uid">uid</param>
/// <param name="info">角色信息</param>
/// <returns>实体角色信息</returns>
public static AvatarInfo From(string uid, Web.Enka.Model.AvatarInfo info)
{
return new() { Uid = uid, Info = info };

View File

@@ -6,18 +6,13 @@ using Snap.Hutao.Core.Json;
namespace Snap.Hutao.Model.Entity.Configuration;
/// <summary>
/// Json文本转换器
/// </summary>
/// <typeparam name="TProperty">实体类型</typeparam>
[HighQuality]
internal sealed class JsonTextValueConverter<TProperty> : ValueConverter<TProperty, string>
internal sealed class JsonTextValueConverter<TPropertyType> : ValueConverter<TPropertyType, string>
{
[SuppressMessage("", "SH007")]
public JsonTextValueConverter()
: base(
obj => JsonSerializer.Serialize(obj, JsonOptions.Default),
str => JsonSerializer.Deserialize<TProperty>(str, JsonOptions.Default)!)
str => JsonSerializer.Deserialize<TPropertyType>(str, JsonOptions.Default)!)
{
}
}

View File

@@ -8,51 +8,25 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Snap.Hutao.Model.Entity;
/// <summary>
/// 养成入口
/// </summary>
[HighQuality]
[Table("cultivate_entries")]
internal sealed class CultivateEntry : IAppDbEntity,
IDbMappingForeignKeyFrom<CultivateEntry, CultivateType, uint>
{
/// <summary>
/// 内部Id
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid InnerId { get; set; }
/// <summary>
/// 项目Id
/// </summary>
public Guid ProjectId { get; set; }
/// <summary>
/// 项目
/// </summary>
[ForeignKey(nameof(ProjectId))]
public CultivateProject Project { get; set; } = default!;
public CultivateEntryLevelInformation? LevelInformation { get; set; }
/// <summary>
/// 养成类型
/// </summary>
public CultivateType Type { get; set; }
/// <summary>
/// 角色/武器/家具 Id
/// </summary>
public uint Id { get; set; }
/// <summary>
/// 创建一个新的养成入口点
/// </summary>
/// <param name="projectId">项目Id</param>
/// <param name="type">类型</param>
/// <param name="id">主Id</param>
/// <returns>养成入口点</returns>
public static CultivateEntry From(in Guid projectId, in CultivateType type, in uint id)
{
return new()
@@ -62,10 +36,4 @@ internal sealed class CultivateEntry : IAppDbEntity,
Id = id,
};
}
public static CultivateEntry Join(CultivateEntry entry, CultivateEntryLevelInformation levelInformation)
{
entry.LevelInformation = levelInformation;
return entry;
}
}

View File

@@ -7,52 +7,24 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Snap.Hutao.Model.Entity;
/// <summary>
/// 消耗物品
/// </summary>
[HighQuality]
[Table("cultivate_items")]
internal sealed class CultivateItem : IDbMappingForeignKeyFrom<CultivateItem, Web.Hoyolab.Takumi.Event.Calculate.Item>
{
/// <summary>
/// 内部Id
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid InnerId { get; set; }
/// <summary>
/// 外键
/// </summary>
public Guid EntryId { get; set; }
/// <summary>
/// 入口名称
/// </summary>
[ForeignKey(nameof(EntryId))]
public CultivateEntry Entry { get; set; } = default!;
/// <summary>
/// 物品 Id
/// </summary>
public uint ItemId { get; set; }
/// <summary>
/// 物品个数
/// </summary>
public uint Count { get; set; }
/// <summary>
/// 是否完成此项
/// </summary>
public bool IsFinished { get; set; }
/// <summary>
/// 创建一个新的养成物品
/// </summary>
/// <param name="entryId">入口点 Id</param>
/// <param name="item">物品</param>
/// <returns>养成物品</returns>
public static CultivateItem From(in Guid entryId, in Web.Hoyolab.Takumi.Event.Calculate.Item item)
{
return new()

View File

@@ -9,45 +9,21 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Snap.Hutao.Model.Entity;
/// <summary>
/// 培养计划
/// </summary>
[HighQuality]
[Table("cultivate_projects")]
internal sealed partial class CultivateProject : ISelectable,
IAdvancedCollectionViewItem,
IMappingFrom<CultivateProject, string, string>
IMappingFrom<CultivateProject, string>
{
/// <summary>
/// 内部Id
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid InnerId { get; set; }
/// <summary>
/// 是否选中
/// </summary>
public bool IsSelected { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; } = default!;
/// <summary>
/// 所属的Uid
/// </summary>
public string? AttachedUid { get; set; }
/// <summary>
/// 创建新的养成计划
/// </summary>
/// <param name="name">名称</param>
/// <param name="attachedUid">绑定的Uid</param>
/// <returns>新的养成计划</returns>
public static CultivateProject From(string name, string? attachedUid = null)
public static CultivateProject From(string name)
{
return new() { Name = name, AttachedUid = attachedUid };
return new() { Name = name };
}
}

View File

@@ -6,4 +6,12 @@ namespace Snap.Hutao.Model.InterChange;
internal sealed class HutaoReserved
{
public required uint Version { get; set; }
public List<HutaoReservedEntry<HutaoReservedAchievement>>? Achievement { get; set; }
public List<HutaoReservedEntry<Web.Enka.Model.AvatarInfo>>? AvatarInfo { get; set; }
public List<HutaoReservedEntry<HutaoReservedCultivationEntry>>? Cultivation { get; set; }
public List<HutaoReservedEntry<HutaoReservedSpiralAbyssEntry>>? SpiralAbyss { get; set; }
}

View File

@@ -0,0 +1,29 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.Abstraction;
using Snap.Hutao.Model.Intrinsic;
namespace Snap.Hutao.Model.InterChange;
internal sealed class HutaoReservedAchievement : IMappingFrom<HutaoReservedAchievement, Model.Entity.Achievement>
{
public required uint Id { get; set; }
public required uint Current { get; set; }
public required DateTimeOffset Time { get; set; }
public required AchievementStatus Status { get; set; }
public static HutaoReservedAchievement From(Entity.Achievement source)
{
return new()
{
Id = source.Id,
Current = source.Current,
Time = source.Time,
Status = source.Status,
};
}
}

View File

@@ -0,0 +1,45 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Entity.Primitive;
namespace Snap.Hutao.Model.InterChange;
internal sealed class HutaoReservedCultivationEntry
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint AvatarLevelFrom { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint AvatarLevelTo { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint SkillALevelFrom { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint SkillALevelTo { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint SkillELevelFrom { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint SkillELevelTo { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint SkillQLevelFrom { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint SkillQLevelTo { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint WeaponLevelFrom { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint WeaponLevelTo { get; set; }
public required CultivateType Type { get; set; }
public required uint Id { get; set; }
public required List<HutaoReservedCultivationItem> Items { get; set; }
}

View File

@@ -0,0 +1,26 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.Abstraction;
using Snap.Hutao.Model.Entity;
namespace Snap.Hutao.Model.InterChange;
internal sealed class HutaoReservedCultivationItem : IMappingFrom<HutaoReservedCultivationItem, CultivateItem>
{
public required uint ItemId { get; set; }
public required uint Count { get; set; }
public required bool IsFinished { get; set; }
public static HutaoReservedCultivationItem From(CultivateItem item)
{
return new()
{
ItemId = item.ItemId,
Count = item.Count,
IsFinished = item.IsFinished,
};
}
}

View File

@@ -0,0 +1,11 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Model.InterChange;
internal sealed class HutaoReservedEntry<TItem>
{
public required string Identity { get; set; }
public required List<TItem> List { get; set; }
}

View File

@@ -0,0 +1,11 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Model.InterChange;
internal sealed class HutaoReservedSpiralAbyssEntry
{
public required uint ScheduleId { get; set; }
public required Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss SpiralAbyss { get; set; }
}

View File

@@ -78,4 +78,9 @@ internal sealed partial class AchievementDbService : IAchievementDbService
{
return this.List<AchievementArchive>();
}
public AchievementArchive? GetAchievementArchiveById(Guid archiveId)
{
return this.SingleOrDefault<AchievementArchive>(a => a.InnerId == archiveId);
}
}

View File

@@ -5,14 +5,19 @@ using Snap.Hutao.Model.Primitive;
using Snap.Hutao.Service.Abstraction;
using System.Collections.ObjectModel;
using EntityAchievement = Snap.Hutao.Model.Entity.Achievement;
using EntityArchive = Snap.Hutao.Model.Entity.AchievementArchive;
namespace Snap.Hutao.Service.Achievement;
internal interface IAchievementDbService : IAppDbService<Model.Entity.AchievementArchive>, IAppDbService<EntityAchievement>
internal interface IAchievementDbService : IAppDbService<EntityArchive>, IAppDbService<EntityAchievement>
{
ObservableCollection<Model.Entity.AchievementArchive> GetAchievementArchiveCollection();
ObservableCollection<EntityArchive> GetAchievementArchiveCollection();
List<Model.Entity.AchievementArchive> GetAchievementArchiveList();
List<EntityArchive> GetAchievementArchiveList();
EntityArchive? GetAchievementArchiveById(Guid archiveId);
void RemoveAchievementArchive(EntityArchive archive);
List<EntityAchievement> GetAchievementListByArchiveId(Guid archiveId);
@@ -23,6 +28,4 @@ internal interface IAchievementDbService : IAppDbService<Model.Entity.Achievemen
List<EntityAchievement> GetLatestFinishedAchievementListByArchiveId(Guid archiveId, int take);
void OverwriteAchievement(EntityAchievement achievement);
void RemoveAchievementArchive(Model.Entity.AchievementArchive archive);
}

View File

@@ -85,4 +85,9 @@ internal sealed partial class CultivationDbService : ICultivationDbService
{
this.Add(levelInformation);
}
public CultivateProject? GetCultivateProjectById(Guid projectId)
{
return this.SingleOrDefault<CultivateProject>(p => p.InnerId == projectId);
}
}

View File

@@ -28,6 +28,8 @@ internal interface ICultivationDbService : IAppDbService<CultivateEntryLevelInfo
ObservableCollection<CultivateProject> GetCultivateProjectCollection();
CultivateProject? GetCultivateProjectById(Guid projectId);
void AddCultivateEntry(CultivateEntry entry);
void AddCultivateItemRange(IEnumerable<CultivateItem> toAdd);

View File

@@ -10,7 +10,7 @@ internal interface ISpiralAbyssRecordDbService : IAppDbService<SpiralAbyssEntry>
{
void AddSpiralAbyssEntry(SpiralAbyssEntry entry);
Dictionary<uint, SpiralAbyssEntry> GetSpiralAbyssEntryListByUid(string uid);
Dictionary<uint, SpiralAbyssEntry> GetSpiralAbyssEntryMapByUid(string uid);
void UpdateSpiralAbyssEntry(SpiralAbyssEntry entry);
}

View File

@@ -14,7 +14,7 @@ internal sealed partial class SpiralAbyssRecordDbService : ISpiralAbyssRecordDbS
public IServiceProvider ServiceProvider { get => serviceProvider; }
public Dictionary<uint, SpiralAbyssEntry> GetSpiralAbyssEntryListByUid(string uid)
public Dictionary<uint, SpiralAbyssEntry> GetSpiralAbyssEntryMapByUid(string uid)
{
return this.Query(query => query
.Where(s => s.Uid == uid)

View File

@@ -34,6 +34,7 @@ internal sealed partial class SpiralAbyssRecordService : ISpiralAbyssRecordServi
{
if (await metadataService.InitializeAsync().ConfigureAwait(false))
{
// TODO replace to IMetadataContext
metadataContext = new()
{
IdScheduleMap = await metadataService.GetIdToTowerScheduleMapAsync().ConfigureAwait(false),
@@ -60,7 +61,7 @@ internal sealed partial class SpiralAbyssRecordService : ISpiralAbyssRecordServi
if (spiralAbysses is null)
{
await taskContext.SwitchToBackgroundAsync();
Dictionary<uint, SpiralAbyssEntry> entryMap = spiralAbyssRecordDbService.GetSpiralAbyssEntryListByUid(userAndUid.Uid.Value);
Dictionary<uint, SpiralAbyssEntry> entryMap = spiralAbyssRecordDbService.GetSpiralAbyssEntryMapByUid(userAndUid.Uid.Value);
ArgumentNullException.ThrowIfNull(metadataContext);
spiralAbysses = metadataContext.IdScheduleMap.Values

View File

@@ -4,8 +4,13 @@
using Snap.Hutao.Core;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.InterChange;
using Snap.Hutao.Service.Achievement;
using Snap.Hutao.Service.AvatarInfo;
using Snap.Hutao.Service.Cultivation;
using Snap.Hutao.Service.GachaLog;
using Snap.Hutao.Service.SpiralAbyss;
using System.IO;
using System.Runtime.InteropServices;
namespace Snap.Hutao.Service.UIGF;
@@ -13,8 +18,8 @@ namespace Snap.Hutao.Service.UIGF;
[Injection(InjectAs.Transient, typeof(IUIGFExportService), Key = UIGFVersion.UIGF40)]
internal sealed partial class UIGF40ExportService : IUIGFExportService
{
private readonly IGachaLogDbService gachaLogDbService;
private readonly JsonSerializerOptions jsonOptions;
private readonly IServiceProvider serviceProvider;
private readonly RuntimeOptions runtimeOptions;
private readonly ITaskContext taskContext;
@@ -38,6 +43,10 @@ internal sealed partial class UIGF40ExportService : IUIGFExportService
};
ExportGachaArchives(uigf, exportOptions.GachaArchiveIds);
ExportAchievementArchives(uigf.HutaoReserved, exportOptions.ReservedAchievementArchiveIds);
ExportAvatarInfoUids(uigf.HutaoReserved, exportOptions.ReservedAvatarInfoUids);
ExportCultivationProjects(uigf.HutaoReserved, exportOptions.ReservedCultivationProjectIds);
ExportSpialAbysses(uigf.HutaoReserved, exportOptions.ReservedSpiralAbyssUids);
using (FileStream stream = File.Create(exportOptions.FilePath))
{
@@ -49,7 +58,14 @@ internal sealed partial class UIGF40ExportService : IUIGFExportService
private void ExportGachaArchives(Model.InterChange.UIGF uigf, List<Guid> archiveIds)
{
List<UIGFEntry<Hk4eItem>> hk4eEntries = [];
if (archiveIds.Count <= 0)
{
return;
}
IGachaLogDbService gachaLogDbService = serviceProvider.GetRequiredService<IGachaLogDbService>();
List<UIGFEntry<Hk4eItem>> results = [];
foreach (Guid archiveId in archiveIds)
{
GachaArchive? archive = gachaLogDbService.GetGachaArchiveById(archiveId);
@@ -59,12 +75,163 @@ internal sealed partial class UIGF40ExportService : IUIGFExportService
{
Uid = archive.Uid,
TimeZone = 0,
List = [.. dbItems.Select(Hk4eItem.From)],
List = dbItems.SelectList(Hk4eItem.From),
};
hk4eEntries.Add(entry);
results.Add(entry);
}
uigf.Hk4e = hk4eEntries;
uigf.Hk4e = results;
}
private void ExportAchievementArchives(HutaoReserved hutaoReserved, List<Guid> archiveIds)
{
if (archiveIds.Count <= 0)
{
return;
}
IAchievementDbService achievementDbService = serviceProvider.GetRequiredService<IAchievementDbService>();
List<HutaoReservedEntry<HutaoReservedAchievement>> results = [];
foreach (Guid archiveId in archiveIds)
{
AchievementArchive? archive = achievementDbService.GetAchievementArchiveById(archiveId);
ArgumentNullException.ThrowIfNull(archive);
List<Model.Entity.Achievement> dbItems = achievementDbService.GetAchievementListByArchiveId(archiveId);
HutaoReservedEntry<HutaoReservedAchievement> entry = new()
{
Identity = archive.Name,
List = dbItems.SelectList(HutaoReservedAchievement.From),
};
results.Add(entry);
}
hutaoReserved.Achievement = results;
}
private void ExportAvatarInfoUids(HutaoReserved hutaoReserved, List<string> uids)
{
if (uids.Count <= 0)
{
return;
}
IAvatarInfoDbService avatarInfoDbService = serviceProvider.GetRequiredService<IAvatarInfoDbService>();
List<HutaoReservedEntry<Web.Enka.Model.AvatarInfo>> results = [];
foreach (string uid in uids)
{
List<Model.Entity.AvatarInfo>? dbItems = avatarInfoDbService.GetAvatarInfoListByUid(uid);
HutaoReservedEntry<Web.Enka.Model.AvatarInfo> entry = new()
{
Identity = uid,
List = dbItems.SelectList(item => item.Info),
};
results.Add(entry);
}
hutaoReserved.AvatarInfo = results;
}
private void ExportCultivationProjects(HutaoReserved hutaoReserved, List<Guid> projectIds)
{
if (projectIds.Count <= 0)
{
return;
}
ICultivationDbService cultivationDbService = serviceProvider.GetRequiredService<ICultivationDbService>();
List<HutaoReservedEntry<HutaoReservedCultivationEntry>> results = [];
foreach (Guid projectId in projectIds)
{
CultivateProject? project = cultivationDbService.GetCultivateProjectById(projectId);
ArgumentNullException.ThrowIfNull(project);
List<CultivateEntry> entries = cultivationDbService.GetCultivateEntryListIncludingLevelInformationByProjectId(projectId);
List<HutaoReservedCultivationEntry> innerResults = [];
foreach (ref readonly CultivateEntry innerEntry in CollectionsMarshal.AsSpan(entries))
{
List<CultivateItem> items = cultivationDbService.GetCultivateItemListByEntryId(innerEntry.InnerId);
HutaoReservedCultivationEntry innerResultEntry = new()
{
AvatarLevelFrom = innerEntry.LevelInformation?.AvatarLevelFrom ?? 0,
AvatarLevelTo = innerEntry.LevelInformation?.AvatarLevelTo ?? 0,
SkillALevelFrom = innerEntry.LevelInformation?.SkillALevelFrom ?? 0,
SkillALevelTo = innerEntry.LevelInformation?.SkillALevelTo ?? 0,
SkillELevelFrom = innerEntry.LevelInformation?.SkillELevelFrom ?? 0,
SkillELevelTo = innerEntry.LevelInformation?.SkillELevelTo ?? 0,
SkillQLevelFrom = innerEntry.LevelInformation?.SkillQLevelFrom ?? 0,
SkillQLevelTo = innerEntry.LevelInformation?.SkillQLevelTo ?? 0,
WeaponLevelFrom = innerEntry.LevelInformation?.WeaponLevelFrom ?? 0,
WeaponLevelTo = innerEntry.LevelInformation?.WeaponLevelTo ?? 0,
Type = innerEntry.Type,
Id = innerEntry.Id,
Items = items.SelectList(HutaoReservedCultivationItem.From),
};
innerResults.Add(innerResultEntry);
}
HutaoReservedEntry<HutaoReservedCultivationEntry> outerEntry = new()
{
Identity = project.Name,
List = innerResults,
};
results.Add(outerEntry);
}
hutaoReserved.Cultivation = results;
}
private void ExportSpialAbysses(HutaoReserved hutaoReserved, List<string> uids)
{
if (uids.Count <= 0)
{
return;
}
ISpiralAbyssRecordDbService spiralAbyssRecordDbService = serviceProvider.GetRequiredService<ISpiralAbyssRecordDbService>();
List<HutaoReservedEntry<HutaoReservedSpiralAbyssEntry>> results = [];
foreach (string uid in uids)
{
Dictionary<uint, SpiralAbyssEntry> dbMap = spiralAbyssRecordDbService.GetSpiralAbyssEntryMapByUid(uid);
HutaoReservedEntry<HutaoReservedSpiralAbyssEntry> entry = new()
{
Identity = uid,
List = dbMap.Select(item => new HutaoReservedSpiralAbyssEntry
{
ScheduleId = item.Key,
SpiralAbyss = item.Value.SpiralAbyss,
}).ToList(),
};
results.Add(entry);
}
hutaoReserved.SpiralAbyss = results;
}
}
[ConstructorGenerated]
[Injection(InjectAs.Transient, typeof(IUIGFImportService), Key = UIGFVersion.UIGF40)]
internal sealed partial class UIGF40ImportService : IUIGFImportService
{
public async ValueTask<bool> ImportAsync(UIGFImportOptions importOptions, CancellationToken token)
{
await Task.CompletedTask;
return true;
}
}
internal interface IUIGFImportService
{
}

View File

@@ -5,17 +5,24 @@ namespace Snap.Hutao.Service.UIGF;
internal sealed class UIGFExportOptions
{
public string FilePath { get; set; } = default!;
public required string FilePath { get; set; }
public List<Guid> GachaArchiveIds { get; set; } = [];
public required List<Guid> GachaArchiveIds { get; set; }
public List<Guid> ReservedAchievementArchiveIds { get; set; } = [];
public required List<Guid> ReservedAchievementArchiveIds { get; set; }
public List<string> ReservedAvatarInfoUids { get; set; } = [];
public required List<string> ReservedAvatarInfoUids { get; set; }
public List<Guid> ReservedCultivationProjectIds { get; set; } = [];
public required List<Guid> ReservedCultivationProjectIds { get; set; }
public List<string> ReservedSpiralAbyssUids { get; set; } = [];
public required List<string> ReservedSpiralAbyssUids { get; set; }
}
public List<Guid> ReservedUserIds { get; set; } = [];
internal sealed class UIGFImportOptions
{
public Model.InterChange.UIGF UIGF { get; set; } = default!;
public HashSet<string> GachaArchiveUids { get; set; } = default!;
public HashSet<string> ReservedAchievementArchiveIdentities { get; set; } = default!;
}

View File

@@ -17,10 +17,5 @@
VerticalAlignment="Top"
PlaceholderText="{shuxm:ResourceString Name=ViewDialogCultivateProjectInputPlaceholder}"
Text="{x:Bind Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<CheckBox
Margin="0,8,0,0"
Content="{shuxm:ResourceString Name=ViewDialogCultivateProjectAttachUid}"
IsChecked="{x:Bind IsUidAttached, Mode=TwoWay}"
Visibility="Collapsed"/>
</StackPanel>
</ContentDialog>

View File

@@ -7,44 +7,25 @@ using Snap.Hutao.Service.User;
namespace Snap.Hutao.UI.Xaml.View.Dialog;
/// <summary>
/// 养成计划对话框
/// </summary>
[HighQuality]
[DependencyProperty("Text", typeof(string))]
[DependencyProperty("IsUidAttached", typeof(bool))]
internal sealed partial class CultivateProjectDialog : ContentDialog
{
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
/// <summary>
/// 构造一个新的养成计划对话框
/// </summary>
/// <param name="serviceProvider">服务提供器</param>
public CultivateProjectDialog(IServiceProvider serviceProvider)
{
InitializeComponent();
this.serviceProvider = serviceProvider;
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
}
/// <summary>
/// 创建一个新的,用户指定的计划
/// </summary>
/// <returns>计划</returns>
public async ValueTask<ValueResult<bool, CultivateProject>> CreateProjectAsync()
{
await taskContext.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
if (result == ContentDialogResult.Primary)
if (await ShowAsync() is ContentDialogResult.Primary)
{
string? uid = IsUidAttached
? await serviceProvider.GetRequiredService<IUserService>().GetCurrentUidAsync().ConfigureAwait(false)
: null;
return new(true, CultivateProject.From(Text, uid));
return new(true, CultivateProject.From(Text));
}
return new(false, default!);