mirror of
https://github.com/drmext/MonkeyBusiness.git
synced 2025-02-15 18:12:32 +01:00
IIDX score import
This commit is contained in:
parent
6a5ad537d9
commit
addec3e88d
12
README.md
12
README.md
@ -47,6 +47,16 @@ for experimental local testing and playing
|
|||||||
|
|
||||||
- DRS requires `music-info-base.xml` copied to the server folder
|
- DRS requires `music-info-base.xml` copied to the server folder
|
||||||
|
|
||||||
|
## Score Import
|
||||||
|
|
||||||
|
Scores can be [imported](utils/db) from any network
|
||||||
|
|
||||||
|
- DDR
|
||||||
|
|
||||||
|
- IIDX
|
||||||
|
|
||||||
## Web Interface
|
## Web Interface
|
||||||
|
|
||||||
- Extract [BounceTrippy](https://github.com/drmext/BounceTrippy/releases) webui to the server folder (DDR only)
|
Extract [BounceTrippy](https://github.com/drmext/BounceTrippy/releases) webui to the server folder
|
||||||
|
|
||||||
|
- DDR
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Database Utilities
|
# Database Utilities
|
||||||
|
|
||||||
**Backup db.json before shrinking or importing**
|
**Backup db.json before using these scripts**
|
||||||
|
|
||||||
## Shrink DB
|
## Shrink DB
|
||||||
|
|
||||||
@ -13,8 +13,6 @@ Example:
|
|||||||
|
|
||||||
## Score Import
|
## Score Import
|
||||||
|
|
||||||
### [import_ddr_spice_automap.py](import_ddr_spice_automap.py)
|
|
||||||
|
|
||||||
Instructions:
|
Instructions:
|
||||||
|
|
||||||
1. Enable `EA Automap` and `EA Netdump` in spicecfg
|
1. Enable `EA Automap` and `EA Netdump` in spicecfg
|
||||||
@ -27,10 +25,20 @@ Instructions:
|
|||||||
|
|
||||||
1. Disable `EA Automap` and `EA Netdump` in spicecfg
|
1. Disable `EA Automap` and `EA Netdump` in spicecfg
|
||||||
|
|
||||||
1. Run the import script
|
1. Run the corresponding import script
|
||||||
|
|
||||||
|
### [import_ddr_spice_automap.py](import_ddr_spice_automap.py)
|
||||||
|
|
||||||
Example: `python utils\db\import_ddr_spice_automap.py --automap_xml automap_0.xml --version 19 --monkey_db db.json --ddr_id 12345678`
|
Example: `python utils\db\import_ddr_spice_automap.py --automap_xml automap_0.xml --version 19 --monkey_db db.json --ddr_id 12345678`
|
||||||
|
|
||||||
- `--version` {19 for A20P or 20 for A3}
|
- `--version` 19 for A20P or 20 for A3
|
||||||
|
|
||||||
- `--ddr_id` {destination profile in db.json}
|
- `--ddr_id` destination profile in db.json
|
||||||
|
|
||||||
|
### [import_iidx_spice_automap.py](import_iidx_spice_automap.py)
|
||||||
|
|
||||||
|
Example: `python utils\db\import_iidx_spice_automap.py --automap_xml automap_0.xml --version 30 --monkey_db db.json --iidx_id 12345678`
|
||||||
|
|
||||||
|
- `--version` must match the source export version (27+ supported)
|
||||||
|
|
||||||
|
- `--iidx_id` destination profile in db.json
|
199
utils/db/import_iidx_spice_automap.py
Normal file
199
utils/db/import_iidx_spice_automap.py
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
import argparse
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
|
from tinydb import TinyDB, where
|
||||||
|
from tinydb.middlewares import CachingMiddleware
|
||||||
|
from tinydb.storages import JSONStorage
|
||||||
|
|
||||||
|
|
||||||
|
def main(automap_xml, version, monkey_db, iidx_id):
|
||||||
|
class ClearFlags(IntEnum):
|
||||||
|
NO_PLAY = 0
|
||||||
|
FAILED = 1
|
||||||
|
ASSIST_CLEAR = 2
|
||||||
|
EASY_CLEAR = 3
|
||||||
|
CLEAR = 4
|
||||||
|
HARD_CLEAR = 5
|
||||||
|
EX_HARD_CLEAR = 6
|
||||||
|
FULL_COMBO = 7
|
||||||
|
|
||||||
|
storage = CachingMiddleware(JSONStorage)
|
||||||
|
storage.WRITE_CACHE_SIZE = 5000
|
||||||
|
|
||||||
|
db = TinyDB(
|
||||||
|
monkey_db,
|
||||||
|
indent=2,
|
||||||
|
encoding="utf-8",
|
||||||
|
ensure_ascii=False,
|
||||||
|
storage=storage,
|
||||||
|
)
|
||||||
|
|
||||||
|
iidx_id = int(iidx_id.replace("-", ""))
|
||||||
|
|
||||||
|
profile = db.table("iidx_profile").get(where("iidx_id") == iidx_id)
|
||||||
|
if profile == None:
|
||||||
|
raise SystemExit(f"ERROR: IIDX profile {iidx_id} not in {monkey_db}")
|
||||||
|
|
||||||
|
game_version = 30
|
||||||
|
|
||||||
|
scores = []
|
||||||
|
|
||||||
|
with open(automap_xml, "rb") as fp:
|
||||||
|
automap_0 = fp.read().split(b"\n\n")
|
||||||
|
|
||||||
|
scores_xml = False
|
||||||
|
for xml in automap_0:
|
||||||
|
try:
|
||||||
|
tree = ET.ElementTree(ET.fromstring(xml.decode(encoding="shift-jis")))
|
||||||
|
root = tree.getroot()
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
if scores_xml:
|
||||||
|
sp_dp = int(root.find(f"IIDX{version}music/style").get("type"))
|
||||||
|
print(sp_dp)
|
||||||
|
for m in root.findall(f"IIDX{version}music/m"):
|
||||||
|
score = [int(x) for x in m.text.split()]
|
||||||
|
if score[0] != -1:
|
||||||
|
# skip rivals
|
||||||
|
continue
|
||||||
|
music_id = score[1]
|
||||||
|
for difficulty in range(5):
|
||||||
|
d = difficulty + 2
|
||||||
|
if score[d] != -1:
|
||||||
|
clear_flg = score[d]
|
||||||
|
ex_score = score[d + 5]
|
||||||
|
miss_count = score[d + 10]
|
||||||
|
scores.append(
|
||||||
|
[
|
||||||
|
sp_dp,
|
||||||
|
music_id,
|
||||||
|
difficulty,
|
||||||
|
clear_flg,
|
||||||
|
ex_score,
|
||||||
|
miss_count,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
scores_xml = False
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if root.find(f"IIDX{version}music").get("method") == "getrank":
|
||||||
|
scores_xml = True
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
total_count = len(scores)
|
||||||
|
|
||||||
|
if total_count == 0:
|
||||||
|
raise SystemExit("ERROR: No scores to import")
|
||||||
|
|
||||||
|
for s in scores:
|
||||||
|
play_style = s[0]
|
||||||
|
music_id = s[1]
|
||||||
|
difficulty = s[2]
|
||||||
|
clear_flg = s[3]
|
||||||
|
ex_score = s[4]
|
||||||
|
miss_count = s[5]
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"music_id: {music_id}, sp_dp: {play_style}, difficulty: {difficulty}, clear_flg: {clear_flg}, ex_score: {ex_score}, miss_count: {miss_count}"
|
||||||
|
)
|
||||||
|
|
||||||
|
best_score = db.table("iidx_scores_best").get(
|
||||||
|
(where("iidx_id") == iidx_id)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("music_id") == music_id)
|
||||||
|
& (where("chart_id") == difficulty)
|
||||||
|
)
|
||||||
|
best_score = {} if best_score is None else best_score
|
||||||
|
|
||||||
|
if clear_flg < ClearFlags.EASY_CLEAR:
|
||||||
|
miss_count = -1
|
||||||
|
best_miss_count = best_score.get("miss_count", miss_count)
|
||||||
|
if best_miss_count == -1:
|
||||||
|
miss_count = max(miss_count, best_miss_count)
|
||||||
|
elif clear_flg > ClearFlags.ASSIST_CLEAR:
|
||||||
|
miss_count = min(miss_count, best_miss_count)
|
||||||
|
else:
|
||||||
|
miss_count = best_miss_count
|
||||||
|
best_ex_score = best_score.get("ex_score", ex_score)
|
||||||
|
best_score_data = {
|
||||||
|
"game_version": game_version,
|
||||||
|
"iidx_id": iidx_id,
|
||||||
|
"pid": 13,
|
||||||
|
"play_style": play_style,
|
||||||
|
"music_id": music_id,
|
||||||
|
"chart_id": difficulty,
|
||||||
|
"miss_count": miss_count,
|
||||||
|
"ex_score": max(ex_score, best_ex_score),
|
||||||
|
"ghost": best_score.get(
|
||||||
|
"ghost",
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
),
|
||||||
|
"ghost_gauge": best_score.get(
|
||||||
|
"ghost_gauge",
|
||||||
|
"4c0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
),
|
||||||
|
"clear_flg": max(clear_flg, best_score.get("clear_flg", clear_flg)),
|
||||||
|
"gauge_type": best_score.get("gauge_type", 4),
|
||||||
|
}
|
||||||
|
|
||||||
|
db.table("iidx_scores_best").upsert(
|
||||||
|
best_score_data,
|
||||||
|
(where("iidx_id") == iidx_id)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("music_id") == music_id)
|
||||||
|
& (where("chart_id") == difficulty),
|
||||||
|
)
|
||||||
|
|
||||||
|
score_stats = db.table("iidx_score_stats").get(
|
||||||
|
(where("music_id") == music_id)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("chart_id") == difficulty)
|
||||||
|
)
|
||||||
|
score_stats = {} if score_stats is None else score_stats
|
||||||
|
|
||||||
|
score_stats["game_version"] = game_version
|
||||||
|
score_stats["play_style"] = play_style
|
||||||
|
score_stats["music_id"] = music_id
|
||||||
|
score_stats["chart_id"] = difficulty
|
||||||
|
score_stats["play_count"] = score_stats.get("play_count", 0) + 1
|
||||||
|
score_stats["fc_count"] = score_stats.get("fc_count", 0) + (
|
||||||
|
1 if clear_flg == ClearFlags.FULL_COMBO else 0
|
||||||
|
)
|
||||||
|
score_stats["clear_count"] = score_stats.get("clear_count", 0) + (
|
||||||
|
1 if clear_flg >= ClearFlags.EASY_CLEAR else 0
|
||||||
|
)
|
||||||
|
score_stats["fc_rate"] = int(
|
||||||
|
(score_stats["fc_count"] / score_stats["play_count"]) * 1000
|
||||||
|
)
|
||||||
|
score_stats["clear_rate"] = int(
|
||||||
|
(score_stats["clear_count"] / score_stats["play_count"]) * 1000
|
||||||
|
)
|
||||||
|
|
||||||
|
db.table("iidx_score_stats").upsert(
|
||||||
|
score_stats,
|
||||||
|
(where("music_id") == music_id)
|
||||||
|
& (where("play_style") == play_style)
|
||||||
|
& (where("chart_id") == difficulty),
|
||||||
|
)
|
||||||
|
|
||||||
|
db.close()
|
||||||
|
print()
|
||||||
|
print(f"{total_count} scores imported to IIDX profile {iidx_id} in {monkey_db}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--automap_xml", help="Input xml file", required=True)
|
||||||
|
parser.add_argument(
|
||||||
|
"--version",
|
||||||
|
help="",
|
||||||
|
default=30,
|
||||||
|
type=int,
|
||||||
|
)
|
||||||
|
parser.add_argument("--monkey_db", help="Output json file", required=True)
|
||||||
|
parser.add_argument("--iidx_id", help="12345678", required=True)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
main(args.automap_xml, args.version, args.monkey_db, args.iidx_id)
|
Loading…
x
Reference in New Issue
Block a user