aboutsummaryrefslogtreecommitdiffstats
path: root/sdvx/asphyxia/22vv0_kfc_to_tachi.py
blob: 637443f3387c167e365dc4a4358ad53a891751c7 (plain) (blame)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import argparse
import json
import os
import requests


LAMP_MAP = {
    1: "FAILED",
    2: "CLEAR",
    3: "EXCESSIVE CLEAR",
    4: "ULTIMATE CHAIN",
    5: "PERFECT ULTIMATE CHAIN",
    6: "MAXXIVE CLEAR"
}

DIFFICULTY_MAP = {
    0: "NOV",
    1: "ADV",
    2: "EXH",
    3: "GAME_SPECIFIC",
    4: "MXM"
}


def load_seeds(url: str = "https://raw.githubusercontent.com/zkrising/Tachi/refs/heads/main/seeds/collections/charts-sdvx.json") -> dict:
    print("Loading seeds from:", url)
    response = requests.get(url)
    response.raise_for_status()
    return response.json()

def find_chart_difficulties(in_game_id: int, seeds: dict = None):
        low, high = 0, len(seeds) - 1
        results = []
        while low <= high:
            mid = (low + high) // 2
            chart = seeds[mid]
            if chart["data"]["inGameID"] == in_game_id:
                results.append(chart)
                left, right = mid - 1, mid + 1
                while left >= 0 and seeds[left]["data"]["inGameID"] == in_game_id:
                    results.append(seeds[left])
                    left -= 1
                while right < len(seeds) and seeds[right]["data"]["inGameID"] == in_game_id:
                    results.append(seeds[right])
                    right += 1
                break
            elif chart["data"]["inGameID"] < in_game_id:
                low = mid + 1
            else:
                high = mid - 1
        for result in results:
            if result["difficulty"] not in DIFFICULTY_MAP.values():
                return result["difficulty"]
        return None


def convert_22vv0_sdvx_to_tachi_json(file: str, output_path: str, service: str, profile_id: str):
    seeds = load_seeds()
    with open(file, "r", encoding="utf-8") as infile:
        batch_manual = {
            "meta": {"game": "sdvx", "playtype": "Single", "service": service},
        }
        scores = []
        for line in infile:
            data = json.loads(line)
            if "collection" not in data.keys():
                continue
            if data["collection"] == "music":
                music_id = data["mid"]
                difficulty = DIFFICULTY_MAP[data["type"]]
                if difficulty == "GAME_SPECIFIC":
                    difficulty  = find_chart_difficulties(music_id, seeds)
                    if difficulty is None:
                        print("[ERROR] -> Difficulty for", music_id, " was not found in Tachi seeds")
                        continue
                score = data["score"]
                exscore = data["exscore"]
                lamp = LAMP_MAP[data["clear"]]
                timestamp = data["updatedAt"]["$$date"]
                scores.append({
                    "score": score,
                    "lamp": lamp,
                    "matchType": "sdvxInGameID",
                    "identifier": str(data["mid"]),
                    "difficulty": difficulty,
                    "timeAchieved": timestamp,
                    "optional": {
                        "exScore": exscore
                    }
                })
        batch_manual["scores"] = scores
        with open(output_path, "w", encoding="utf-8") as outfile:
            json.dump(batch_manual, outfile, indent=4, ensure_ascii=False)
            print(f"Output saved to {output_path}")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        prog="22vv0_kfc_to_tachi.py",
        description="Converts 22vv0 Asphyxia SDVX (KFC) 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="SOUND VOLTEX Asphyxia (22vv0)",
    )
    parser.add_argument("-f", "--file", help="AsphyxiaCORE SOUND VOLTEX .db file (sdvx@asphyxia.db)", required=True)
    parser.add_argument(
        "-o", "--output", help="Output filename", default="sdvx_asphyxia_batch_manual.json"
    )
    parser.add_argument("-p", "--profile", help="Asphyxia Profile ID to export for")
    args = parser.parse_args()
    if args.file is None:
        print("ERROR: Please specify Asphyxia DB file (from savedata folder)")
        exit(1)
    if not os.path.exists(args.file):
        print(f"ERROR: The file {args.file} does not exist.")
        exit(1)

    convert_22vv0_sdvx_to_tachi_json(args.file, args.output, args.service, args.profile)
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage