From de9abcfad44a84a76fcd7b7dc220761a80bf116a Mon Sep 17 00:00:00 2001
From: Lightczx <1686188646@qq.com>
Date: Thu, 27 Jul 2023 22:26:19 +0800
Subject: [PATCH] refactor gacha service 2
---
.../Extension/EnumerableExtension.List.cs | 4 +-
.../Snap.Hutao/Extension/SpanExtension.cs | 8 +-
.../Service/DailyNote/DailyNoteDbService.cs | 10 --
.../Factory/GachaStatisticsFactory.cs | 13 +-
.../Factory/GachaStatisticsSlimFactory.cs | 52 ++++----
.../GachaLog/Factory/HistoryWishBuilder.cs | 2 +-
.../Factory/IGachaStatisticsFactory.cs | 2 +-
.../Factory/IGachaStatisticsSlimFactory.cs | 2 +-
.../Factory/TypedWishSummaryBuilder.cs | 9 +-
.../GachaArchiveInitializationContext.cs | 1 +
.../Service/GachaLog/GachaArchives.cs | 39 ------
.../Snap.Hutao/Service/GachaLog/GachaLog.cs | 2 +-
.../Service/GachaLog/GachaLogFetchContext.cs | 8 +-
.../Service/GachaLog/GachaLogService.cs | 115 ++++++++++++------
...t.cs => GachaLogServiceMetadataContext.cs} | 10 +-
.../Service/GachaLog/IGachaLogService.cs | 9 +-
.../Service/GachaLog/IUIGFExportService.cs | 2 +-
.../Service/GachaLog/IUIGFImportService.cs | 2 +-
.../Service/GachaLog/UIGFExportService.cs | 2 +-
.../Service/GachaLog/UIGFImportService.cs | 2 +-
.../GachaLog/GachaLogViewModelSlim.cs | 2 +-
21 files changed, 145 insertions(+), 151 deletions(-)
delete mode 100644 src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaArchives.cs
rename src/Snap.Hutao/Snap.Hutao/Service/GachaLog/{GachaLogServiceContext.cs => GachaLogServiceMetadataContext.cs} (92%)
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.List.cs b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.List.cs
index 0fe984fe..26b97745 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.List.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.List.cs
@@ -12,7 +12,7 @@ namespace Snap.Hutao.Extension;
internal static partial class EnumerableExtension
{
///
- public static double SpanAverage(this List source)
+ public static double Average(this List source)
{
Span span = CollectionsMarshal.AsSpan(source);
if (span.IsEmpty)
@@ -21,7 +21,7 @@ internal static partial class EnumerableExtension
}
long sum = 0;
- foreach (int item in span)
+ foreach (ref readonly int item in span)
{
sum += item;
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/SpanExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/SpanExtension.cs
index 18db77a0..dee1a93c 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/SpanExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/SpanExtension.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using System.Numerics;
+using System.Runtime.InteropServices;
namespace Snap.Hutao.Extension;
@@ -59,7 +60,7 @@ internal static class SpanExtension
/// 平均值
public static byte Average(this in ReadOnlySpan span)
{
- if (span.Length == 0)
+ if (span.IsEmpty)
{
return 0;
}
@@ -74,4 +75,9 @@ internal static class SpanExtension
return unchecked((byte)(sum / count));
}
+
+ public static Span AsSpan(this List list)
+ {
+ return CollectionsMarshal.AsSpan(list);
+ }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteDbService.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteDbService.cs
index 68fa3d22..5829e0bb 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteDbService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteDbService.cs
@@ -1,20 +1,10 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using CommunityToolkit.Mvvm.Messaging;
using Microsoft.EntityFrameworkCore;
using Snap.Hutao.Core.Database;
-using Snap.Hutao.Core.DependencyInjection.Abstraction;
-using Snap.Hutao.Message;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Database;
-using Snap.Hutao.Service.Notification;
-using Snap.Hutao.Service.User;
-using Snap.Hutao.ViewModel.User;
-using Snap.Hutao.Web.Hoyolab;
-using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
-using System.Collections.ObjectModel;
-using WebDailyNote = Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote.DailyNote;
namespace Snap.Hutao.Service.DailyNote;
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs
index 064080db..162c0f76 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs
@@ -9,6 +9,7 @@ using Snap.Hutao.Model.Metadata.Avatar;
using Snap.Hutao.Model.Metadata.Weapon;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.ViewModel.GachaLog;
+using System.Runtime.InteropServices;
namespace Snap.Hutao.Service.GachaLog.Factory;
@@ -26,7 +27,7 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
private readonly AppOptions options;
///
- public async ValueTask CreateAsync(IOrderedQueryable items, GachaLogServiceContext context)
+ public async ValueTask CreateAsync(List items, GachaLogServiceMetadataContext context)
{
await taskContext.SwitchToBackgroundAsync();
List gachaEvents = await metadataService.GetGachaEventsAsync().ConfigureAwait(false);
@@ -37,9 +38,9 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
private static GachaStatistics CreateCore(
IServiceProvider serviceProvider,
- IOrderedQueryable items,
+ List items,
List historyWishBuilders,
- in GachaLogServiceContext context,
+ in GachaLogServiceMetadataContext context,
bool isEmptyHistoryWishVisible)
{
TypedWishSummaryBuilder standardWishBuilder = new(
@@ -65,9 +66,9 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
Dictionary purpleWeaponCounter = new();
Dictionary blueWeaponCounter = new();
- // Items are ordered by precise time
- // first is oldest
- foreach (GachaItem item in items)
+ // Items are ordered by precise time, first is oldest
+ // 'ref' is not allowed here because we have lambda below
+ foreach (GachaItem item in CollectionsMarshal.AsSpan(items))
{
// Find target history wish to operate.
HistoryWishBuilder? targetHistoryWishBuilder = historyWishBuilders
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsSlimFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsSlimFactory.cs
index b87fd8e7..aa6b2f00 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsSlimFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsSlimFactory.cs
@@ -6,6 +6,7 @@ using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Model.Metadata.Abstraction;
using Snap.Hutao.ViewModel.GachaLog;
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
+using System.Runtime.InteropServices;
namespace Snap.Hutao.Service.GachaLog.Factory;
@@ -19,10 +20,36 @@ internal sealed partial class GachaStatisticsSlimFactory : IGachaStatisticsSlimF
private readonly ITaskContext taskContext;
///
- public async ValueTask CreateAsync(IOrderedQueryable items, GachaLogServiceContext context)
+ public async ValueTask CreateAsync(List items, GachaLogServiceMetadataContext context)
{
await taskContext.SwitchToBackgroundAsync();
+ return CreateCore(items, context);
+ }
+
+ private static void Track(INameQuality nameQuality, ref int orangeTracker, ref int purpleTracker)
+ {
+ switch (nameQuality.Quality)
+ {
+ case QualityType.QUALITY_ORANGE:
+ orangeTracker = 0;
+ ++purpleTracker;
+ break;
+ case QualityType.QUALITY_PURPLE:
+ ++orangeTracker;
+ purpleTracker = 0;
+ break;
+ case QualityType.QUALITY_BLUE:
+ ++orangeTracker;
+ ++purpleTracker;
+ break;
+ default:
+ break;
+ }
+ }
+
+ private GachaStatisticsSlim CreateCore(List items, GachaLogServiceMetadataContext context)
+ {
int standardOrangeTracker = 0;
int standardPurpleTracker = 0;
TypedWishSummarySlim standardWish = new(SH.ServiceGachaLogFactoryPermanentWishName, 90, 10);
@@ -36,7 +63,7 @@ internal sealed partial class GachaStatisticsSlimFactory : IGachaStatisticsSlimF
TypedWishSummarySlim weaponWish = new(SH.ServiceGachaLogFactoryWeaponWishName, 80, 10);
// O(n) operation
- foreach (GachaItem item in items)
+ foreach (ref readonly GachaItem item in CollectionsMarshal.AsSpan(items))
{
INameQuality nameQuality = context.GetNameQualityByItemId(item.ItemId);
switch (item.QueryType)
@@ -70,25 +97,4 @@ internal sealed partial class GachaStatisticsSlimFactory : IGachaStatisticsSlimF
StandardWish = standardWish,
};
}
-
- private static void Track(INameQuality nameQuality, ref int orangeTracker, ref int purpleTracker)
- {
- switch (nameQuality.Quality)
- {
- case QualityType.QUALITY_ORANGE:
- orangeTracker = 0;
- ++purpleTracker;
- break;
- case QualityType.QUALITY_PURPLE:
- ++orangeTracker;
- purpleTracker = 0;
- break;
- case QualityType.QUALITY_BLUE:
- ++orangeTracker;
- ++purpleTracker;
- break;
- default:
- break;
- }
- }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HistoryWishBuilder.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HistoryWishBuilder.cs
index 7585cd7c..6feac754 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HistoryWishBuilder.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HistoryWishBuilder.cs
@@ -30,7 +30,7 @@ internal sealed class HistoryWishBuilder
/// 卡池配置
/// 祈愿记录上下文
[SuppressMessage("", "SH002")]
- public HistoryWishBuilder(GachaEvent gachaEvent, GachaLogServiceContext context)
+ public HistoryWishBuilder(GachaEvent gachaEvent, GachaLogServiceMetadataContext context)
{
this.gachaEvent = gachaEvent;
ConfigType = gachaEvent.Type;
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsFactory.cs
index 1f1c7dbb..13997252 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsFactory.cs
@@ -18,5 +18,5 @@ internal interface IGachaStatisticsFactory
/// 物品列表
/// 祈愿记录上下文
/// 祈愿统计对象
- ValueTask CreateAsync(IOrderedQueryable items, GachaLogServiceContext context);
+ ValueTask CreateAsync(List items, GachaLogServiceMetadataContext context);
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsSlimFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsSlimFactory.cs
index 7ffad2be..68c02bc6 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsSlimFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsSlimFactory.cs
@@ -17,5 +17,5 @@ internal interface IGachaStatisticsSlimFactory
/// 排序的物品
/// 祈愿记录服务上下文
/// 简化的祈愿统计
- ValueTask CreateAsync(IOrderedQueryable items, GachaLogServiceContext context);
+ ValueTask CreateAsync(List items, GachaLogServiceMetadataContext context);
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/TypedWishSummaryBuilder.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/TypedWishSummaryBuilder.cs
index d028e159..6163ae3c 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/TypedWishSummaryBuilder.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/TypedWishSummaryBuilder.cs
@@ -127,10 +127,6 @@ internal sealed class TypedWishSummaryBuilder
}
}
- ///
- /// 转换到类型化祈愿统计信息
- ///
- /// 类型化祈愿统计信息
public TypedWishSummary ToTypedWishSummary(AsyncBarrier barrier)
{
summaryItems.CompleteAdding(guaranteeOrangeThreshold);
@@ -157,12 +153,11 @@ internal sealed class TypedWishSummaryBuilder
TotalOrangePercent = totalOrangePullTracker / totalCount,
TotalPurplePercent = totalPurplePullTracker / totalCount,
TotalBluePercent = totalBluePullTracker / totalCount,
- AverageOrangePull = averageOrangePullTracker.SpanAverage(),
- AverageUpOrangePull = averageUpOrangePullTracker.SpanAverage(),
+ AverageOrangePull = averageOrangePullTracker.Average(),
+ AverageUpOrangePull = averageUpOrangePullTracker.Average(),
OrangeList = summaryItems,
};
- // TODO: barrier all predictions.
new PullPrediction(serviceProvider, summary, distributionType).PredictAsync(barrier).SafeForget();
return summary;
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaArchiveInitializationContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaArchiveInitializationContext.cs
index 5d132896..8969b2b7 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaArchiveInitializationContext.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaArchiveInitializationContext.cs
@@ -15,6 +15,7 @@ internal readonly struct GachaArchiveInitializationContext
///
/// 任务上下文
///
+ [Obsolete]
public readonly ITaskContext TaskContext;
///
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaArchives.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaArchives.cs
deleted file mode 100644
index 930418b4..00000000
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaArchives.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.Data.Sqlite;
-using Microsoft.EntityFrameworkCore;
-using Snap.Hutao.Core.ExceptionService;
-using Snap.Hutao.Model.Entity;
-using Snap.Hutao.Model.Entity.Database;
-using System.Collections.ObjectModel;
-
-namespace Snap.Hutao.Service.GachaLog;
-
-///
-/// 存档操作
-///
-internal static class GachaArchives
-{
- ///
- /// 初始化存档集合
- ///
- /// 服务提供器
- /// 集合
- public static void Initialize(IServiceProvider serviceProvider, out ObservableCollection collection)
- {
- try
- {
- using (IServiceScope scope = serviceProvider.CreateScope())
- {
- AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
- collection = appDbContext.GachaArchives.AsNoTracking().ToObservableCollection();
- }
- }
- catch (SqliteException ex)
- {
- string message = string.Format(SH.ServiceGachaLogArchiveCollectionUserdataCorruptedMessage, ex.Message);
- throw ThrowHelper.UserdataCorrupted(message, ex);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLog.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLog.cs
index 96b5ebf8..7ace4b6a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLog.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLog.cs
@@ -20,5 +20,5 @@ internal static class GachaLog
GachaConfigType.StandardWish,
GachaConfigType.AvatarEventWish,
GachaConfigType.WeaponEventWish,
- }.ToImmutableList();
+ }.ToImmutableList(); // TODO: FrozenSet
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogFetchContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogFetchContext.cs
index d2efc450..ef859c25 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogFetchContext.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogFetchContext.cs
@@ -49,7 +49,7 @@ internal struct GachaLogFetchContext
public GachaConfigType CurrentType;
private readonly IServiceProvider serviceProvider;
- private readonly GachaLogServiceContext serviceContext;
+ private readonly GachaLogServiceMetadataContext serviceContext;
private readonly bool isLazy;
///
@@ -58,7 +58,7 @@ internal struct GachaLogFetchContext
/// 服务提供器
/// 祈愿服务上下文
/// 是否为懒惰模式
- public GachaLogFetchContext(IServiceProvider serviceProvider, in GachaLogServiceContext serviceContext, bool isLazy)
+ public GachaLogFetchContext(IServiceProvider serviceProvider, in GachaLogServiceMetadataContext serviceContext, bool isLazy)
{
this.serviceProvider = serviceProvider;
this.serviceContext = serviceContext;
@@ -99,8 +99,8 @@ internal struct GachaLogFetchContext
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
ITaskContext taskContext = scope.ServiceProvider.GetRequiredService();
- GachaArchiveInitializationContext initContext = new(taskContext, item.Uid, appDbContext.GachaArchives, serviceContext.ArchiveCollection);
- GachaArchive.SkipOrInit(initContext, ref TargetArchive);
+ GachaArchiveInitializationContext context = new(taskContext, item.Uid, appDbContext.GachaArchives, serviceContext.ArchiveCollection);
+ GachaArchive.SkipOrInit(context, ref TargetArchive);
DbEndId ??= TargetArchive.GetEndId(CurrentType, appDbContext.GachaItems);
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs
index 48e94181..1e873aed 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs
@@ -1,8 +1,11 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
using Snap.Hutao.Core.Database;
using Snap.Hutao.Core.Diagnostics;
+using Snap.Hutao.Core.ExceptionService;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Database;
using Snap.Hutao.Model.InterChange.GachaLog;
@@ -34,9 +37,11 @@ internal sealed partial class GachaLogService : IGachaLogService
private readonly IMetadataService metadataService;
private readonly ILogger logger;
private readonly GachaInfoClient gachaInfoClient;
+ private readonly IGachaLogDbService gachaLogDbService;
private readonly ITaskContext taskContext;
- private GachaLogServiceContext context;
+ private GachaLogServiceMetadataContext context;
+ private ObservableCollection? archiveCollection;
///
public GachaArchive? CurrentArchive
@@ -48,11 +53,11 @@ internal sealed partial class GachaLogService : IGachaLogService
///
public ObservableCollection? ArchiveCollection
{
- get => context.ArchiveCollection;
+ get => archiveCollection;
}
///
- public async ValueTask InitializeAsync(CancellationToken token)
+ public async ValueTask InitializeAsync(CancellationToken token = default)
{
if (context.IsInitialized)
{
@@ -67,9 +72,9 @@ internal sealed partial class GachaLogService : IGachaLogService
Dictionary nameAvatarMap = await metadataService.GetNameToAvatarMapAsync(token).ConfigureAwait(false);
Dictionary nameWeaponMap = await metadataService.GetNameToWeaponMapAsync(token).ConfigureAwait(false);
- GachaArchives.Initialize(serviceProvider, out ObservableCollection collection);
+ ObservableCollection collection = gachaLogDbService.GetGachaArchiveCollection();
- context = new(idAvatarMap, idWeaponMap, nameAvatarMap, nameWeaponMap, collection);
+ context = new(idAvatarMap, idWeaponMap, nameAvatarMap, nameWeaponMap);
return true;
}
else
@@ -87,48 +92,37 @@ internal sealed partial class GachaLogService : IGachaLogService
// Return statistics
using (ValueStopwatch.MeasureExecution(logger))
{
- using (IServiceScope scope = serviceProvider.CreateScope())
- {
- AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
- IOrderedQueryable items = appDbContext.GachaItems
- .Where(i => i.ArchiveId == archive.InnerId)
- .OrderBy(i => i.Id);
-
- return await gachaStatisticsFactory.CreateAsync(items, context).ConfigureAwait(false);
- }
+ List items = gachaLogDbService.GetGachaItemListByArchiveId(archive.InnerId);
+ return await gachaStatisticsFactory.CreateAsync(items, context).ConfigureAwait(false);
}
}
///
- public async Task> GetStatisticsSlimsAsync()
+ public async ValueTask> GetStatisticsSlimListAsync(CancellationToken token = default)
{
- using (IServiceScope scope = serviceProvider.CreateScope())
+ await InitializeAsync(token).ConfigureAwait(false);
+ ArgumentNullException.ThrowIfNull(ArchiveCollection);
+
+ List statistics = new();
+ foreach (GachaArchive archive in ArchiveCollection)
{
- AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
- List statistics = new();
- foreach (GachaArchive archive in appDbContext.GachaArchives)
- {
- IOrderedQueryable items = appDbContext.GachaItems
- .Where(i => i.ArchiveId == archive.InnerId)
- .OrderBy(i => i.Id);
-
- GachaStatisticsSlim slim = await gachaStatisticsSlimFactory.CreateAsync(items, context).ConfigureAwait(false);
- slim.Uid = archive.Uid;
- statistics.Add(slim);
- }
-
- return statistics;
+ List items = gachaLogDbService.GetGachaItemListByArchiveId(archive.InnerId);
+ GachaStatisticsSlim slim = await gachaStatisticsSlimFactory.CreateAsync(items, context).ConfigureAwait(false);
+ slim.Uid = archive.Uid;
+ statistics.Add(slim);
}
+
+ return statistics;
}
///
- public Task ExportToUIGFAsync(GachaArchive archive)
+ public ValueTask ExportToUIGFAsync(GachaArchive archive)
{
return gachaLogExportService.ExportAsync(context, archive);
}
///
- public async Task ImportFromUIGFAsync(UIGF uigf)
+ public async ValueTask ImportFromUIGFAsync(UIGF uigf)
{
CurrentArchive = await gachaLogImportService.ImportAsync(context, uigf).ConfigureAwait(false);
}
@@ -156,19 +150,15 @@ internal sealed partial class GachaLogService : IGachaLogService
///
public async Task RemoveArchiveAsync(GachaArchive archive)
{
+ ArgumentNullException.ThrowIfNull(archiveCollection);
+
// Sync cache
await taskContext.SwitchToMainThreadAsync();
- context.ArchiveCollection.Remove(archive);
+ archiveCollection.Remove(archive);
// Sync database
await taskContext.SwitchToBackgroundAsync();
- using (IServiceScope scope = serviceProvider.CreateScope())
- {
- AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
- await appDbContext.GachaArchives
- .ExecuteDeleteWhereAsync(a => a.InnerId == archive.InnerId)
- .ConfigureAwait(false);
- }
+ await gachaLogDbService.DeleteGachaArchiveByIdAsync(archive.InnerId).ConfigureAwait(false);
}
private static Task RandomDelayAsync(CancellationToken token)
@@ -246,9 +236,54 @@ internal sealed partial class GachaLogService : IGachaLogService
[Injection(InjectAs.Scoped, typeof(IGachaLogDbService))]
internal sealed partial class GachaLogDbService : IGachaLogDbService
{
+ private readonly IServiceProvider serviceProvider;
+ public ObservableCollection GetGachaArchiveCollection()
+ {
+ try
+ {
+ using (IServiceScope scope = serviceProvider.CreateScope())
+ {
+ AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
+ return appDbContext.GachaArchives.AsNoTracking().ToObservableCollection();
+ }
+ }
+ catch (SqliteException ex)
+ {
+ string message = string.Format(SH.ServiceGachaLogArchiveCollectionUserdataCorruptedMessage, ex.Message);
+ throw ThrowHelper.UserdataCorrupted(message, ex);
+ }
+ }
+
+ public List GetGachaItemListByArchiveId(Guid archiveId)
+ {
+ using (IServiceScope scope = serviceProvider.CreateScope())
+ {
+ AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
+ return appDbContext.GachaItems
+ .AsNoTracking()
+ .Where(i => i.ArchiveId == archiveId)
+ .OrderBy(i => i.Id)
+ .ToList();
+ }
+ }
+
+ public async ValueTask DeleteGachaArchiveByIdAsync(Guid archiveId)
+ {
+ using (IServiceScope scope = serviceProvider.CreateScope())
+ {
+ AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
+ await appDbContext.GachaArchives
+ .ExecuteDeleteWhereAsync(a => a.InnerId == archiveId)
+ .ConfigureAwait(false);
+ }
+ }
}
internal interface IGachaLogDbService
{
+ ValueTask DeleteGachaArchiveByIdAsync(Guid archiveId);
+ ObservableCollection GetGachaArchiveCollection();
+
+ List GetGachaItemListByArchiveId(Guid archiveId);
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogServiceContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogServiceMetadataContext.cs
similarity index 92%
rename from src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogServiceContext.cs
rename to src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogServiceMetadataContext.cs
index 363e3a4b..5d62d8d1 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogServiceContext.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogServiceMetadataContext.cs
@@ -15,7 +15,7 @@ namespace Snap.Hutao.Service.GachaLog;
///
/// 祈愿记录服务上下文
///
-internal readonly struct GachaLogServiceContext
+internal readonly struct GachaLogServiceMetadataContext
{
///
/// 物品缓存
@@ -45,6 +45,7 @@ internal readonly struct GachaLogServiceContext
///
/// 存档集合
///
+ [Obsolete]
public readonly ObservableCollection ArchiveCollection;
///
@@ -59,19 +60,16 @@ internal readonly struct GachaLogServiceContext
/// Id 武器 映射
/// 名称 角色 映射
/// 名称 武器 映射
- /// 存档集合
- public GachaLogServiceContext(
+ public GachaLogServiceMetadataContext(
Dictionary idAvatarMap,
Dictionary idWeaponMap,
Dictionary nameAvatarMap,
- Dictionary nameWeaponMap,
- ObservableCollection archiveCollection)
+ Dictionary nameWeaponMap)
{
IdAvatarMap = idAvatarMap;
IdWeaponMap = idWeaponMap;
NameAvatarMap = nameAvatarMap;
NameWeaponMap = nameWeaponMap;
- ArchiveCollection = archiveCollection;
IsInitialized = true;
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IGachaLogService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IGachaLogService.cs
index 38ad34fe..c3da913f 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IGachaLogService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IGachaLogService.cs
@@ -30,7 +30,7 @@ internal interface IGachaLogService
///
/// 存档
/// UIGF对象
- Task ExportToUIGFAsync(GachaArchive archive);
+ ValueTask ExportToUIGFAsync(GachaArchive archive);
///
/// 获得对应的祈愿统计
@@ -42,22 +42,23 @@ internal interface IGachaLogService
///
/// 异步获取简化的祈愿统计列表
///
+ /// 取消令牌
/// 简化的祈愿统计列表
- Task> GetStatisticsSlimsAsync();
+ ValueTask> GetStatisticsSlimListAsync(CancellationToken token = default);
///
/// 异步从UIGF导入数据
///
/// 信息
/// 任务
- Task ImportFromUIGFAsync(UIGF uigf);
+ ValueTask ImportFromUIGFAsync(UIGF uigf);
///
/// 异步初始化
///
/// 取消令牌
/// 是否初始化成功
- ValueTask InitializeAsync(CancellationToken token);
+ ValueTask InitializeAsync(CancellationToken token = default);
///
/// 刷新祈愿记录
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IUIGFExportService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IUIGFExportService.cs
index 702a17fa..408da5c1 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IUIGFExportService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IUIGFExportService.cs
@@ -17,5 +17,5 @@ internal interface IUIGFExportService
/// 元数据上下文
/// 存档
/// UIGF
- Task ExportAsync(GachaLogServiceContext context, GachaArchive archive);
+ ValueTask ExportAsync(GachaLogServiceMetadataContext context, GachaArchive archive);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IUIGFImportService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IUIGFImportService.cs
index feab2181..3e409e71 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IUIGFImportService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IUIGFImportService.cs
@@ -17,5 +17,5 @@ internal interface IUIGFImportService
/// 祈愿记录服务上下文
/// 数据
/// 存档
- Task ImportAsync(GachaLogServiceContext context, UIGF uigf);
+ Task ImportAsync(GachaLogServiceMetadataContext context, UIGF uigf);
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFExportService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFExportService.cs
index 5a6ec3df..f94297b7 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFExportService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFExportService.cs
@@ -18,7 +18,7 @@ internal sealed partial class UIGFExportService : IUIGFExportService
private readonly ITaskContext taskContext;
///
- public async Task ExportAsync(GachaLogServiceContext context, GachaArchive archive)
+ public async ValueTask ExportAsync(GachaLogServiceMetadataContext context, GachaArchive archive)
{
await taskContext.SwitchToBackgroundAsync();
using (IServiceScope scope = serviceProvider.CreateScope())
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFImportService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFImportService.cs
index 10579235..508b9837 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFImportService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFImportService.cs
@@ -20,7 +20,7 @@ internal sealed partial class UIGFImportService : IUIGFImportService
private readonly ITaskContext taskContext;
///
- public async Task ImportAsync(GachaLogServiceContext context, UIGF uigf)
+ public async Task ImportAsync(GachaLogServiceMetadataContext context, UIGF uigf)
{
await taskContext.SwitchToBackgroundAsync();
using (IServiceScope scope = serviceProvider.CreateScope())
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModelSlim.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModelSlim.cs
index 8186f4b6..40e53f24 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModelSlim.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModelSlim.cs
@@ -37,7 +37,7 @@ internal sealed class GachaLogViewModelSlim : Abstraction.ViewModelSlim list = await gachaLogService.GetStatisticsSlimsAsync().ConfigureAwait(false);
+ List list = await gachaLogService.GetStatisticsSlimListAsync().ConfigureAwait(false);
await taskContext.SwitchToMainThreadAsync();
StatisticsList = list;
IsInitialized = true;