diff options
| author | Pinapelz <yukais@pinapelz.com> | 2025-02-28 02:18:02 -0800 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2025-02-28 02:18:02 -0800 |
| commit | b6aa2b4a9d04d01f511c630e1286e01e3fc2a244 (patch) | |
| tree | ce9f606b0597b0135563f78d5180c00353574abf /chuni/aquadx | |
| parent | 5d26d7a3f0571444f7a006b0c1be0c2bfe9912c5 (diff) | |
mai2: add aquadx to tachi json script
Diffstat (limited to 'chuni/aquadx')
| -rw-r--r-- | chuni/aquadx/README.md | 1 | ||||
| -rw-r--r-- | chuni/aquadx/chuni_aquadx_to_tachi.py | 102 |
2 files changed, 103 insertions, 0 deletions
diff --git a/chuni/aquadx/README.md b/chuni/aquadx/README.md new file mode 100644 index 0000000..0f79860 --- /dev/null +++ b/chuni/aquadx/README.md @@ -0,0 +1 @@ +`chuni_aquadx_to_tachi.py` is for converting the user data exported JSON from AquaNet. It does not require a connection to the DB diff --git a/chuni/aquadx/chuni_aquadx_to_tachi.py b/chuni/aquadx/chuni_aquadx_to_tachi.py new file mode 100644 index 0000000..4063ac2 --- /dev/null +++ b/chuni/aquadx/chuni_aquadx_to_tachi.py @@ -0,0 +1,102 @@ +import argparse +import json + +DIFFICULTY_MAPPING = { + 0: "BASIC", + 1: "ADVANCED", + 2: "EXPERT", + 3: "MASTER", + 4: "ULTIMA", + 5: "WORLD'S END", +} + +def convert_chuni_aquadx_json_to_tachi_json(input_json: str, output_file: str, service: str): + with open(input_json, "r", encoding="utf-8") as f: + raw_data = json.load(f) + + batch_manual = { + "meta": {"game": "chunithm", "playtype": "Single", "service": service}, + "scores": [], + } + + processed_count = 0 + skipped_count = 0 + + if "userPlaylogList" in raw_data: + for entry in raw_data["userPlaylogList"]: + level = entry.get("level", 0) + + # Skip World's End, Unsupported by Tachi + if level == 5 or level not in DIFFICULTY_MAPPING: + skipped_count += 1 + continue + + processed_count += 1 + music_id = entry["musicId"] + + score_value = entry.get("score", 0) + is_clear = entry.get("isClear", False) + is_full_combo = entry.get("isFullCombo", False) + is_all_justice = entry.get("isAllJustice", False) + is_all_perfect = entry.get("isAllPerfect", False) + lamp = "FAILED" + if is_all_perfect: + lamp = "ALL JUSTICE CRITICAL" + elif is_all_justice: + lamp = "ALL JUSTICE" + elif is_full_combo: + lamp = "FULL COMBO" + elif is_clear: + lamp = "CLEAR" + timestamp = entry.get("sortNumber", None) + + jcrit = entry.get("judgeHeaven", 0) + entry.get("judgeCritical", 0) + justice = entry.get("judgeJustice", 0) + attack = entry.get("judgeAttack", 0) + miss = entry.get("judgeGuilty", 0) + combo = entry.get("maxCombo", 0) + + score_entry = { + "score": score_value, + "lamp": lamp, + "matchType": "inGameID", + "identifier": str(music_id), + "difficulty": DIFFICULTY_MAPPING[level], + "timeAchieved": timestamp * 1000 if timestamp else None, + "judgements": { + "jcrit": jcrit, + "justice": justice, + "attack": attack, + "miss": miss, + }, + "optional": {"maxCombo": combo}, + } + + batch_manual["scores"].append(score_entry) + + with open(output_file, "w", encoding="utf-8") as f: + print("--- Processing Summary ---") + print(f"Total scores processed: {processed_count}") + print(f"Scores skipped (level 5 or invalid): {skipped_count}") + print(f"Output saved to {output_file}") + json.dump(batch_manual, f, indent=4, ensure_ascii=False) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + prog="chuni_aquadx_to_tachi", + description="Converts AquaDX score data for Chuni to Tachi compatible JSON", + epilog="Fast/Slow can't be derived (I think)", + ) + parser.add_argument("input_file", help="Path to the input JSON file exported from AquaDX") + parser.add_argument( + "-s", + "--service", + help="Service description to be shown on Tachi (Note for where this score came from)", + default="AquaDX Chuni Import", + ) + parser.add_argument( + "-o", "--output", help="Output filename", default="aquadx_chuni_tachi.json" + ) + args = parser.parse_args() + convert_chuni_aquadx_json_to_tachi_json(args.input_file, args.output, args.service) |
