feat(missions): /mission/info, /mission/retire, /mission/change_receive_setting
Three endpoints + 9 integration tests. Captured-data-is-catalog: viewer's achievement Level starts at MIN(Level) per type from the catalog (not 1), so the assembler always has a row to render against. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,11 @@ public interface IMissionCatalogRepository
|
||||
/// <summary>All distinct achievement_type values present in the catalog. Used by /load/index materialization.</summary>
|
||||
Task<List<int>> GetAllAchievementTypesAsync(CancellationToken ct);
|
||||
|
||||
/// <summary>MIN(Level) per achievement_type — the "starting tier" for new viewers when the
|
||||
/// catalog doesn't contain a level-1 row. With our captured-data-is-catalog model, a fresh
|
||||
/// viewer starts at whatever the lowest captured tier is for that type.</summary>
|
||||
Task<IReadOnlyDictionary<int, int>> GetMinLevelByAchievementTypeAsync(CancellationToken ct);
|
||||
|
||||
/// <summary>MAX(Level) per achievement_type — cached. Used to compute wire max_level.</summary>
|
||||
Task<IReadOnlyDictionary<int, int>> GetMaxLevelByAchievementTypeAsync(CancellationToken ct);
|
||||
|
||||
|
||||
@@ -57,6 +57,15 @@ public sealed class MissionCatalogRepository : IMissionCatalogRepository
|
||||
finally { _maxLevelLock.Release(); }
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyDictionary<int, int>> GetMinLevelByAchievementTypeAsync(CancellationToken ct)
|
||||
{
|
||||
var pairs = await _db.AchievementCatalog.AsNoTracking()
|
||||
.GroupBy(e => e.AchievementType)
|
||||
.Select(g => new { Type = g.Key, Min = g.Min(e => e.Level) })
|
||||
.ToListAsync(ct);
|
||||
return pairs.ToDictionary(p => p.Type, p => p.Min);
|
||||
}
|
||||
|
||||
public Task<AchievementCatalogEntry?> GetAchievementAsync(int achievementType, int level, CancellationToken ct) =>
|
||||
_db.AchievementCatalog.AsNoTracking()
|
||||
.FirstOrDefaultAsync(e => e.AchievementType == achievementType && e.Level == level, ct);
|
||||
|
||||
Reference in New Issue
Block a user