diff --git a/src/swgoh_comlink/StatCalc/data_builder/_builder_base.py b/src/swgoh_comlink/StatCalc/data_builder/_builder_base.py index b9a0403..fdb9df3 100644 --- a/src/swgoh_comlink/StatCalc/data_builder/_builder_base.py +++ b/src/swgoh_comlink/StatCalc/data_builder/_builder_base.py @@ -238,16 +238,19 @@ def _build_unit_data( """Build per-unit metadata for characters and ships. The Comlink ``units`` field is an array of rarity groups, each - containing a ``unitDef`` array. Rarity-1 entries supply base - definitions (gear tiers, skills, etc.); all rarities contribute + containing a ``unitDef`` array. Each unit's lowest-rarity entry + supplies its base definition (gear tiers, skills, etc.) — usually + rarity 1, but some units (e.g. ``ADELPHIRANGER``) start at 2★ and + have no rarity-1 entry. All rarities contribute ``statProgressionId`` for growth modifier tables. """ base_units: dict[str, dict[str, Any]] = {} + base_rarity: dict[str, int] = {} stat_prog_map: dict[str, dict[str, str]] = {} total_units = 0 - # Filter for only obtainable units at rarity 1 + # Filter for only obtainable units base_unit_list = [unit for unit in raw_units if unit.get("obtainable", False) and unit.get("obtainableTime") == "0"] for unit in base_unit_list: @@ -264,7 +267,8 @@ def _build_unit_data( if prog_id: stat_prog_map.setdefault(base_id, {})[str(rarity)] = prog_id - if rarity == 1: + if 0 < rarity < base_rarity.get(base_id, 8): + base_rarity[base_id] = rarity base_units[base_id] = unit data: dict[str, dict[str, Any]] = {} diff --git a/tests/unit/test_builder_base.py b/tests/unit/test_builder_base.py index b4ee0e9..445d30c 100644 --- a/tests/unit/test_builder_base.py +++ b/tests/unit/test_builder_base.py @@ -507,6 +507,17 @@ def test_growth_modifiers_across_rarities(make_unit: Callable[..., dict[str, Any assert result["unitData"]["UNIT1"]["growthModifiers"] == {"1": {"2": 10}, "7": {"2": 70}} +@pytest.mark.parametrize("make_unit", [_char_unit, _ship_unit], ids=["character", "ship"]) +@pytest.mark.parametrize("rarities", [[2, 7], [7, 2], ["SEVEN_STAR", "TWO_STAR"]], ids=["asc", "desc", "enum"]) +def test_unit_without_one_star_row_uses_lowest_rarity_as_base(make_unit: Callable[..., dict[str, Any]], rarities): + """Units that start above 1★ (e.g. ADELPHIRANGER at 2★) have no rarity-1 row but must still be built.""" + units = [make_unit("STARTS_AT_TWO", rarity=r, statProgressionId=f"stattable_{r}") for r in rarities] + + result = _build_unit_data(units, {}, {}) + + assert list(result) == ["STARTS_AT_TWO"] + + @pytest.mark.parametrize( "excluded", [