From 824fba89a8749e4a6b51b35d4798ca069fec91db Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Sun, 10 Dec 2023 21:37:27 +0800 Subject: [PATCH] minor code style --- .../Extension/MemoryCacheExtension.cs | 19 ++- .../Snap.Hutao/Service/AnnouncementService.cs | 138 +++++++++--------- .../Achievement/AchievementFinishPercent.cs | 65 +++++---- .../Achievement/AchievementGoalView.cs | 12 +- 4 files changed, 117 insertions(+), 117 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/MemoryCacheExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/MemoryCacheExtension.cs index 9ae998a5..77b7a755 100644 --- a/src/Snap.Hutao/Snap.Hutao/Extension/MemoryCacheExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Extension/MemoryCacheExtension.cs @@ -10,13 +10,6 @@ namespace Snap.Hutao.Extension; /// internal static class MemoryCacheExtension { - /// - /// 尝试从 IMemoryCache 中移除并返回具有指定键的值 - /// - /// 缓存 - /// 键 - /// 值 - /// 是否移除成功 public static bool TryRemove(this IMemoryCache memoryCache, string key, out object? value) { if (!memoryCache.TryGetValue(key, out value)) @@ -27,4 +20,16 @@ internal static class MemoryCacheExtension memoryCache.Remove(key); return true; } + + public static bool TryGetRequiredValue(this IMemoryCache memoryCache, string key, [NotNullWhen(true)] out T? value) + where T : class + { + if (!memoryCache.TryGetValue(key, out value)) + { + return false; + } + + ArgumentNullException.ThrowIfNull(value); + return true; + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AnnouncementService.cs b/src/Snap.Hutao/Snap.Hutao/Service/AnnouncementService.cs index 45a51287..df39f93b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AnnouncementService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AnnouncementService.cs @@ -28,11 +28,9 @@ internal sealed partial class AnnouncementService : IAnnouncementService public async ValueTask GetAnnouncementWrapperAsync(CancellationToken cancellationToken = default) { // 缓存中存在记录,直接返回 - if (memoryCache.TryGetValue(CacheKey, out object? cache)) + if (memoryCache.TryGetRequiredValue(CacheKey, out AnnouncementWrapper? cache)) { - AnnouncementWrapper? wrapper = (AnnouncementWrapper?)cache; - ArgumentNullException.ThrowIfNull(wrapper); - return wrapper; + return cache; } await taskContext.SwitchToBackgroundAsync(); @@ -40,30 +38,32 @@ internal sealed partial class AnnouncementService : IAnnouncementService .GetAnnouncementsAsync(cancellationToken) .ConfigureAwait(false); - if (announcementWrapperResponse.IsOk()) + if (!announcementWrapperResponse.IsOk()) { - AnnouncementWrapper wrapper = announcementWrapperResponse.Data; - Response> announcementContentResponse = await announcementClient - .GetAnnouncementContentsAsync(cancellationToken) - .ConfigureAwait(false); - - if (announcementContentResponse.IsOk()) - { - List contents = announcementContentResponse.Data.List; - - Dictionary contentMap = contents - .ToDictionary(id => id.AnnId, content => content.Content); - - // 将活动公告置于前方 - wrapper.List.Reverse(); - - PreprocessAnnouncements(contentMap, wrapper.List); - - return memoryCache.Set(CacheKey, wrapper, TimeSpan.FromMinutes(30)); - } + return default!; } - return default!; + AnnouncementWrapper wrapper = announcementWrapperResponse.Data; + Response> announcementContentResponse = await announcementClient + .GetAnnouncementContentsAsync(cancellationToken) + .ConfigureAwait(false); + + if (!announcementContentResponse.IsOk()) + { + return default!; + } + + List contents = announcementContentResponse.Data.List; + + Dictionary contentMap = contents + .ToDictionary(id => id.AnnId, content => content.Content); + + // 将活动公告置于前方 + wrapper.List.Reverse(); + + PreprocessAnnouncements(contentMap, wrapper.List); + + return memoryCache.Set(CacheKey, wrapper, TimeSpan.FromMinutes(30)); } private static void PreprocessAnnouncements(Dictionary contentMap, List announcementListWrappers) @@ -103,56 +103,60 @@ internal sealed partial class AnnouncementService : IAnnouncementService .List .Single(ann => AnnouncementRegex.VersionUpdateTitleRegex.IsMatch(ann.Title)); - if (AnnouncementRegex.VersionUpdateTimeRegex.Match(versionUpdate.Content) is { Success: true } match) + if (AnnouncementRegex.VersionUpdateTimeRegex.Match(versionUpdate.Content) is not { Success: true } match) { - DateTimeOffset versionUpdateTime = DateTimeOffset.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture); - _ = 1; - foreach (ref readonly Announcement announcement in CollectionsMarshal.AsSpan(activities)) + return; + } + + DateTimeOffset versionUpdateTime = DateTimeOffset.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture); + + foreach (ref readonly Announcement announcement in CollectionsMarshal.AsSpan(activities)) + { + if (AnnouncementRegex.PermanentActivityAfterUpdateTimeRegex.Match(announcement.Content) is { Success: true } permanent) { - if (AnnouncementRegex.PermanentActivityAfterUpdateTimeRegex.Match(announcement.Content) is { Success: true } permanent) + announcement.StartTime = versionUpdateTime; + continue; + } + + if (AnnouncementRegex.PersistentActivityAfterUpdateTimeRegex.Match(announcement.Content) is { Success: true } persistent) + { + announcement.StartTime = versionUpdateTime; + announcement.EndTime = versionUpdateTime + TimeSpan.FromDays(42); + continue; + } + + if (AnnouncementRegex.TransientActivityAfterUpdateTimeRegex.Match(announcement.Content) is { Success: true } transient) + { + announcement.StartTime = versionUpdateTime; + announcement.EndTime = DateTimeOffset.Parse(transient.Groups[2].ValueSpan, CultureInfo.InvariantCulture); + continue; + } + + MatchCollection matches = AnnouncementRegex.XmlTimeTagRegex.Matches(announcement.Content); + if (matches.Count < 2) + { + continue; + } + + List dateTimes = matches.Select(match => DateTimeOffset.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture)).ToList(); + DateTimeOffset min = DateTimeOffset.MaxValue; + DateTimeOffset max = DateTimeOffset.MinValue; + + foreach (DateTimeOffset time in dateTimes) + { + if (time < min) { - announcement.StartTime = versionUpdateTime; - continue; + min = time; } - if (AnnouncementRegex.PersistentActivityAfterUpdateTimeRegex.Match(announcement.Content) is { Success: true } persistent) + if (time > max) { - announcement.StartTime = versionUpdateTime; - announcement.EndTime = versionUpdateTime + TimeSpan.FromDays(42); - continue; - } - - if (AnnouncementRegex.TransientActivityAfterUpdateTimeRegex.Match(announcement.Content) is { Success: true } transient) - { - announcement.StartTime = versionUpdateTime; - announcement.EndTime = DateTimeOffset.Parse(transient.Groups[2].ValueSpan, CultureInfo.InvariantCulture); - continue; - } - - MatchCollection matches = AnnouncementRegex.XmlTimeTagRegex.Matches(announcement.Content); - if (matches.Count >= 2) - { - List dateTimes = matches.Select(match => DateTimeOffset.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture)).ToList(); - DateTimeOffset min = DateTimeOffset.MaxValue; - DateTimeOffset max = DateTimeOffset.MinValue; - - foreach (DateTimeOffset time in dateTimes) - { - if (time < min) - { - min = time; - } - - if (time > max) - { - max = time; - } - } - - announcement.StartTime = min; - announcement.EndTime = max; + max = time; } } + + announcement.StartTime = min; + announcement.EndTime = max; } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementFinishPercent.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementFinishPercent.cs index 57bfc0af..7a4678cd 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementFinishPercent.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementFinishPercent.cs @@ -21,41 +21,42 @@ internal static class AchievementFinishPercent int totalFinished = 0; int totalCount = 0; - if (viewModel.Achievements is { } achievements) + if (viewModel.Achievements is not { } achievements) { - if (viewModel.AchievementGoals is { } achievementGoals) + return; + } + + if (viewModel.AchievementGoals is not { } achievementGoals) + { + return; + } + + if (achievements.SourceCollection is not List list) + { + // Fast path + throw Must.NeverHappen("AchievementViewModel.Achievements.SourceCollection 应为 List"); + } + + Dictionary counter = achievementGoals.ToDictionary(x => x.Id, AchievementGoalStatistics.From); + + foreach (ref readonly AchievementView achievement in CollectionsMarshal.AsSpan(list)) + { + ref AchievementGoalStatistics goalStat = ref CollectionsMarshal.GetValueRefOrNullRef(counter, achievement.Inner.Goal); + + goalStat.TotalCount += 1; + totalCount += 1; + if (achievement.IsChecked) { - Dictionary counter = achievementGoals.ToDictionary(x => x.Id, AchievementGoalStatistics.From); - - // Fast path - if (achievements.SourceCollection is List list) - { - foreach (ref readonly AchievementView achievement in CollectionsMarshal.AsSpan(list)) - { - // Make the state update as fast as possible - ref AchievementGoalStatistics stat = ref CollectionsMarshal.GetValueRefOrNullRef(counter, achievement.Inner.Goal); - - stat.TotalCount += 1; - totalCount += 1; - if (achievement.IsChecked) - { - stat.Finished += 1; - totalFinished += 1; - } - } - } - else - { - Must.NeverHappen("AchievementViewModel.Achievements.SourceCollection 应为 List"); - } - - foreach (AchievementGoalStatistics statistics in counter.Values) - { - statistics.AchievementGoal.UpdateFinishDescriptionAndPercent(statistics); - } - - viewModel.FinishDescription = AchievementStatistics.Format(totalFinished, totalCount, out _); + goalStat.Finished += 1; + totalFinished += 1; } } + + foreach (AchievementGoalStatistics statistics in counter.Values) + { + statistics.AchievementGoal.UpdateFinishDescriptionAndPercent(statistics); + } + + viewModel.FinishDescription = AchievementStatistics.Format(totalFinished, totalCount, out _); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementGoalView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementGoalView.cs index bd5e5c48..c89d7b26 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementGoalView.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementGoalView.cs @@ -72,17 +72,7 @@ internal sealed class AchievementGoalView : ObservableObject, INameIcon, IMappin /// 统计 public void UpdateFinishDescriptionAndPercent(AchievementGoalStatistics statistics) { - UpdateFinishDescriptionAndPercent(statistics.Finished, statistics.TotalCount); - } - - /// - /// 更新进度 - /// - /// 完成项 - /// 总项 - private void UpdateFinishDescriptionAndPercent(int finished, int count) - { - FinishDescription = AchievementStatistics.Format(finished, count, out double finishPercent); + FinishDescription = AchievementStatistics.Format(statistics.Finished, statistics.TotalCount, out double finishPercent); FinishPercent = finishPercent; } } \ No newline at end of file