minor code style

This commit is contained in:
DismissedLight
2023-12-10 21:37:27 +08:00
parent ecd17de279
commit 824fba89a8
4 changed files with 117 additions and 117 deletions

View File

@@ -10,13 +10,6 @@ namespace Snap.Hutao.Extension;
/// </summary>
internal static class MemoryCacheExtension
{
/// <summary>
/// 尝试从 IMemoryCache 中移除并返回具有指定键的值
/// </summary>
/// <param name="memoryCache">缓存</param>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <returns>是否移除成功</returns>
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<T>(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;
}
}

View File

@@ -28,11 +28,9 @@ internal sealed partial class AnnouncementService : IAnnouncementService
public async ValueTask<AnnouncementWrapper> 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<ListWrapper<AnnouncementContent>> announcementContentResponse = await announcementClient
.GetAnnouncementContentsAsync(cancellationToken)
.ConfigureAwait(false);
if (announcementContentResponse.IsOk())
{
List<AnnouncementContent> contents = announcementContentResponse.Data.List;
Dictionary<int, string> 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<ListWrapper<AnnouncementContent>> announcementContentResponse = await announcementClient
.GetAnnouncementContentsAsync(cancellationToken)
.ConfigureAwait(false);
if (!announcementContentResponse.IsOk())
{
return default!;
}
List<AnnouncementContent> contents = announcementContentResponse.Data.List;
Dictionary<int, string> 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<int, string> contentMap, List<AnnouncementListWrapper> 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<DateTimeOffset> 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<DateTimeOffset> 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;
}
}
}

View File

@@ -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<AchievementView> list)
{
// Fast path
throw Must.NeverHappen("AchievementViewModel.Achievements.SourceCollection 应为 List<AchievementView>");
}
Dictionary<AchievementGoalId, AchievementGoalStatistics> 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<AchievementGoalId, AchievementGoalStatistics> counter = achievementGoals.ToDictionary(x => x.Id, AchievementGoalStatistics.From);
// Fast path
if (achievements.SourceCollection is List<AchievementView> 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<AchievementView>");
}
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 _);
}
}

View File

@@ -72,17 +72,7 @@ internal sealed class AchievementGoalView : ObservableObject, INameIcon, IMappin
/// <param name="statistics">统计</param>
public void UpdateFinishDescriptionAndPercent(AchievementGoalStatistics statistics)
{
UpdateFinishDescriptionAndPercent(statistics.Finished, statistics.TotalCount);
}
/// <summary>
/// 更新进度
/// </summary>
/// <param name="finished">完成项</param>
/// <param name="count">总项</param>
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;
}
}