1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
import csv
import json
import argparse
DIFFICULTY_MAPPING = {
"NOVICE": "NOV",
"ADVANCED": "ADV",
"EXHAUST": "EXH",
"INFINITE": "INF",
"GRAVITY": "GRV",
"HEAVENLY": "HVN",
"VIVD": "VVD",
"EXCEED": "XCD",
"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)}")
|