Implement GITADORA

This commit is contained in:
drmext 2022-12-17 23:09:40 +00:00
parent 6a4e6ec88b
commit 74a6e16d22
No known key found for this signature in database
GPG Key ID: F1ED48FFE79A6961
11 changed files with 1645 additions and 13 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.pyc
mdb*.xml
/db*.json
/*.db
.venv/

View File

@ -18,9 +18,17 @@ for experimental local testing and playing
- DDR A20 PLUS
- DDR A3
- GITADORA 5 Matixx
- GITADORA 6 EXCHAIN
- GITADORA 7 NEX+AGE
- GITADORA 8 HIGH-VOLTAGE
- GITADORA 9 FUZZ-UP
- IIDX 18 Resort Anthem
- IIDX 19 Lincle
- IIDX 20 tricoro
- IIDX 29 CastHour
- IIDX 30 RESIDENT
- SDVX 6 EXCEED GEAR

View File

@ -50,20 +50,62 @@ async def core_get_game_version_from_software_version(software_version):
_, model, dest, spec, rev, ext = software_version
ext = int(ext)
if model == "LDJ" and ext >= 2022101700:
return 30
elif model == "LDJ" and ext in range(2021101300, 2022101500):
return 29
elif model == "JDZ" and ext == 2011071200:
if model == "LDJ":
if ext >= 2022101700:
return 30
elif ext in range(2021101300, 2022101500):
return 29
elif ext in range(2020102800, 2021100601):
return 28
elif ext in range(2019101600, 2020102201):
return 27
elif ext in range(2018110700, 2019100701):
return 26
elif ext in range(2017122100, 2018103101):
return 25
elif ext in range(2016102400, 2017082801):
return 24
elif ext in range(2015111100, 2016102001):
return 23
elif ext in range(2014091700, 2015080501):
return 22
elif ext in range(2013100200, 2014071601):
return 21
elif ext in range(2012091900, 2013090901):
return 20
elif model == "KDZ":
return 19
elif model == "JDZ":
return 18
elif model == "KDZ" and ext == 2012090300:
return 19
elif model == "LDJ" and ext == 2013090900:
return 20
elif model == "MDX" and ext >= 2019022600:
return 19
elif model == "KFC" and ext >= 2020090402:
return 6
elif model == "M32":
if ext >= 2022121400:
return 9
elif ext >= 2021042100:
return 8
elif ext >= 2019100200:
return 7
elif ext >= 2018072700:
return 6
elif ext >= 2017090600:
return 5
elif ext >= 2017011800:
return 4
elif ext in range(2015042100, 2016112302):
return 3
elif ext in range(2014021400, 2015032702):
return 2
elif ext in range(2013012400, 2014011601):
return 1
elif model == "MDX":
if ext >= 2019022600: # ???
return 19
elif model == "KFC":
if ext >= 2020090402: # ???
return 6
else:
return 0

View File

@ -12,6 +12,7 @@ def get_target_table(game_id):
"LDJ": "iidx_profile",
"MDX": "ddr_profile",
"KFC": "sdvx_profile",
"M32": "gitadora_profile",
"JDZ": "iidx_profile",
"KDZ": "iidx_profile",
}

View File

View File

@ -0,0 +1,263 @@
from tinydb import Query, where
import random
from fastapi import APIRouter, Request, Response
from core_common import core_process_request, core_prepare_response, E
from core_database import get_db
router = APIRouter(prefix="/local", tags=["local"])
router.model_whitelist = ["M32"]
def get_profile(cid):
return get_db().table("gitadora_profile").get(where("card") == cid)
def get_game_profile(cid, game_version):
profile = get_profile(cid)
return profile["version"].get(str(game_version), None)
@router.post("/{gameinfo}/{ver}_cardutil/check")
async def gitadora_cardutil_check(ver: str, request: Request):
request_info = await core_process_request(request)
game_version = request_info["game_version"]
data = request_info["root"][0].find("player")
no = int(data.attrib["no"])
dataid = data.find("refid").text
profile = get_game_profile(dataid, game_version)
if profile is None:
state = 0
name = ""
did = 0
else:
state = 2
name = profile["name"]
did = 1
response = E.response(
E(
f"{ver}_cardutil",
E.player(
E.name(name, __type="str"),
E.charaid(0, __type="s32"),
E.did(did, __type="s32"),
E.skilldata(
E.skill(0, __type="s32"),
E.all_skill(0, __type="s32"),
E.old_skill(0, __type="s32"),
E.old_all_skill(0, __type="s32"),
),
no=1,
state=state,
),
)
)
response_body, response_headers = await core_prepare_response(request, response)
return Response(content=response_body, headers=response_headers)
@router.post("/{gameinfo}/{ver}_cardutil/regist")
async def gitadora_cardutil_regist(ver: str, request: Request):
request_info = await core_process_request(request)
game_version = request_info["game_version"]
spec = request_info["spec"]
data = request_info["root"][0].find("player")
no = int(data.attrib["no"])
dataid = data.find("refid").text
db = get_db().table("gitadora_profile")
all_profiles_for_card = db.get(Query().card == dataid)
if "gitadora_id" not in all_profiles_for_card:
gitadora_id = random.randint(10000000, 99999999)
all_profiles_for_card["gitadora_id"] = gitadora_id
all_profiles_for_card["version"][str(game_version)] = {
"game_version": game_version,
"name": "kors k",
"title": "MONKEY BUSINESS",
"charaid": 0,
"stickers": {},
}
for game_type in ("drummania", "guitarfreaks"):
all_profiles_for_card["version"][str(game_version)][game_type] = {
"customdata_playstyle": [
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
20,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
20,
0,
],
"customdata_custom": [0] * 50,
"playinfo_cabid": 1,
"playinfo_play": 0,
"playinfo_playtime": 0,
"playinfo_playterm": 0,
"playinfo_session_cnt": 0,
"playinfo_saved_cnt": 0,
"playinfo_matching_num": 0,
"playinfo_extra_stage": 0,
"playinfo_extra_play": 0,
"playinfo_extra_clear": 0,
"playinfo_encore_play": 0,
"playinfo_encore_clear": 0,
"playinfo_pencore_play": 0,
"playinfo_pencore_clear": 0,
"playinfo_max_clear_diff": 0,
"playinfo_max_full_diff": 0,
"playinfo_max_exce_diff": 0,
"playinfo_clear_num": 0,
"playinfo_full_num": 0,
"playinfo_exce_num": 0,
"playinfo_no_num": 0,
"playinfo_e_num": 0,
"playinfo_d_num": 0,
"playinfo_c_num": 0,
"playinfo_b_num": 0,
"playinfo_a_num": 0,
"playinfo_s_num": 0,
"playinfo_ss_num": 0,
"playinfo_last_category": 0,
"playinfo_last_musicid": 0,
"playinfo_last_seq": 0,
"playinfo_disp_level": 0,
"tutorial_progress": 0,
"tutorial_disp_state": 0,
"information": [0] * 50,
"reward": [0] * 50,
"skilldata_skill": 0,
"skilldata_allskill": 0,
"groove_extra_gauge": 0,
"groove_encore_gauge": 0,
"groove_encore_cnt": 0,
"groove_encore_success": 0,
"groove_unlock_point": 0,
"record_max_skill": 0,
"record_max_all_skill": 0,
"record_max_clear_diff": 0,
"record_max_full_diff": 0,
"record_max_exce_diff": 0,
"record_max_clear_music_num": 0,
"record_max_full_music_num": 0,
"record_max_exce_music_num": 0,
"record_max_clear_seq_num": 0,
"record_max_classic_all_skill": 0,
"record_diff_100_nr": 0,
"record_diff_150_nr": 0,
"record_diff_200_nr": 0,
"record_diff_250_nr": 0,
"record_diff_300_nr": 0,
"record_diff_350_nr": 0,
"record_diff_400_nr": 0,
"record_diff_450_nr": 0,
"record_diff_500_nr": 0,
"record_diff_550_nr": 0,
"record_diff_600_nr": 0,
"record_diff_650_nr": 0,
"record_diff_700_nr": 0,
"record_diff_750_nr": 0,
"record_diff_800_nr": 0,
"record_diff_850_nr": 0,
"record_diff_900_nr": 0,
"record_diff_950_nr": 0,
"record_diff_100_clear": [0] * 7,
"record_diff_150_clear": [0] * 7,
"record_diff_200_clear": [0] * 7,
"record_diff_250_clear": [0] * 7,
"record_diff_300_clear": [0] * 7,
"record_diff_350_clear": [0] * 7,
"record_diff_400_clear": [0] * 7,
"record_diff_450_clear": [0] * 7,
"record_diff_500_clear": [0] * 7,
"record_diff_550_clear": [0] * 7,
"record_diff_600_clear": [0] * 7,
"record_diff_650_clear": [0] * 7,
"record_diff_700_clear": [0] * 7,
"record_diff_750_clear": [0] * 7,
"record_diff_800_clear": [0] * 7,
"record_diff_850_clear": [0] * 7,
"record_diff_900_clear": [0] * 7,
"record_diff_950_clear": [0] * 7,
"favorite_music_list_1": [-1] * 100,
"favorite_music_list_2": [-1] * 100,
"favorite_music_list_3": [-1] * 100,
"recommend_musicid_list": [-1] * 5,
"thanks_medal_medal": 0,
"thanks_medal_granted_total_medal": 0,
# "skindata_skin": [0] * 100,
}
db.upsert(all_profiles_for_card, where("card") == dataid)
response = E.response(
E(
f"{ver}_cardutil",
E.player(
E.is_succession(0, __type="bool"),
E.did(1, __type="s32"),
no=no,
),
)
)
response_body, response_headers = await core_prepare_response(request, response)
return Response(content=response_body, headers=response_headers)

341
modules/gitadora/gameend.py Normal file
View File

@ -0,0 +1,341 @@
from tinydb import Query, where
from fastapi import APIRouter, Request, Response
from core_common import core_process_request, core_prepare_response, E
from core_database import get_db
router = APIRouter(prefix="/local", tags=["local"])
router.model_whitelist = ["M32"]
def get_profile(cid):
return get_db().table("gitadora_profile").get(where("card") == cid)
def get_game_profile(cid, game_version):
profile = get_profile(cid)
return profile["version"].get(str(game_version), None)
@router.post("/{gameinfo}/{ver}_gameend/regist")
async def gitadora_gameend_regist(ver: str, request: Request):
request_info = await core_process_request(request)
game_version = request_info["game_version"]
spec = request_info["spec"]
if spec == "A":
g = "guitarfreaks"
elif spec == "B":
g = "drummania"
root = request_info["root"][0]
player = root.find("player")
no = int(player.attrib["no"])
if player.attrib["card"] == "use":
dataid = player.find("refid").text
profile = get_profile(dataid)
gitadora_id = profile["gitadora_id"]
game_profile = profile["version"].get(str(game_version), {})
game_profile[g]["customdata_playstyle"] = [
int(x) for x in player.find("customdata/playstyle").text.split(" ")
]
game_profile[g]["customdata_custom"] = [
int(x) for x in player.find("customdata/custom").text.split(" ")
]
for k in [
"cabid",
"play",
"playtime",
"playterm",
"session_cnt",
"matching_num",
"extra_stage",
"extra_play",
"extra_clear",
"encore_play",
"encore_clear",
"pencore_play",
"pencore_clear",
"max_clear_diff",
"max_full_diff",
"max_exce_diff",
"clear_num",
"full_num",
"exce_num",
"no_num",
"e_num",
"d_num",
"c_num",
"b_num",
"a_num",
"s_num",
"ss_num",
"last_category",
"last_musicid",
"last_seq",
"disp_level",
]:
game_profile[g]["playinfo_" + k] = int(player.find(f"playinfo/{k}").text)
game_profile[g]["tutorial_progress"] = int(
player.find("tutorial/progress").text
)
game_profile[g]["tutorial_disp_state"] = int(
player.find("tutorial/disp_state").text
)
game_profile[g]["information"] = [
int(x) for x in player.find("information/info").text.split(" ")
]
game_profile[g]["reward"] = [
int(x) for x in player.find("reward/status").text.split(" ")
]
game_profile[g]["skilldata_skill"] = int(player.find("skilldata/skill").text)
game_profile[g]["skilldata_allskill"] = int(
player.find("skilldata/all_skill").text
)
groove = [
"extra_gauge",
"encore_gauge",
"encore_cnt",
"encore_success",
]
if game_version > 6:
groove.append("unlock_point")
for k in groove:
game_profile[g]["groove_" + k] = int(player.find(f"groove/{k}").text)
record_max = [
"skill",
"all_skill",
"clear_diff",
"full_diff",
"exce_diff",
"clear_music_num",
"full_music_num",
"exce_music_num",
"clear_seq_num",
]
if game_version > 6:
record_max.append("classic_all_skill")
for k in record_max:
game_profile[g]["record_max_" + k] = int(
player.find(f"record/max/{k}").text
)
for k in [
"diff_100_nr",
"diff_150_nr",
"diff_200_nr",
"diff_250_nr",
"diff_300_nr",
"diff_350_nr",
"diff_400_nr",
"diff_450_nr",
"diff_500_nr",
"diff_550_nr",
"diff_600_nr",
"diff_650_nr",
"diff_700_nr",
"diff_750_nr",
"diff_800_nr",
"diff_850_nr",
"diff_900_nr",
"diff_950_nr",
]:
game_profile[g]["record_" + k] = int(player.find(f"record/diff/{k}").text)
for k in [
"diff_100_clear",
"diff_150_clear",
"diff_200_clear",
"diff_250_clear",
"diff_300_clear",
"diff_350_clear",
"diff_400_clear",
"diff_450_clear",
"diff_500_clear",
"diff_550_clear",
"diff_600_clear",
"diff_650_clear",
"diff_700_clear",
"diff_750_clear",
"diff_800_clear",
"diff_850_clear",
"diff_900_clear",
"diff_950_clear",
]:
game_profile[g]["record_" + k] = [
int(x) for x in player.find(f"record/diff/{k}").text.split(" ")
]
for k in [
"music_list_1",
"music_list_2",
"music_list_3",
]:
game_profile[g]["favorite_" + k] = [
int(x) for x in player.find(f"favoritemusic/{k}").text.split(" ")
]
profile["version"][str(game_version)] = game_profile
get_db().table("gitadora_profile").upsert(profile, where("card") == dataid)
stage = player.findall("stage")
for s in stage:
data_version = root.find("data_version").text
timestamp = int(s.find("date_ms").text)
musicid = int(s.find("musicid").text)
seq = int(s.find("seq").text)
skill = int(s.find("skill").text)
new_skill = int(s.find("new_skill").text)
clear = int(s.find("clear").text)
auto_clear = int(s.find("auto_clear").text)
fullcombo = int(s.find("fullcombo").text)
excellent = int(s.find("excellent").text)
medal = int(s.find("medal").text)
perc = int(s.find("perc").text)
new_perc = int(s.find("new_perc").text)
rank = int(s.find("rank").text)
score = int(s.find("score").text)
combo = int(s.find("combo").text)
max_combo_perc = int(s.find("max_combo_perc").text)
flags = int(s.find("flags").text)
phrase_combo_perc = int(s.find("phrase_combo_perc").text)
perfect = int(s.find("perfect").text)
great = int(s.find("great").text)
good = int(s.find("good").text)
ok = int(s.find("ok").text)
miss = int(s.find("miss").text)
perfect_perc = int(s.find("perfect_perc").text)
great_perc = int(s.find("great_perc").text)
good_perc = int(s.find("good_perc").text)
ok_perc = int(s.find("ok_perc").text)
miss_perc = int(s.find("miss_perc").text)
meter = int(s.find("meter").text)
meter_prog = int(s.find("meter_prog").text)
before_meter = int(s.find("before_meter").text)
before_meter_prog = int(s.find("before_meter_prog").text)
is_new_meter = int(s.find("is_new_meter").text)
phrase_data_num = int(s.find("phrase_data_num").text)
phrase_addr = [int(x) for x in s.find("phrase_addr").text.split(" ")]
phrase_type = [int(x) for x in s.find("phrase_type").text.split(" ")]
phrase_status = [int(x) for x in s.find("phrase_status").text.split(" ")]
phrase_end_addr = int(s.find("phrase_end_addr").text)
get_db().table(f"{g}_scores").insert(
{
"timestamp": timestamp,
"game_version": game_version,
"gitadora_id": gitadora_id,
"data_version": data_version,
"musicid": musicid,
"seq": seq,
"skill": skill,
"new_skill": new_skill,
"clear": clear,
"auto_clear": auto_clear,
"fullcombo": fullcombo,
"excellent": excellent,
"medal": medal,
"perc": perc,
"new_perc": new_perc,
"rank": rank,
"score": score,
"combo": combo,
"max_combo_perc": max_combo_perc,
"flags": flags,
"phrase_combo_perc": phrase_combo_perc,
"perfect": perfect,
"great": great,
"good": good,
"ok": ok,
"miss": miss,
"perfect_perc": perfect_perc,
"great_perc": great_perc,
"good_perc": good_perc,
"ok_perc": ok_perc,
"miss_perc": miss_perc,
"meter": meter,
"meter_prog": meter_prog,
"before_meter": before_meter,
"before_meter_prog": before_meter_prog,
"is_new_meter": is_new_meter,
"phrase_data_num": phrase_data_num,
"phrase_addr": phrase_addr,
"phrase_type": phrase_type,
"phrase_status": phrase_status,
"phrase_end_addr": phrase_end_addr,
},
)
best_score = (
get_db()
.table(f"{g}_scores_best")
.get(
(where("gitadora_id") == gitadora_id)
& (where("musicid") == musicid)
& (where("seq") == seq)
)
)
best_score = {} if best_score is None else best_score
best_ex_score = best_score.get("score", score)
best_score_data = {
"gitadora_id": gitadora_id,
"musicid": musicid,
"seq": seq,
"skill": max(skill, best_score.get("skill", skill)),
"clear": max(clear, best_score.get("clear", clear)),
"fullcombo": max(fullcombo, best_score.get("fullcombo", fullcombo)),
"excellent": max(excellent, best_score.get("excellent", excellent)),
"perc": max(perc, best_score.get("perc", perc)),
"rank": max(rank, best_score.get("rank", rank)),
"meter": meter
if score >= best_ex_score
else best_score.get("meter", meter),
"meter_prog": meter_prog
if score >= best_ex_score
else best_score.get("meter_prog", meter_prog),
}
get_db().table(f"{g}_scores_best").upsert(
best_score_data,
(where("gitadora_id") == gitadora_id)
& (where("musicid") == musicid)
& (where("seq") == seq),
)
response = E.response(
E(
f"{ver}_gameend",
E.gamemode(mode="game_mode"),
E.player(
E.skill(
E.rank(1, __type="s32"),
E.total_nr(1, __type="s32"),
),
E.all_skill(
E.rank(1, __type="s32"),
E.total_nr(1, __type="s32"),
),
no=no,
state=0,
),
)
)
response_body, response_headers = await core_prepare_response(request, response)
return Response(content=response_body, headers=response_headers)

View File

@ -0,0 +1,218 @@
import time
from fastapi import APIRouter, Request, Response
from core_common import core_process_request, core_prepare_response, E
router = APIRouter(prefix="/local", tags=["local"])
router.model_whitelist = ["M32"]
@router.post("/{gameinfo}/{ver}_gameinfo/get")
async def gitadora_gameinfo_get(ver: str, request: Request):
request_info = await core_process_request(request)
game_version = request_info["game_version"]
response = E.response(
E(
f"{ver}_gameinfo",
E.now_date(round(time.time()), __type="u64"),
E.extra(
E.extra_lv(0, __type="u8"),
E.extramusic(
E.music(
E.musicid(0, __type="s32"),
E.get_border(0, __type="u8"),
),
),
),
E.general_term(
*[
E.termdata(
E.type(f"general_{s}", __type="str"),
E.term(1, __type="u8"),
E.start_date_ms(0, __type="u64"),
E.end_date_ms(0, __type="u64"),
)
for s in [
"ultimate_mobile_2019_info",
"50th_konami_logo",
"cardconnect_champ",
"otobear_birthday",
"kac_9th_info",
"floor_break_info",
]
],
),
*[
E(
x,
E.term(1, __type="u8"),
E.start_date_ms(0, __type="u64"),
E.end_date_ms(0, __type="u64"),
)
for x in [
"phrase_combo_challenge",
"sdvx_stamprally3",
"chronicle_1",
"paseli_point_lottery",
]
],
*[
E(
f"phrase_combo_challenge_{x}",
E.term(1, __type="u8"),
E.start_date_ms(0, __type="u64"),
E.end_date_ms(0, __type="u64"),
)
for x in range(2, 21)
],
E.long_otobear_fes_1(
E.term(1, __type="u8"),
E.start_date_ms(0, __type="u64"),
E.end_date_ms(0, __type="u64"),
E.bonus_musicid(),
),
E.monstar_subjugation(
E.bonus_musicid(0, __type="s32"),
*[
E(
f"monstar_subjugation_{x}",
E.term(1, __type="u8"),
E.start_date_ms(0, __type="u64"),
E.end_date_ms(0, __type="u64"),
)
for x in range(1, 5)
],
),
E.bear_fes(
*[
E(
f"bear_fes_{x}",
E.term(1, __type="u8"),
E.start_date_ms(0, __type="u64"),
E.end_date_ms(0, __type="u64"),
)
for x in range(1, 5)
],
),
*[
E(
f"kouyou_challenge_{x}",
E.term(0, __type="u8"),
E.bonus_musicid(0, __type="s32"),
)
for x in range(1, 4)
],
*[
E(
x,
E.term(1, __type="u8"),
E.start_date_ms(0, __type="u64"),
E.end_date_ms(0, __type="u64"),
E.box_term(
E.state(0, __type="u8"),
),
)
for x in ["thanksgiving", "lotterybox"]
],
E.sticker_campaign(
E.term(0, __type="u8"),
E.sticker_list(),
),
E.infect_music(
E.term(1, __type="u8"),
),
E.unlock_challenge(
E.term(0, __type="u8"),
),
E.battle(
E.term(1, __type="u8"),
),
E.battle_chara(
E.term(1, __type="u8"),
),
E.data_ver_limit(
E.term(0, __type="s32" if game_version >= 9 else "u8"),
),
E.ea_pass_propel(
E.term(0, __type="u8"),
),
E.monthly_skill(
E.term(0, __type="u8"),
E.target_music(
E.music(
E.musicid(0, __type="s32"),
),
),
),
E.update_prog(
E.term(0, __type="u8"),
),
E.rockwave(E.event_list()),
E.general_term(),
E.jubeat_omiyage_challenge(),
E.kac2017(),
E.nostalgia_concert(),
E.trbitemdata(),
E.ctrl_movie(),
E.ng_jacket(),
E.ng_recommend_music(),
E.ranking(
E.skill_0_999(),
E.skill_1000_1499(),
E.skill_1500_1999(),
E.skill_2000_2499(),
E.skill_2500_2999(),
E.skill_3000_3499(),
E.skill_3500_3999(),
E.skill_4000_4499(),
E.skill_4500_4999(),
E.skill_5000_5499(),
E.skill_5500_5999(),
E.skill_6000_6499(),
E.skill_6500_6999(),
E.skill_7000_7499(),
E.skill_7500_7999(),
E.skill_8000_8499(),
E.skill_8500_9999(),
E.total(),
E.original(),
E.bemani(),
E.famous(),
E.anime(),
E.band(),
E.western(),
),
E.processing_report_state(0, __type="u8"),
E.assert_report_state(0, __type="u8"),
E.recommendmusic(
E.music(
E.musicid(0, __type="s32"),
),
nr=1,
),
E.demomusic(nr=0),
E.event_skill(),
E.temperature(
E.is_send(0, __type="bool"),
),
E.bemani_summer_2018(
E.is_open(0, __type="bool"),
),
E.kac2018(
E.event(
E.term(0, __type="s32"),
E.since(0, __type="u64"),
E.till(0, __type="u64"),
E.is_open(0, __type="bool"),
E.target_music(
E.music_id([0] * 6, __type="s32"),
),
),
),
)
)
response_body, response_headers = await core_prepare_response(request, response)
return Response(content=response_body, headers=response_headers)

605
modules/gitadora/gametop.py Normal file
View File

@ -0,0 +1,605 @@
from tinydb import Query, where
import time
from fastapi import APIRouter, Request, Response
from core_common import core_process_request, core_prepare_response, E
from core_database import get_db
router = APIRouter(prefix="/local", tags=["local"])
router.model_whitelist = ["M32"]
def get_profile(cid):
return get_db().table("gitadora_profile").get(where("card") == cid)
def get_game_profile(cid, game_version):
profile = get_profile(cid)
return profile["version"].get(str(game_version), None)
@router.post("/{gameinfo}/{ver}_gametop/get")
async def gitadora_gametop_get(ver: str, request: Request):
request_info = await core_process_request(request)
game_version = request_info["game_version"]
spec = request_info["spec"]
if spec == "A":
g = "guitarfreaks"
elif spec == "B":
g = "drummania"
data = request_info["root"][0].find("player")
no = int(data.attrib["no"])
dataid = data.find("refid").text
profile = get_game_profile(dataid, game_version)
gitadora_id = get_profile(dataid)["gitadora_id"]
records = {}
for record in (
get_db().table(f"{g}_scores_best").search(where("gitadora_id") == gitadora_id)
):
s = {
"musicid": record["musicid"],
"seq": record["seq"],
"skill": record["skill"],
"clear": record["clear"],
"fullcombo": record["fullcombo"],
"excellent": record["excellent"],
"perc": record["perc"],
"rank": record["rank"],
"meter": record["meter"],
"meter_prog": record["meter_prog"],
"sdata": 0,
}
if record["musicid"] not in records:
records[record["musicid"]] = {"order": len(records.keys()), "seq": {}}
records[record["musicid"]]["seq"][record["seq"]] = s
mlist = {}
for musicid in records:
data = {
"musicid": musicid,
"mdata": [-1] * 20,
"flag": [0] * 5,
"sdata": [-1] * 2,
"meter": [0] * 8,
"meter_prog": [-1] * 8,
}
for seq in records[musicid]["seq"]:
seqidx = int(seq)
data["mdata"][seqidx] = records[musicid]["seq"][seq]["perc"]
data["mdata"][8 + seqidx] = (
records[musicid]["seq"][seq]["rank"]
if records[musicid]["seq"][seq]["clear"] != 0
else -1
)
if records[musicid]["seq"][seq]["fullcombo"] != 0:
data["flag"][0] |= 1 << seqidx
if records[musicid]["seq"][seq]["excellent"] != 0:
data["flag"][1] |= 1 << seqidx
data["flag"][2] |= (
records[musicid]["seq"][seq]["clear"] << seqidx
) # Clear flag/count score towards profile stats
data["meter"][seqidx - 1] = records[musicid]["seq"][seq]["meter"]
data["meter_prog"][seqidx - 1] = records[musicid]["seq"][seq]["meter_prog"]
mlist[records[musicid]["order"]] = data
mlist = [mlist[x] for x in sorted(mlist.keys(), key=lambda x: int(x))]
if len(mlist) == 0:
mlist = [
{
"musicid": -1,
"mdata": [-1] * 20,
"flag": [0] * 5,
"sdata": [-1] * 2,
"meter": [0] * 8,
"meter_prog": [-1] * 8,
}
]
response = E.response(
E(
f"{ver}_gametop",
E.player(
E.now_date(round(time.time()), __type="u64"),
E.musiclist(
*[
E.musicdata(
E.mdata(m["mdata"], __type="s16"),
E.flag(m["flag"], __type="u16"),
E.sdata(m["sdata"], __type="s16"),
E.meter(m["meter"], __type="u64"),
E.meter_prog(m["meter_prog"], __type="s16"),
musicid=m["musicid"],
)
for m in mlist
],
nr=len(mlist),
),
E.secretmusic(
E.music(
E.musicid(1, __type="s32"),
E.seq(1, __type="u16"),
E.kind(1, __type="s32"),
)
),
E.chara_list(),
E.title_parts(),
E.information(
E.info(profile[g]["information"], __type="u32"),
),
E.reward(
E.status(profile[g]["reward"], __type="u32"),
),
E.rivaldata(),
E.frienddata(E.friend()),
E.thanks_medal(
E.medal(profile[g]["thanks_medal_medal"], __type="s32"),
E.grant_medal(0, __type="s32"),
E.grant_total_medal(
profile[g]["thanks_medal_granted_total_medal"], __type="s32"
),
),
E.skindata(
E.skin([0xFFFFFFFF] * 100, __type="u32"),
),
E.battledata(
E.info(
E.orb(0, __type="s32"),
E.get_gb_point(0, __type="s32"),
E.send_gb_point(0, __type="s32"),
),
E.greeting(
E.greeting_1("", __type="str"),
E.greeting_2("", __type="str"),
E.greeting_3("", __type="str"),
E.greeting_4("", __type="str"),
E.greeting_5("", __type="str"),
E.greeting_6("", __type="str"),
E.greeting_7("", __type="str"),
E.greeting_8("", __type="str"),
E.greeting_9("", __type="str"),
),
E.setting(
E.matching(0, __type="s32"),
E.info_level(0, __type="s32"),
),
E.score(
E.battle_class(0, __type="s32"),
E.max_battle_class(0, __type="s32"),
E.battle_point(0, __type="s32"),
E.win(0, __type="s32"),
E.lose(0, __type="s32"),
E.draw(0, __type="s32"),
E.consecutive_win(0, __type="s32"),
E.max_consecutive_win(0, __type="s32"),
E.glorious_win(0, __type="s32"),
E.max_defeat_skill(0, __type="s32"),
E.latest_result(0, __type="s32"),
),
E.history(),
),
E.is_free_ok(0, __type="bool"),
E.ranking(
E.skill(
E.rank(1, __type="s32"),
E.total_nr(1, __type="s32"),
),
E.all_skill(
E.rank(1, __type="s32"),
E.total_nr(1, __type="s32"),
),
),
E.stage_result(),
E.monthly_skill(),
E.event_skill(
E.skill(1, __type="s32"),
E.ranking(
E.rank(1, __type="s32"),
E.total_nr(1, __type="s32"),
),
E.eventlist(),
),
E.event_score(E.event_list()),
E.rockwave(E.score_list()),
E.jubeat_omiyage_challenge(),
E.light_mode_reward_item(
E.itemid(-1, __type="s32"),
E.rarity(0, __type="s32"),
),
E.standard_mode_reward_item(
E.itemid(-1, __type="s32"),
E.rarity(0, __type="s32"),
),
E.delux_mode_reward_item(
E.itemid(-1, __type="s32"),
E.rarity(0, __type="s32"),
),
E.kac2018(
E.entry_status(0, __type="s32"),
E.data(
E.term(0, __type="s32"),
E.total_score(0, __type="s32"),
E.score([0] * 6, __type="s32"),
E.music_type([0] * 6, __type="s32"),
E.play_count([0] * 6, __type="s32"),
),
),
E.sticker_campaign(),
E.kac2017(
E.entry_status(0, __type="s32"),
),
E.nostalgia_concert(),
E.bemani_summer_2018(
E.linkage_id(-1, __type="s32"),
E.is_entry(0, __type="bool"),
E.target_music_idx(-1, __type="s32"),
E.point_1(0, __type="s32"),
E.point_2(0, __type="s32"),
E.point_3(0, __type="s32"),
E.point_4(0, __type="s32"),
E.point_5(0, __type="s32"),
E.point_6(0, __type="s32"),
E.point_7(0, __type="s32"),
E.reward_1(0, __type="bool"),
E.reward_2(0, __type="bool"),
E.reward_3(0, __type="bool"),
E.reward_4(0, __type="bool"),
E.reward_5(0, __type="bool"),
E.reward_6(0, __type="bool"),
E.reward_7(0, __type="bool"),
E.unlock_status_1(0, __type="s32"),
E.unlock_status_2(0, __type="s32"),
E.unlock_status_3(0, __type="s32"),
E.unlock_status_4(0, __type="s32"),
E.unlock_status_5(0, __type="s32"),
E.unlock_status_6(0, __type="s32"),
E.unlock_status_7(0, __type="s32"),
),
E.thanksgiving(
E.term(0, __type="u8"),
E.score(
E.one_day_play_cnt(0, __type="s32"),
E.one_day_lottery_cnt(0, __type="s32"),
E.lucky_star(0, __type="s32"),
E.bear_mark(0, __type="s32"),
E.play_date_ms(0, __type="u64"),
),
E.lottery_result(
E.unlock_bit(0, __type="u64"),
),
),
E.lotterybox(),
E.long_otobear_fes_1(
E.point(0, __type="s32"),
),
E.phrase_combo_challenge(
E.point(0, __type="s32"),
),
*[
E(f"phrase_combo_challenge_{x}", E.point(0, __type="s32"))
for x in range(2, 21)
],
E.bear_fes(
*[
E(
f"bear_fes_{x}",
E.stage(0, __type="s32"),
E.point([0] * 8, __type="s32"),
)
for x in range(1, 5)
],
),
E.monstar_subjugation(
*[
E(
f"monstar_subjugation_{x}",
E.stage(0, __type="s32"),
E.point_1(0, __type="s32"),
E.point_2(0, __type="s32"),
E.point_3(0, __type="s32"),
)
for x in range(1, 4)
],
),
*[
E(f"kouyou_challenge_{x}", E.point(0, __type="s32"))
for x in range(1, 4)
],
E.sdvx_stamprally3(
E.point(0, __type="s32"),
),
E.chronicle_1(
E.point(0, __type="s32"),
),
E.playerboard(
E.index(1, __type="s32"),
E.is_active(1, __type="bool"),
E.sticker(
E.id(479, __type="s32"),
E.pos_x(160, __type="float"),
E.pos_y(235, __type="float"),
E.scale_x(1, __type="float"),
E.scale_y(1, __type="float"),
E.rotate(0, __type="float"),
),
E.sticker(
E.id(172, __type="s32"),
E.pos_x(160, __type="float"),
E.pos_y(235, __type="float"),
E.scale_x(1, __type="float"),
E.scale_y(1, __type="float"),
E.rotate(0, __type="float"),
),
E.sticker(
E.id(379, __type="s32"),
E.pos_x(175, __type="float"),
E.pos_y(175, __type="float"),
E.scale_x(0.4, __type="float"),
E.scale_y(0.4, __type="float"),
E.rotate(5, __type="float"),
),
E.sticker(
E.id(172, __type="s32"),
E.pos_x(175, __type="float"),
E.pos_y(265, __type="float"),
E.scale_x(1, __type="float"),
E.scale_y(1, __type="float"),
E.rotate(0, __type="float"),
),
E.sticker(
E.id(179, __type="s32"),
E.pos_x(69, __type="float"),
E.pos_y(420, __type="float"),
E.scale_x(1, __type="float"),
E.scale_y(1, __type="float"),
E.rotate(0, __type="float"),
),
),
E.player_info(
E.player_type(1, __type="s8"),
E.did(1, __type="s32"),
E.name(profile["name"], __type="str"),
E.title(profile["title"], __type="str"),
E.charaid(profile["charaid"], __type="s32"),
),
E.customdata(
E.playstyle(profile[g]["customdata_playstyle"], __type="s32"),
E.custom(profile[g]["customdata_custom"], __type="s32"),
),
E.playinfo(
E.cabid(profile[g]["playinfo_cabid"], __type="s32"),
E.play(profile[g]["playinfo_play"], __type="s32"),
E.playtime(profile[g]["playinfo_playtime"], __type="s32"),
E.playterm(profile[g]["playinfo_playterm"], __type="s32"),
E.session_cnt(profile[g]["playinfo_session_cnt"], __type="s32"),
E.matching_num(profile[g]["playinfo_matching_num"], __type="s32"),
E.extra_stage(profile[g]["playinfo_extra_stage"], __type="s32"),
E.extra_play(profile[g]["playinfo_extra_play"], __type="s32"),
E.extra_clear(profile[g]["playinfo_extra_clear"], __type="s32"),
E.encore_play(profile[g]["playinfo_encore_play"], __type="s32"),
E.encore_clear(profile[g]["playinfo_encore_clear"], __type="s32"),
E.pencore_play(profile[g]["playinfo_pencore_play"], __type="s32"),
E.pencore_clear(profile[g]["playinfo_pencore_clear"], __type="s32"),
E.max_clear_diff(
profile[g]["playinfo_max_clear_diff"], __type="s32"
),
E.max_full_diff(profile[g]["playinfo_max_full_diff"], __type="s32"),
E.max_exce_diff(profile[g]["playinfo_max_exce_diff"], __type="s32"),
E.clear_num(profile[g]["playinfo_clear_num"], __type="s32"),
E.full_num(profile[g]["playinfo_full_num"], __type="s32"),
E.exce_num(profile[g]["playinfo_exce_num"], __type="s32"),
E.no_num(profile[g]["playinfo_no_num"], __type="s32"),
E.e_num(profile[g]["playinfo_e_num"], __type="s32"),
E.d_num(profile[g]["playinfo_d_num"], __type="s32"),
E.c_num(profile[g]["playinfo_c_num"], __type="s32"),
E.b_num(profile[g]["playinfo_b_num"], __type="s32"),
E.a_num(profile[g]["playinfo_a_num"], __type="s32"),
E.s_num(profile[g]["playinfo_s_num"], __type="s32"),
E.ss_num(profile[g]["playinfo_ss_num"], __type="s32"),
E.last_category(profile[g]["playinfo_last_category"], __type="s32"),
E.last_musicid(profile[g]["playinfo_last_musicid"], __type="s32"),
E.last_seq(profile[g]["playinfo_last_seq"], __type="s32"),
E.disp_level(profile[g]["playinfo_disp_level"], __type="s32"),
),
E.tutorial(
E.progress(profile[g]["tutorial_progress"], __type="s32"),
E.disp_state(profile[g]["tutorial_disp_state"], __type="u32"),
),
E.skilldata(
E.skill(profile[g]["skilldata_skill"], __type="s32"),
E.all_skill(profile[g]["skilldata_allskill"], __type="s32"),
E.old_skill(profile[g]["skilldata_skill"], __type="s32"),
E.old_all_skill(profile[g]["skilldata_allskill"], __type="s32"),
),
E.favoritemusic(
E.list_1(profile[g]["favorite_music_list_1"], __type="s32"),
E.list_2(profile[g]["favorite_music_list_2"], __type="s32"),
E.list_3(profile[g]["favorite_music_list_3"], __type="s32"),
),
E.recommend_musicid_list(
profile[g]["recommend_musicid_list"], __type="s32"
),
E.record(
*[
E(
"gf" if g == "guitarfreaks" else "dm",
E.max_record(
E.skill(profile[g]["record_max_skill"], __type="s32"),
E.all_skill(
profile[g]["record_max_all_skill"], __type="s32"
),
E.clear_diff(
profile[g]["record_max_clear_diff"], __type="s32"
),
E.full_diff(
profile[g]["record_max_full_diff"], __type="s32"
),
E.exce_diff(
profile[g]["record_max_exce_diff"], __type="s32"
),
E.clear_music_num(
profile[g]["record_max_clear_music_num"],
__type="s32",
),
E.full_music_num(
profile[g]["record_max_full_music_num"],
__type="s32",
),
E.exce_music_num(
profile[g]["record_max_exce_music_num"],
__type="s32",
),
E.clear_seq_num(
profile[g]["record_max_clear_seq_num"], __type="s32"
),
E.classic_all_skill(
profile[g]["record_max_classic_all_skill"],
__type="s32",
),
),
E.diff_record(
E.diff_100_nr(
profile[g]["record_diff_100_nr"], __type="s32"
),
E.diff_150_nr(
profile[g]["record_diff_150_nr"], __type="s32"
),
E.diff_200_nr(
profile[g]["record_diff_200_nr"], __type="s32"
),
E.diff_250_nr(
profile[g]["record_diff_250_nr"], __type="s32"
),
E.diff_300_nr(
profile[g]["record_diff_300_nr"], __type="s32"
),
E.diff_350_nr(
profile[g]["record_diff_350_nr"], __type="s32"
),
E.diff_400_nr(
profile[g]["record_diff_400_nr"], __type="s32"
),
E.diff_450_nr(
profile[g]["record_diff_450_nr"], __type="s32"
),
E.diff_500_nr(
profile[g]["record_diff_500_nr"], __type="s32"
),
E.diff_550_nr(
profile[g]["record_diff_550_nr"], __type="s32"
),
E.diff_600_nr(
profile[g]["record_diff_600_nr"], __type="s32"
),
E.diff_650_nr(
profile[g]["record_diff_650_nr"], __type="s32"
),
E.diff_700_nr(
profile[g]["record_diff_700_nr"], __type="s32"
),
E.diff_750_nr(
profile[g]["record_diff_750_nr"], __type="s32"
),
E.diff_800_nr(
profile[g]["record_diff_800_nr"], __type="s32"
),
E.diff_850_nr(
profile[g]["record_diff_850_nr"], __type="s32"
),
E.diff_900_nr(
profile[g]["record_diff_900_nr"], __type="s32"
),
E.diff_950_nr(
profile[g]["record_diff_950_nr"], __type="s32"
),
E.diff_100_clear(
profile[g]["record_diff_100_clear"], __type="s32"
),
E.diff_150_clear(
profile[g]["record_diff_150_clear"], __type="s32"
),
E.diff_200_clear(
profile[g]["record_diff_200_clear"], __type="s32"
),
E.diff_250_clear(
profile[g]["record_diff_250_clear"], __type="s32"
),
E.diff_300_clear(
profile[g]["record_diff_300_clear"], __type="s32"
),
E.diff_350_clear(
profile[g]["record_diff_350_clear"], __type="s32"
),
E.diff_400_clear(
profile[g]["record_diff_400_clear"], __type="s32"
),
E.diff_450_clear(
profile[g]["record_diff_450_clear"], __type="s32"
),
E.diff_500_clear(
profile[g]["record_diff_500_clear"], __type="s32"
),
E.diff_550_clear(
profile[g]["record_diff_550_clear"], __type="s32"
),
E.diff_600_clear(
profile[g]["record_diff_600_clear"], __type="s32"
),
E.diff_650_clear(
profile[g]["record_diff_650_clear"], __type="s32"
),
E.diff_700_clear(
profile[g]["record_diff_700_clear"], __type="s32"
),
E.diff_750_clear(
profile[g]["record_diff_750_clear"], __type="s32"
),
E.diff_800_clear(
profile[g]["record_diff_800_clear"], __type="s32"
),
E.diff_850_clear(
profile[g]["record_diff_850_clear"], __type="s32"
),
E.diff_900_clear(
profile[g]["record_diff_900_clear"], __type="s32"
),
E.diff_950_clear(
profile[g]["record_diff_950_clear"], __type="s32"
),
),
)
for g in ["guitarfreaks", "drummania"]
],
),
E.groove(
E.extra_gauge(profile[g]["groove_extra_gauge"], __type="s32"),
E.encore_gauge(profile[g]["groove_encore_gauge"], __type="s32"),
E.encore_cnt(profile[g]["groove_encore_cnt"], __type="s32"),
E.encore_success(profile[g]["groove_encore_success"], __type="s32"),
E.unlock_point(profile[g]["groove_unlock_point"], __type="s32"),
),
E.finish(1, __type="bool"),
no=no,
),
)
)
response_body, response_headers = await core_prepare_response(request, response)
return Response(content=response_body, headers=response_headers)

View File

@ -0,0 +1,122 @@
import lxml.etree as ET
from os import path
from fastapi import APIRouter, Request, Response
from core_common import core_process_request, core_prepare_response, E
router = APIRouter(prefix="/local", tags=["local"])
router.model_whitelist = ["M32"]
@router.post("/{gameinfo}/{ver}_playablemusic/get")
async def gitadora_playablemusic_get(ver: str, request: Request):
request_info = await core_process_request(request)
# the game freezes if response has no songs
# so make sure there is at least one
# in case mdb isn't supplied
songs = {
0: {
"xg_diff_list": [
"0",
"100",
"295",
"395",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"160",
"490",
"585",
"0",
],
"contain_stat": ["2", "2"],
"data_ver": 115,
}
}
if ver == "fuzzup":
short_ver = "fz"
elif ver == "highvoltage":
short_ver = "hv"
elif ver == "nextage":
short_ver = "nt"
elif ver == "exchain":
short_ver = "ex"
elif ver == "matixx":
short_ver = "mt"
if not short_ver:
short_ver = "MISSING_FALLBACK"
for f in (
path.join("modules", "gitadora", f"mdb_{short_ver}.xml"),
path.join(f"mdb_{short_ver}.xml"),
):
if path.exists(f):
with open(f, "r", encoding="utf-8") as fp:
tree = ET.parse(fp, ET.XMLParser())
root = tree.getroot()
for entry in root:
if entry.tag == "mdb_data":
lvl = entry.find("xg_diff_list").text.split(" ")
if short_ver in ("fz", "hv", "nt", "ex"):
d_ver = int(entry.find("data_ver").text)
else:
d_ver = 115
mid = entry.find("music_id").text
songs[mid] = {}
songs[mid]["xg_diff_list"] = lvl[:5] + lvl[10:] + lvl[5:10]
songs[mid]["contain_stat"] = entry.find(
"contain_stat"
).text.split(" ")
songs[mid]["data_ver"] = d_ver
break
response = E.response(
E(
f"{ver}_playablemusic",
E.hot(
E.major(-1, __type="s32"),
E.minor(-1, __type="s32"),
),
E.musicinfo(
*[
E.music(
E.id(s, __type="s32"),
E.cont_gf(
1 if int(songs[s]["contain_stat"][0]) != 0 else 0,
__type="bool",
),
E.cont_dm(
1 if int(songs[s]["contain_stat"][1]) != 0 else 0,
__type="bool",
),
E.is_secret(0, __type="bool"),
E.is_hot(
1
if (int(songs[s]["contain_stat"][0]) & 1)
or (int(songs[s]["contain_stat"][1]) & 1)
else 0,
__type="bool",
),
E.data_ver(songs[s]["data_ver"], __type="s32"),
E.diff(songs[s]["xg_diff_list"], __type="u16"),
)
for s in songs
],
nr=len(songs),
),
)
)
response_body, response_headers = await core_prepare_response(request, response)
return Response(content=response_body, headers=response_headers)

View File

@ -0,0 +1,31 @@
from fastapi import APIRouter, Request, Response
from core_common import core_process_request, core_prepare_response, E
router = APIRouter(prefix="/local", tags=["local"])
router.model_whitelist = ["M32"]
@router.post("/{gameinfo}/{ver}_shopinfo/regist")
async def gitadora_shopinfo_regist(ver: str, request: Request):
request_info = await core_process_request(request)
response = E.response(
E(
f"{ver}_shopinfo",
E.data(
E.cabid(1, __type="u32"),
E.locationid("EA000001", __type="str"),
E.is_send(0, __type="u8"),
),
E.temperature(
E.is_send(0, __type="bool"),
),
E.tax(
E.tax_phase(1, __type="s32"),
),
)
)
response_body, response_headers = await core_prepare_response(request, response)
return Response(content=response_body, headers=response_headers)