namespace Mr.BrickAdventures.Progression; /// /// The authored upgrade table for every Skill: what each level costs to reach. Built from /// SkillData resources by an adapter — same pattern as , so no port is /// needed and a test can construct one directly. /// public sealed class SkillCatalogue { private readonly Dictionary> _costs; private SkillCatalogue(Dictionary> costs) => _costs = costs; public static SkillCatalogue Empty() => new(new Dictionary>()); /// /// Builds a catalogue. Each Skill's list is the cost to reach level 1, level 2, and so on, so a /// Skill with an empty list cannot be bought at all. /// public static SkillCatalogue Of(IReadOnlyDictionary> costsByLevel) => new(costsByLevel.ToDictionary(e => e.Key, e => e.Value)); /// /// The highest level this Skill can reach, or null when it has no authored upgrades and so /// cannot be bought. Returning null is what stops Upgrades[0].Cost from throwing on the /// five Skills that currently have no upgrade entries. /// public SkillLevel? MaxLevelOf(SkillId skill) => _costs.TryGetValue(skill, out var costs) && costs.Count > 0 ? SkillLevel.Of(costs.Count) : null; /// /// What it costs to reach , or null if this Skill does not go that high. /// public Coins? CostToReach(SkillId skill, SkillLevel level) => _costs.TryGetValue(skill, out var costs) && level.Value <= costs.Count ? costs[level.Value - 1] : null; }