diff --git a/SVSim.EmulatedEntrypoint/Services/MissionAssembler.cs b/SVSim.EmulatedEntrypoint/Services/MissionAssembler.cs index faa2f2b3..d000b07b 100644 --- a/SVSim.EmulatedEntrypoint/Services/MissionAssembler.cs +++ b/SVSim.EmulatedEntrypoint/Services/MissionAssembler.cs @@ -9,15 +9,18 @@ public sealed class MissionAssembler : IMissionAssembler private readonly IMissionCatalogRepository _catalog; private readonly IViewerMissionRepository _viewerRepo; private readonly TimeProvider _time; + private readonly IGameCalendarService _calendar; public MissionAssembler( IMissionCatalogRepository catalog, IViewerMissionRepository viewerRepo, - TimeProvider time) + TimeProvider time, + IGameCalendarService calendar) { _catalog = catalog; _viewerRepo = viewerRepo; _time = time; + _calendar = calendar; } public async Task BuildAsync(Viewer viewer, CancellationToken ct = default) @@ -54,15 +57,14 @@ public sealed class MissionAssembler : IMissionAssembler if (c.EventType is not null) counterEventKeys.Add(c.EventType); } - // BP monthly missions for current JST month. - var jstNow = now.ToOffset(TimeSpan.FromHours(9)).AddHours(-2); - var monthlyMissions = await _catalog.GetMonthlyMissionsAsync(jstNow.Year, jstNow.Month, ct); + // BP monthly missions for the current calendar month (UTC). + var monthlyMissions = await _catalog.GetMonthlyMissionsAsync(now.Year, now.Month, ct); foreach (var mm in monthlyMissions) { if (mm.EventType is not null) counterEventKeys.Add(mm.EventType); } - var periods = new[] { JstPeriod.DayKey(now), JstPeriod.WeekKey(now), JstPeriod.MonthKey(now), JstPeriod.AllTime }; + var periods = _calendar.AllPeriods(now); var counters = counterEventKeys.Count == 0 ? new List() : await _viewerRepo.GetCountersAsync(viewer.Id, counterEventKeys.ToList(), periods, ct); @@ -78,7 +80,7 @@ public sealed class MissionAssembler : IMissionAssembler int total = 0; if (cat.EventType is not null) { - string period = cat.LotType == 6 ? JstPeriod.DayKey(now) : JstPeriod.WeekKey(now); + string period = cat.LotType == 6 ? _calendar.DayKey(now) : _calendar.WeekKey(now); total = GetCounter(cat.EventType, period); } dto.UserMissionList.Add(new UserMissionDto @@ -105,7 +107,7 @@ public sealed class MissionAssembler : IMissionAssembler foreach (var a in viewerAchievements.OrderBy(a => a.AchievementType)) { if (!achievementCatalogByKey.TryGetValue((a.AchievementType, a.Level), out var catalog)) continue; - int total = catalog.EventType is null ? 0 : GetCounter(catalog.EventType, JstPeriod.AllTime); + int total = catalog.EventType is null ? 0 : GetCounter(catalog.EventType, GameCalendarService.AllTime); int maxLevel = maxLevelByType.TryGetValue(a.AchievementType, out var ml) ? ml : a.Level; dto.UserAchievementList.Add(new UserAchievementDto { @@ -142,7 +144,7 @@ public sealed class MissionAssembler : IMissionAssembler // BP monthly missions block — omit when no rows for current month. if (monthlyMissions.Count > 0) { - var startUtc = new DateTimeOffset(jstNow.Year, jstNow.Month, 1, 2, 0, 0, TimeSpan.FromHours(9)); + var startUtc = new DateTimeOffset(now.Year, now.Month, 1, 0, 0, 0, TimeSpan.Zero); var endUtc = startUtc.AddMonths(1).AddSeconds(-1); dto.BattlePassMonthlyMission = new BPMonthlyMissionsDto { @@ -151,7 +153,7 @@ public sealed class MissionAssembler : IMissionAssembler MissionList = monthlyMissions.Select(mm => { int done = mm.EventType is null ? 0 - : GetCounter(mm.EventType, JstPeriod.MonthKey(now)); + : GetCounter(mm.EventType, _calendar.MonthKey(now)); var entry = new BPMonthlyMissionDto { Name = mm.Name, diff --git a/SVSim.EmulatedEntrypoint/Services/MissionProgressService.cs b/SVSim.EmulatedEntrypoint/Services/MissionProgressService.cs index 8181dece..0d340f06 100644 --- a/SVSim.EmulatedEntrypoint/Services/MissionProgressService.cs +++ b/SVSim.EmulatedEntrypoint/Services/MissionProgressService.cs @@ -9,24 +9,27 @@ public sealed class MissionProgressService : IMissionProgressService private readonly IMissionCatalogRepository _catalog; private readonly IViewerMissionRepository _viewerRepo; private readonly TimeProvider _time; + private readonly IGameCalendarService _calendar; public MissionProgressService( SVSimDbContext db, IMissionCatalogRepository catalog, IViewerMissionRepository viewerRepo, - TimeProvider time) + TimeProvider time, + IGameCalendarService calendar) { _db = db; _catalog = catalog; _viewerRepo = viewerRepo; _time = time; + _calendar = calendar; } public async Task RecordEventAsync(long viewerId, IReadOnlyList eventKeys, int delta = 1, CancellationToken ct = default) { if (eventKeys.Count == 0) return; var now = _time.GetUtcNow(); - var periods = JstPeriod.AllPeriods(now); + var periods = _calendar.AllPeriods(now); // 1. Increment counters for every (key, period). foreach (var key in eventKeys) @@ -50,7 +53,7 @@ public sealed class MissionProgressService : IMissionProgressService var atLevel = catalogRows.FirstOrDefault(r => r.Level == viewerRow.Level); if (atLevel is null || atLevel.EventType is null) continue; - var count = await _viewerRepo.GetCounterAsync(viewerId, atLevel.EventType, JstPeriod.AllTime, ct); + var count = await _viewerRepo.GetCounterAsync(viewerId, atLevel.EventType, GameCalendarService.AllTime, ct); if (count >= atLevel.RequireNumber && viewerRow.AchievementStatus == 0) { viewerRow.AchievementStatus = 1;