aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPinapelz <yukais@pinapelz.com>2025-12-22 21:55:29 -0800
committerPinapelz <yukais@pinapelz.com>2025-12-22 21:55:29 -0800
commit887deb3a8cb7c3e15e3c2a4cd0f4e6c1a1ec6bf3 (patch)
treecea60c5ab5194891651a29bc38c5063af493f920
parentcbacc1cd7924c558c27c89ab0b6723dc73d0db08 (diff)
add duel0213 iidx to tachi
-rw-r--r--README.md1
-rw-r--r--iidx/asphyxia/README.md23
-rw-r--r--iidx/asphyxia/iidx_duel0213_to_tachi.py112
3 files changed, 136 insertions, 0 deletions
diff --git a/README.md b/README.md
index 006002d..18f52c5 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ Use with caution as there may be some cases missing/not handled.
- [SDVX e-amusement CSV (with limited Session/Date data)](./sdvx/eamuse_csv)
- [DDR e-amusement scores](./ddr/eamuse)
- [SDVX 22vv0 Asphyxia](./sdvx/asphyxia)
+- [IIDX duel0213 Asphyxia](./iidx/asphyxia)
- [jubeat Asphyxia-CZEAve](./jubeat/asphyxia)
**Export from Tachi**
diff --git a/iidx/asphyxia/README.md b/iidx/asphyxia/README.md
new file mode 100644
index 0000000..09ac1dd
--- /dev/null
+++ b/iidx/asphyxia/README.md
@@ -0,0 +1,23 @@
+# duel0213 Asphyxia IIDX to Batch Manual
+
+> Important, this is only compatible with [duel's Asphyxia plugin](https://github.com/duel0213/asphyxia-plugins). If you use something else it probably won't work as save formats differ.
+
+# Get Score file
+1. Go to the Web UI and select IIDX
+2. Select `Profiles`
+3. Select `Data`
+4. Choose `Score Export`
+5. If a page opens instead of a file downloading, hit `CTRL+S` and save it somewhere
+
+Command Line Arguments
+- `-f, --file` (required): Path to your Asphyxia score export JSON file
+- `-so, --sp-output`: Output filename for Single Play scores (default: `iidx_scores_sp.json`)
+- `-do, --dp-output`: Output filename for Double Play scores (default: `iidx_scores_dp.json`)
+- `-s, --service`: Service description shown on Tachi (default: `"beatmania IIDX Asphyxia Export"`)
+
+Output
+
+The script generates two separate JSON files:
+
+- **SP file**: Contains all Single Play scores (NORMAL, HYPER, ANOTHER, LEGGENDARIA)
+- **DP file**: Contains all Double Play scores (DP NORMAL, DP HYPER, DP ANOTHER, DP LEGGENDARIA)
diff --git a/iidx/asphyxia/iidx_duel0213_to_tachi.py b/iidx/asphyxia/iidx_duel0213_to_tachi.py
new file mode 100644
index 0000000..f7d56bd
--- /dev/null
+++ b/iidx/asphyxia/iidx_duel0213_to_tachi.py
@@ -0,0 +1,112 @@
+import argparse
+import json
+import os
+from datetime import datetime
+
+
+LAMP_MAP = {
+ 1: "FAILED",
+ 2: "ASSIST CLEAR",
+ 3: "EASY CLEAR",
+ 4: "CLEAR",
+ 5: "HARD CLEAR",
+ 6: "EX HARD CLEAR",
+ 7: "FULL COMBO"
+}
+
+DIFFICULTY_MAP = { # Beginner difficulty not supported
+ 1: "NORMAL",
+ 2: "HYPER",
+ 3: "ANOTHER",
+ 4: "LEGGENDARIA",
+ 6: "DP NORMAL",
+ 7: "DP HYPER",
+ 8: "DP ANOTHER",
+ 9: "DP LEGGENDARIA"
+}
+
+def convert_duel0213_to_tachi(file: str, single_output_path: str, double_output_path: str, service: str):
+ with open(file, "r", encoding="utf-8") as infile:
+ sp_scores = []
+ dp_scores = []
+ export_data = json.load(infile)
+ data_sect = export_data["data"]
+ for score_id in data_sect:
+ data = data_sect[score_id]
+ if data["collection"] != "score":
+ continue
+
+ music_id = str(data["mid"])
+ cArray = data["cArray"]
+ played_levels = []
+ for i in range(10):
+ if i == 0 or i == 5: # skip BEGINNER
+ continue
+ if cArray[i] != 0:
+ played_levels.append((i, cArray[i]))
+
+ for diff, lamp_val in played_levels:
+ score = data["esArray"][diff]
+ difficulty = DIFFICULTY_MAP[diff]
+ pgreat = data["pgArray"][diff]
+ great = data["gArray"][diff]
+ lamp = LAMP_MAP[lamp_val]
+ timestamp_str = data["updatedAt"]
+ timestamp = int(datetime.fromisoformat(timestamp_str.replace('Z', '+00:00')).timestamp() * 1000)
+ judgements = {
+ "pgreat": pgreat,
+ "great": great,
+ }
+ score_obj = {
+ "score": score,
+ "timeAchieved": timestamp,
+ "matchType": "inGameID",
+ "identifier": music_id,
+ "lamp": lamp,
+ "difficulty": difficulty,
+ "judgements": judgements
+ }
+ if diff <= 4: # SP
+ sp_scores.append(score_obj)
+ else:
+ dp_scores.append(score_obj)
+
+ batch_manual_single = {"meta": {"game": "iidx", "playtype": "SP", "service": service}, "scores": sp_scores}
+ batch_manual_double = {"meta": {"game": "iidx", "playtype": "DP", "service": service}, "scores": dp_scores}
+
+ with open(single_output_path, "w", encoding="utf-8") as spoutfile:
+ json.dump(batch_manual_single, spoutfile, indent=4, ensure_ascii=False)
+ print(f"SP Output saved to {single_output_path}")
+
+ with open(double_output_path, "w", encoding="utf-8") as dpoutfile:
+ json.dump(batch_manual_double, dpoutfile, indent=4, ensure_ascii=False)
+ print(f"DP Output saved to {double_output_path}")
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(
+ prog="iidx_duel0213_to_tachi.py",
+ description="Converts duel0213 Asphyxia IIDX save data to Tachi compatible JSON",
+ )
+ parser.add_argument(
+ "-s",
+ "--service",
+ help="Service description to be shown on Tachi (Note for where this score came from)",
+ default="beatmania IIDX Asphyxia Export",
+ )
+ parser.add_argument("-f", "--file", help="Score Export JSON Get this by going to the WebUI -> Profiles -> Detail -> Data -> Score Export", required=True)
+ parser.add_argument(
+ "-so", "--sp-output", help="Output filename for SP scores", default="iidx_scores_sp.json"
+ )
+ parser.add_argument(
+ "-do", "--dp-output", help="Output filename for DP scores", default="iidx_scores_dp.json"
+ )
+ args = parser.parse_args()
+ if args.file is None:
+ print("ERROR: Please specify score JSON. Get this by going to the WebUI -> Profiles -> Detail -> Data -> Score Export")
+ exit(1)
+ if not os.path.exists(args.file):
+ print(f"ERROR: The file {args.file} does not exist.")
+ exit(1)
+
+ convert_duel0213_to_tachi(args.file, args.sp_output, args.dp_output, args.service)
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage