aboutsummaryrefslogtreecommitdiffstats
path: root/sdvx
diff options
context:
space:
mode:
authorPinapelz <yukais@pinapelz.com>2025-02-27 16:04:16 -0800
committerPinapelz <yukais@pinapelz.com>2025-02-27 16:04:16 -0800
commit057c83de767320b071ecc0318a95a07019ab3d71 (patch)
tree12f20e1a006b86798d939615716efcac3b839dde /sdvx
initial commit
Diffstat (limited to 'sdvx')
-rw-r--r--sdvx/sdvx_csv_to_tachi.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/sdvx/sdvx_csv_to_tachi.py b/sdvx/sdvx_csv_to_tachi.py
new file mode 100644
index 0000000..062b0f4
--- /dev/null
+++ b/sdvx/sdvx_csv_to_tachi.py
@@ -0,0 +1,101 @@
+import csv
+import json
+import argparse
+
+DIFFICULTY_MAPPING = {
+ "NOVICE": "NOV",
+ "ADVANCED": "ADV",
+ "EXHAUST": "EXH",
+ "INFINITE": "INF",
+ "GRAVITY": "GRV",
+ "HEAVENLY": "HVN",
+ "VIVD": "VVD",
+ "EXCEED": "EXCEED",
+ "MAXIMUM": "MXM"
+}
+
+LAMP_MAPPING = {
+ "PLAYED": "FAILED",
+ "COMPLETE": "CLEAR",
+}
+
+def convert_sdvx_csv_to_tachi_json(csv_file, game, playtype, service):
+ encodings = ['utf-8-sig', 'utf-8', 'shift-jis', 'cp932']
+
+ for encoding in encodings:
+ try:
+ batch_manual = {
+ "meta": {
+ "game": game,
+ "playtype": playtype,
+ "service": service
+ },
+ "scores": []
+ }
+
+ with open(csv_file, newline='', encoding=encoding) as f:
+ reader = csv.DictReader(f)
+ fieldnames = reader.fieldnames
+ required_fields = ["楽曲名", "難易度", "クリアランク", "ハイスコア"]
+ if not all(field in fieldnames for field in required_fields):
+ continue
+
+
+ for row in reader:
+ lamp = LAMP_MAPPING[row["クリアランク"].upper()]
+ if row.get("ULTIMATE CHAIN"):
+ lamp = "ULTIMATE CHAIN"
+ if row.get("PERFECT"):
+ lamp = "PERFECT ULTIMATE CHAIN"
+
+ score_entry = {
+ "score": int(row["ハイスコア"]),
+ "lamp": lamp,
+ "matchType": "songTitle",
+ "identifier": row["楽曲名"],
+ "difficulty": DIFFICULTY_MAPPING[row["難易度"].upper()],
+ }
+ optional_fields = {}
+ if row.get("EXスコア"):
+ optional_fields["exScore"] = int(row["EXスコア"])
+ if row.get("fast"):
+ optional_fields["fast"] = int(row["fast"])
+ if row.get("slow"):
+ optional_fields["slow"] = int(row["slow"])
+ if row.get("maxCombo"):
+ optional_fields["maxCombo"] = int(row["maxCombo"])
+ if row.get("gauge"):
+ optional_fields["gauge"] = float(row["gauge"])
+ if optional_fields:
+ score_entry["optional"] = optional_fields
+ batch_manual["scores"].append(score_entry)
+ return batch_manual
+ except UnicodeDecodeError:
+ continue
+ except Exception as e:
+ print(f"Error with encoding {encoding}: {str(e)}")
+ continue
+
+ raise ValueError("Failed to read CSV file with any supported encoding")
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(
+ prog="sdvx_csv_to_tachi",
+ description="Converts CSV data exported from SDVX eAmuse site to Tachi compatibile JSON",
+ epilog="Note that not all information can be derived from the CSV so some fields will be missing from Tachi"
+ )
+ parser.add_argument("csv_filename", help="Path to the CSV file")
+ parser.add_argument("-s", "--service", help="Service description to be shown on Tachi (Note for where this score came from)", default="SDVX Arcade Import")
+ parser.add_argument("-o", "--output", help="Output filename", default="sdvx_tachi.json")
+ args = parser.parse_args()
+
+try:
+ output_json = convert_sdvx_csv_to_tachi_json(args.csv_filename, "sdvx", "Single", args.service)
+
+ with open(args.output, "w", encoding="utf-8") as json_file:
+ json.dump(output_json, json_file, ensure_ascii=False, indent=4)
+
+ print("Conversion completed. JSON saved as " + args.output)
+except Exception as e:
+ print(f"Error: {str(e)}")
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage