From b6aa2b4a9d04d01f511c630e1286e01e3fc2a244 Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Fri, 28 Feb 2025 02:18:02 -0800 Subject: mai2: add aquadx to tachi json script --- chuni/aquadx/README.md | 1 + chuni/aquadx/chuni_aquadx_to_tachi.py | 102 ++++++++++++++++++++++++++++++++++ chuni/chuni_aquadx_to_tachi.py | 102 ---------------------------------- 3 files changed, 103 insertions(+), 102 deletions(-) create mode 100644 chuni/aquadx/README.md create mode 100644 chuni/aquadx/chuni_aquadx_to_tachi.py delete mode 100644 chuni/chuni_aquadx_to_tachi.py (limited to 'chuni') 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) diff --git a/chuni/chuni_aquadx_to_tachi.py b/chuni/chuni_aquadx_to_tachi.py deleted file mode 100644 index 4063ac2..0000000 --- a/chuni/chuni_aquadx_to_tachi.py +++ /dev/null @@ -1,102 +0,0 @@ -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) -- cgit v1.2.3