From f0094619f321e1ac1d958d6c7a7b90a01ea4ca47 Mon Sep 17 00:00:00 2001 From: nichinichisou Date: Sat, 3 Oct 2026 23:43:24 +0800 Subject: [PATCH] feat(deck-data): export character rank experience thresholds MasterCharacterRank now carries `_exp`, the cumulative experience each rank needs. A reader can convert a character's experience into its rank: the highest rank whose threshold the experience has reached. --- docs/music-data.md | 2 +- src/nnnotes/deckdata.py | 2 +- tests/test_deckdata.py | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/music-data.md b/docs/music-data.md index 66d71a0..211f0b9 100644 --- a/docs/music-data.md +++ b/docs/music-data.md @@ -351,7 +351,7 @@ column their rows have, in the order the rows first have them; when such a table | `MasterSupportCardRank` | `_id` `_group` `_rank` `_limitLevel` `_cardTypeLinkBonusRate` `_supportSkill01Level` `_supportSkill02Level` `_gekisouSupportSkill01Level` `_gekisouSupportSkill02Level` | | `MasterCharacter` | `_id` `_bandID` | | `MasterBand` | `_id` | -| `MasterCharacterRank` | `_id` `_rank` `_bonus` | +| `MasterCharacterRank` | `_id` `_rank` `_exp` `_bonus` | | `MasterCharacterTotalRank` | `_id` `_totalRank` `_bonus` | | `MasterBandItemSkillEffect` | `_id` `_bandItemId` `_level` `_skillTargetIDs` `_skillEffectType` `_effectValue` | | `MasterBandItem` | `_id` `_bandId` | diff --git a/src/nnnotes/deckdata.py b/src/nnnotes/deckdata.py index 4b76c49..2298b6d 100644 --- a/src/nnnotes/deckdata.py +++ b/src/nnnotes/deckdata.py @@ -63,7 +63,7 @@ "_supportSkill02Level _gekisouSupportSkill01Level _gekisouSupportSkill02Level"), ("MasterCharacter", "_id _bandID"), ("MasterBand", "_id"), - ("MasterCharacterRank", "_id _rank _bonus"), + ("MasterCharacterRank", "_id _rank _exp _bonus"), ("MasterCharacterTotalRank", "_id _totalRank _bonus"), ("MasterBandItemSkillEffect", "_id _bandItemId _level _skillTargetIDs _skillEffectType _effectValue"), ("MasterBandItem", "_id _bandId"), diff --git a/tests/test_deckdata.py b/tests/test_deckdata.py index 21d9f3e..da68109 100644 --- a/tests/test_deckdata.py +++ b/tests/test_deckdata.py @@ -214,6 +214,24 @@ def rows(name): assert document["provenance"]["tables"]["MasterVip"] == hashlib.sha256((tmp_path / "m/MasterVip.bin").read_bytes()).hexdigest() +def test_character_rank_carries_its_experience_threshold(tmp_path): + def rows(name): + if name == "MasterCharacterRank": + return [{"_id": 1, "_rank": 1, "_exp": 0, "_bonus": 0}, {"_id": 2, "_rank": 2, "_exp": 3, "_bonus": 5}] + return rows_of(name) + + ranks = export(tmp_path, rows=rows)["master"]["MasterCharacterRank"] + # A character's rank is the highest rank whose cumulative experience it has reached. + assert ranks == {"columns": ["_id", "_rank", "_exp", "_bonus"], "rows": [[1, 1, 0, 0], [2, 2, 3, 5]]} + + def without_exp(name): + if name == "MasterCharacterRank": + return [{"_id": 1, "_rank": 1, "_bonus": 0}] + return rows_of(name) + failing(tmp_path, r"MasterCharacterRank: row 0 \(_id 1\) has no column _exp", + src=deckdata.master_files(master_dir(tmp_path, without_exp, name="p"))) + + def test_charts(tmp_path): export(tmp_path) charts = json.loads((tmp_path / "deck.json").read_bytes())["charts"]