mirror of
https://github.com/DragonMinded/bemaniutils.git
synced 2026-09-29 10:27:56 +03:00
954 lines
40 KiB
Python
954 lines
40 KiB
Python
import random
|
|
import time
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from bemani.client.base import BaseClient
|
|
from bemani.protocol import Node
|
|
|
|
|
|
class DDRX3Client(BaseClient):
|
|
NAME = "TEST"
|
|
|
|
def verify_cardmng_getkeepspan(self) -> None:
|
|
call = self.call_node()
|
|
|
|
# Calculate model node
|
|
model = ":".join(self.config["model"].split(":")[:4])
|
|
|
|
# Construct node
|
|
cardmng = Node.void("cardmng")
|
|
cardmng.set_attribute("method", "getkeepspan")
|
|
cardmng.set_attribute("model", model)
|
|
call.add_child(cardmng)
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/cardmng/@keepspan")
|
|
|
|
def verify_game_shop(self, loc: str) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "shop")
|
|
game.set_attribute("area", "51")
|
|
game.set_attribute("boot", "34")
|
|
game.set_attribute("close", "0")
|
|
game.set_attribute("close_t", "0")
|
|
game.set_attribute("coin", "02.01.--.--.01.G")
|
|
game.set_attribute("diff", "3")
|
|
game.set_attribute("during", "1")
|
|
game.set_attribute("first", "1")
|
|
game.set_attribute("ip", "1.5.7.3")
|
|
game.set_attribute("is_paseli", "1")
|
|
game.set_attribute("loc", loc)
|
|
game.set_attribute("mac", "00:11:22:33:44:55")
|
|
game.set_attribute("machine", "2")
|
|
game.set_attribute("name", "TEST")
|
|
game.set_attribute("pay", "0")
|
|
game.set_attribute("region", ".")
|
|
game.set_attribute("soft", self.config["model"])
|
|
game.set_attribute("softid", self.pcbid)
|
|
game.set_attribute("stage", "1")
|
|
game.set_attribute("time", "60")
|
|
game.set_attribute("type", "0")
|
|
game.set_attribute("ver", "2012092400")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game/@stop")
|
|
|
|
def verify_game_common(self) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "common")
|
|
game.set_attribute("ver", "2012092400")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game/flag/@id")
|
|
self.assert_path(resp, "response/game/flag/@s1")
|
|
self.assert_path(resp, "response/game/flag/@s2")
|
|
self.assert_path(resp, "response/game/flag/@t")
|
|
self.assert_path(resp, "response/game/cnt_music")
|
|
|
|
def verify_game_hiscore(self) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "hiscore")
|
|
game.set_attribute("ver", "2012092400")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
for child in resp.child("game").children:
|
|
self.assert_path(child, "music/@reclink_num")
|
|
self.assert_path(child, "music/type/@diff")
|
|
self.assert_path(child, "music/type/name")
|
|
self.assert_path(child, "music/type/score")
|
|
self.assert_path(child, "music/type/area")
|
|
self.assert_path(child, "music/type/rank")
|
|
self.assert_path(child, "music/type/combo_type")
|
|
self.assert_path(child, "music/type/code")
|
|
|
|
def verify_game_area_hiscore(self) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "area_hiscore")
|
|
game.set_attribute("shop_area", "51")
|
|
game.set_attribute("ver", "2012092400")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
for child in resp.child("game").children:
|
|
self.assert_path(child, "music/@reclink_num")
|
|
self.assert_path(child, "music/type/@diff")
|
|
self.assert_path(child, "music/type/name")
|
|
self.assert_path(child, "music/type/score")
|
|
self.assert_path(child, "music/type/area")
|
|
self.assert_path(child, "music/type/rank")
|
|
self.assert_path(child, "music/type/combo_type")
|
|
self.assert_path(child, "music/type/code")
|
|
|
|
def verify_game_message(self) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "message")
|
|
game.set_attribute("ver", "2012092400")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
|
|
def verify_game_ranking(self) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "ranking")
|
|
game.set_attribute("max", "10")
|
|
game.set_attribute("ver", "2012092400")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
|
|
def verify_game_log(self) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "log")
|
|
game.set_attribute("type", "0")
|
|
game.set_attribute("soft", self.config["model"])
|
|
game.set_attribute("softid", self.pcbid)
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("boot", "34")
|
|
game.set_attribute("mac", "00:11:22:33:44:55")
|
|
clear = Node.void("clear")
|
|
game.add_child(clear)
|
|
clear.set_attribute("book", "0")
|
|
clear.set_attribute("edit", "0")
|
|
clear.set_attribute("rank", "0")
|
|
clear.set_attribute("set", "0")
|
|
auto = Node.void("auto")
|
|
game.add_child(auto)
|
|
auto.set_attribute("book", "1")
|
|
auto.set_attribute("edit", "1")
|
|
auto.set_attribute("rank", "1")
|
|
auto.set_attribute("set", "1")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
|
|
def verify_game_lock(self, ref_id: str, play: int) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("refid", ref_id)
|
|
game.set_attribute("method", "lock")
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("play", str(play))
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game/@now_login")
|
|
|
|
def verify_game_new(self, ref_id: str) -> None:
|
|
# Pad the name to 8 characters
|
|
name = self.NAME[:8]
|
|
while len(name) < 8:
|
|
name = name + " "
|
|
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "new")
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("name", name)
|
|
game.set_attribute("area", "51")
|
|
game.set_attribute("old", "0")
|
|
game.set_attribute("refid", ref_id)
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
|
|
def verify_game_load_daily(self, ref_id: str) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "load_daily")
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("refid", ref_id)
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
self.assert_path(resp, "response/game/daycount/@playcount")
|
|
self.assert_path(resp, "response/game/dailycombo/@daily_combo")
|
|
self.assert_path(resp, "response/game/dailycombo/@daily_combo_lv")
|
|
|
|
def verify_game_load(self, ref_id: str, msg_type: str) -> Dict[str, Any]:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "load")
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("refid", ref_id)
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
if msg_type == "new":
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game/@none")
|
|
return {}
|
|
if msg_type == "existing":
|
|
# Verify existing profile and return info
|
|
self.assert_path(resp, "response/game/seq")
|
|
self.assert_path(resp, "response/game/code")
|
|
self.assert_path(resp, "response/game/name")
|
|
self.assert_path(resp, "response/game/area")
|
|
self.assert_path(resp, "response/game/cnt_s")
|
|
self.assert_path(resp, "response/game/cnt_d")
|
|
self.assert_path(resp, "response/game/cnt_b")
|
|
self.assert_path(resp, "response/game/cnt_m0")
|
|
self.assert_path(resp, "response/game/cnt_m1")
|
|
self.assert_path(resp, "response/game/cnt_m2")
|
|
self.assert_path(resp, "response/game/cnt_m3")
|
|
self.assert_path(resp, "response/game/cnt_m4")
|
|
self.assert_path(resp, "response/game/cnt_m5")
|
|
self.assert_path(resp, "response/game/exp")
|
|
self.assert_path(resp, "response/game/exp_o")
|
|
self.assert_path(resp, "response/game/star")
|
|
self.assert_path(resp, "response/game/star_c")
|
|
self.assert_path(resp, "response/game/combo")
|
|
self.assert_path(resp, "response/game/timing_diff")
|
|
self.assert_path(resp, "response/game/chara")
|
|
self.assert_path(resp, "response/game/chara_opt")
|
|
self.assert_path(resp, "response/game/daycount/@playcount")
|
|
self.assert_path(resp, "response/game/dailycombo/@daily_combo")
|
|
self.assert_path(resp, "response/game/dailycombo/@daily_combo_lv")
|
|
self.assert_path(resp, "response/game/last/@cate")
|
|
self.assert_path(resp, "response/game/last/@cid")
|
|
self.assert_path(resp, "response/game/last/@ctype")
|
|
self.assert_path(resp, "response/game/last/@fri")
|
|
self.assert_path(resp, "response/game/last/@mid")
|
|
self.assert_path(resp, "response/game/last/@mode")
|
|
self.assert_path(resp, "response/game/last/@mtype")
|
|
self.assert_path(resp, "response/game/last/@rival1")
|
|
self.assert_path(resp, "response/game/last/@rival2")
|
|
self.assert_path(resp, "response/game/last/@rival3")
|
|
self.assert_path(resp, "response/game/last/@sid")
|
|
self.assert_path(resp, "response/game/last/@sort")
|
|
self.assert_path(resp, "response/game/last/@style")
|
|
self.assert_path(resp, "response/game/result_star/@slot1")
|
|
self.assert_path(resp, "response/game/result_star/@slot2")
|
|
self.assert_path(resp, "response/game/result_star/@slot3")
|
|
self.assert_path(resp, "response/game/result_star/@slot4")
|
|
self.assert_path(resp, "response/game/result_star/@slot5")
|
|
self.assert_path(resp, "response/game/result_star/@slot6")
|
|
self.assert_path(resp, "response/game/result_star/@slot7")
|
|
self.assert_path(resp, "response/game/result_star/@slot8")
|
|
self.assert_path(resp, "response/game/result_star/@slot9")
|
|
self.assert_path(resp, "response/game/target/@flag")
|
|
self.assert_path(resp, "response/game/target/@setnum")
|
|
self.assert_path(resp, "response/game/gr_s/@gr1")
|
|
self.assert_path(resp, "response/game/gr_s/@gr2")
|
|
self.assert_path(resp, "response/game/gr_s/@gr3")
|
|
self.assert_path(resp, "response/game/gr_s/@gr4")
|
|
self.assert_path(resp, "response/game/gr_s/@gr5")
|
|
self.assert_path(resp, "response/game/gr_d/@gr1")
|
|
self.assert_path(resp, "response/game/gr_d/@gr2")
|
|
self.assert_path(resp, "response/game/gr_d/@gr3")
|
|
self.assert_path(resp, "response/game/gr_d/@gr4")
|
|
self.assert_path(resp, "response/game/gr_d/@gr5")
|
|
self.assert_path(resp, "response/game/opt")
|
|
self.assert_path(resp, "response/game/opt_ex")
|
|
self.assert_path(resp, "response/game/flag")
|
|
self.assert_path(resp, "response/game/rank")
|
|
for i in range(55):
|
|
self.assert_path(resp, f"response/game/play_area/@play_cnt{i}")
|
|
|
|
gr_s = resp.child("game/gr_s")
|
|
gr_d = resp.child("game/gr_d")
|
|
|
|
return {
|
|
"name": resp.child_value("game/name"),
|
|
"single_plays": resp.child_value("game/cnt_s"),
|
|
"double_plays": resp.child_value("game/cnt_d"),
|
|
"groove_single": [
|
|
int(gr_s.attribute("gr1")),
|
|
int(gr_s.attribute("gr2")),
|
|
int(gr_s.attribute("gr3")),
|
|
int(gr_s.attribute("gr4")),
|
|
int(gr_s.attribute("gr5")),
|
|
],
|
|
"groove_double": [
|
|
int(gr_d.attribute("gr1")),
|
|
int(gr_d.attribute("gr2")),
|
|
int(gr_d.attribute("gr3")),
|
|
int(gr_d.attribute("gr4")),
|
|
int(gr_d.attribute("gr5")),
|
|
],
|
|
}
|
|
|
|
raise Exception("Unknown load type!")
|
|
|
|
def verify_game_load_m(self, ref_id: str) -> Dict[int, Dict[int, Dict[str, Any]]]:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("all", "1")
|
|
game.set_attribute("refid", ref_id)
|
|
game.set_attribute("method", "load_m")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
scores: Dict[int, Dict[int, Dict[str, Any]]] = {}
|
|
self.assert_path(resp, "response/game")
|
|
for child in resp.child("game").children:
|
|
self.assert_path(child, "music/@reclink")
|
|
reclink = int(child.attribute("reclink"))
|
|
|
|
for typenode in child.children:
|
|
self.assert_path(typenode, "type/@diff")
|
|
self.assert_path(typenode, "type/score")
|
|
self.assert_path(typenode, "type/count")
|
|
self.assert_path(typenode, "type/rank")
|
|
self.assert_path(typenode, "type/combo_type")
|
|
self.assert_path(typenode, "type/score_2nd")
|
|
self.assert_path(typenode, "type/rank_2nd")
|
|
self.assert_path(typenode, "type/cnt_2nd")
|
|
chart = int(typenode.attribute("diff"))
|
|
vals = {
|
|
"score": typenode.child_value("score"),
|
|
"count": typenode.child_value("count"),
|
|
"rank": typenode.child_value("rank"),
|
|
"halo": typenode.child_value("combo_type"),
|
|
"score_2nd": typenode.child_value("score_2nd"),
|
|
"rank_2nd": typenode.child_value("rank_2nd"),
|
|
"cnt_2nd": typenode.child_value("cnt_2nd"),
|
|
}
|
|
if reclink not in scores:
|
|
scores[reclink] = {}
|
|
scores[reclink][chart] = vals
|
|
return scores
|
|
|
|
def verify_game_load_c(self, ref_id: str) -> Dict[int, Dict[int, Dict[str, Any]]]:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "load_c")
|
|
game.set_attribute("refid", ref_id)
|
|
game.set_attribute("ver", "2012092400")
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
courses: Dict[int, Dict[int, Dict[str, Any]]] = {}
|
|
self.assert_path(resp, "response/game/course")
|
|
courseblob = resp.child_value("game/course")
|
|
index = 0
|
|
for chunk in [courseblob[i : (i + 8)] for i in range(0, len(courseblob), 8)]:
|
|
if any([v != 0 for v in chunk]):
|
|
course = int(index / 4)
|
|
chart = index % 4
|
|
vals = {
|
|
"score": chunk[0] * 10000 + chunk[1],
|
|
"combo": chunk[2],
|
|
"rank": chunk[3],
|
|
"stage": chunk[5],
|
|
"combo_type": chunk[6],
|
|
}
|
|
if course not in courses:
|
|
courses[course] = {}
|
|
courses[course][chart] = vals
|
|
|
|
index = index + 1
|
|
return courses
|
|
|
|
def verify_game_save(
|
|
self, ref_id: str, style: int, gauge: Optional[List[int]] = None
|
|
) -> None:
|
|
gauge = gauge or [0, 0, 0, 0, 0]
|
|
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "save")
|
|
game.set_attribute("refid", ref_id)
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("shop_area", "51")
|
|
last = Node.void("last")
|
|
game.add_child(last)
|
|
last.set_attribute("mode", "1")
|
|
last.set_attribute("style", str(style))
|
|
gr = Node.void("gr")
|
|
game.add_child(gr)
|
|
gr.set_attribute("gr1", str(gauge[0]))
|
|
gr.set_attribute("gr2", str(gauge[1]))
|
|
gr.set_attribute("gr3", str(gauge[2]))
|
|
gr.set_attribute("gr4", str(gauge[3]))
|
|
gr.set_attribute("gr5", str(gauge[4]))
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
|
|
def verify_game_score(self, ref_id: str, songid: int, chart: int) -> List[int]:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("method", "score")
|
|
game.set_attribute("mid", str(songid))
|
|
game.set_attribute("refid", ref_id)
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("type", str(chart))
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game/@sc1")
|
|
self.assert_path(resp, "response/game/@sc2")
|
|
self.assert_path(resp, "response/game/@sc3")
|
|
self.assert_path(resp, "response/game/@sc4")
|
|
self.assert_path(resp, "response/game/@sc5")
|
|
return [
|
|
int(resp.child("game").attribute("sc1")),
|
|
int(resp.child("game").attribute("sc2")),
|
|
int(resp.child("game").attribute("sc3")),
|
|
int(resp.child("game").attribute("sc4")),
|
|
int(resp.child("game").attribute("sc5")),
|
|
]
|
|
|
|
def verify_game_save_m(self, ref_id: str, score: Dict[str, Any]) -> None:
|
|
if score["score"] == 0 and score["score_2nd"] == 0:
|
|
raise Exception("Must store either 2ndMIX or regular score!")
|
|
if score["score"] != 0 and score["score_2nd"] != 0:
|
|
raise Exception("Must store either 2ndMIX or regular score!")
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("refid", ref_id)
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("mtype", str(score["chart"]))
|
|
game.set_attribute("mid", str(score["id"]))
|
|
game.set_attribute("method", "save_m")
|
|
data = Node.void("data")
|
|
game.add_child(data)
|
|
data.set_attribute("perf", "1" if score["halo"] >= 2 else "0")
|
|
data.set_attribute("score", str(score["score"]))
|
|
data.set_attribute("rank", str(score["rank"]))
|
|
data.set_attribute("phase", "1")
|
|
data.set_attribute("full", "1" if score["halo"] >= 1 else "0")
|
|
data.set_attribute("combo", str(score["combo"]))
|
|
data.set_attribute("playmode", str(1 if score["score"] > 0 else 5))
|
|
data.set_attribute("rank_2nd", str(score["rank_2nd"]))
|
|
data.set_attribute("score_2nd", str(score["score_2nd"]))
|
|
data.set_attribute("combo_2nd", str(score["combo_2nd"]))
|
|
option = Node.void("option")
|
|
game.add_child(option)
|
|
option.set_attribute("opt0", "6")
|
|
option.set_attribute("opt6", "1")
|
|
game.add_child(Node.u8_array("trace", [0] * 512))
|
|
game.add_child(Node.u32("size", 512))
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
|
|
def verify_game_save_c(self, ref_id: str, course: Dict[str, Any]) -> None:
|
|
call = self.call_node()
|
|
game = Node.void("game")
|
|
call.add_child(game)
|
|
game.set_attribute("ctype", str(course["chart"]))
|
|
game.set_attribute("cid", str(course["id"]))
|
|
game.set_attribute("method", "save_c")
|
|
game.set_attribute("ver", "2012092400")
|
|
game.set_attribute("refid", ref_id)
|
|
data = Node.void("data")
|
|
game.add_child(data)
|
|
data.set_attribute("combo_type", str(course["combo_type"]))
|
|
data.set_attribute("clear", "1")
|
|
data.set_attribute("combo", str(course["combo"]))
|
|
data.set_attribute("opt", "32774")
|
|
data.set_attribute("per", "995")
|
|
data.set_attribute("score", str(course["score"]))
|
|
data.set_attribute("stage", str(course["stage"]))
|
|
data.set_attribute("rank", str(course["rank"]))
|
|
game.add_child(Node.u8_array("trace", [0] * 4096))
|
|
game.add_child(Node.u32("size", 4096))
|
|
|
|
# Swap with server
|
|
resp = self.exchange("", call)
|
|
|
|
# Verify that response is correct
|
|
self.assert_path(resp, "response/game")
|
|
|
|
def verify(self, cardid: Optional[str]) -> None:
|
|
# Verify boot sequence is okay
|
|
self.verify_services_get(
|
|
expected_services=[
|
|
"pcbtracker",
|
|
"pcbevent",
|
|
"local",
|
|
"message",
|
|
"facility",
|
|
"cardmng",
|
|
"package",
|
|
"posevent",
|
|
"pkglist",
|
|
"dlstatus",
|
|
"eacoin",
|
|
"lobby",
|
|
"ntp",
|
|
"keepalive",
|
|
]
|
|
)
|
|
paseli_enabled = self.verify_pcbtracker_alive()
|
|
self.verify_message_get()
|
|
self.verify_package_list()
|
|
location = self.verify_facility_get("EUC_JP")
|
|
self.verify_pcbevent_put()
|
|
self.verify_cardmng_getkeepspan()
|
|
self.verify_game_shop(location)
|
|
self.verify_game_common()
|
|
self.verify_game_hiscore()
|
|
self.verify_game_area_hiscore()
|
|
self.verify_game_message()
|
|
self.verify_game_ranking()
|
|
self.verify_game_log()
|
|
|
|
# Verify card registration and profile lookup
|
|
if cardid is not None:
|
|
card = cardid
|
|
else:
|
|
card = self.random_card()
|
|
print(f"Generated random card ID {card} for use.")
|
|
|
|
if cardid is None:
|
|
self.verify_cardmng_inquire(
|
|
card, msg_type="unregistered", paseli_enabled=paseli_enabled
|
|
)
|
|
ref_id = self.verify_cardmng_getrefid(card)
|
|
if len(ref_id) != 16:
|
|
raise Exception(
|
|
f"Invalid refid '{ref_id}' returned when registering card"
|
|
)
|
|
if ref_id != self.verify_cardmng_inquire(
|
|
card, msg_type="new", paseli_enabled=paseli_enabled
|
|
):
|
|
raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
|
|
# Bishi doesn't read a new profile, it just writes out CSV for a blank one
|
|
self.verify_game_load(ref_id, msg_type="new")
|
|
self.verify_game_new(ref_id)
|
|
else:
|
|
print("Skipping new card checks for existing card")
|
|
ref_id = self.verify_cardmng_inquire(
|
|
card, msg_type="query", paseli_enabled=paseli_enabled
|
|
)
|
|
|
|
# Verify pin handling and return card handling
|
|
self.verify_cardmng_authpass(ref_id, correct=True)
|
|
self.verify_cardmng_authpass(ref_id, correct=False)
|
|
if ref_id != self.verify_cardmng_inquire(
|
|
card, msg_type="query", paseli_enabled=paseli_enabled
|
|
):
|
|
raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
|
|
|
|
# Verify locking and unlocking profile ability
|
|
self.verify_game_lock(ref_id, 1)
|
|
self.verify_game_lock(ref_id, 0)
|
|
|
|
if cardid is None:
|
|
# Verify empty profile
|
|
profile = self.verify_game_load(ref_id, msg_type="existing")
|
|
if profile["name"] != self.NAME:
|
|
raise Exception("Profile has invalid name associated with it!")
|
|
if profile["single_plays"] != 0:
|
|
raise Exception("Profile has plays on single already!")
|
|
if profile["double_plays"] != 0:
|
|
raise Exception("Profile has plays on double already!")
|
|
if any([g != 0 for g in profile["groove_single"]]):
|
|
raise Exception("Profile has single groove gauge values already!")
|
|
if any([g != 0 for g in profile["groove_double"]]):
|
|
raise Exception("Profile has double groove gauge values already!")
|
|
|
|
# Verify empty scores
|
|
scores = self.verify_game_load_m(ref_id)
|
|
if len(scores) > 0:
|
|
raise Exception("Scores exist on new profile!")
|
|
|
|
# Verify empty courses
|
|
courses = self.verify_game_load_c(ref_id)
|
|
if len(courses) > 0:
|
|
raise Exception("Courses exist on new profile!")
|
|
|
|
self.verify_game_load_daily(ref_id)
|
|
|
|
# Verify profile saving
|
|
self.verify_game_save(ref_id, 0, [1, 2, 3, 4, 5])
|
|
profile = self.verify_game_load(ref_id, msg_type="existing")
|
|
if profile["name"] != self.NAME:
|
|
raise Exception("Profile has invalid name associated with it!")
|
|
if profile["single_plays"] != 1:
|
|
raise Exception("Profile has invalid plays on single!")
|
|
if profile["double_plays"] != 0:
|
|
raise Exception("Profile has invalid plays on double!")
|
|
if profile["groove_single"] != [1, 2, 3, 4, 5]:
|
|
raise Exception("Profile has invalid single groove gauge values!")
|
|
if any([g != 0 for g in profile["groove_double"]]):
|
|
raise Exception("Profile has invalid double groove gauge values!")
|
|
|
|
self.verify_game_save(ref_id, 1, [5, 4, 3, 2, 1])
|
|
profile = self.verify_game_load(ref_id, msg_type="existing")
|
|
if profile["name"] != self.NAME:
|
|
raise Exception("Profile has invalid name associated with it!")
|
|
if profile["single_plays"] != 1:
|
|
raise Exception("Profile has invalid plays on single!")
|
|
if profile["double_plays"] != 1:
|
|
raise Exception("Profile has invalid plays on double!")
|
|
if profile["groove_single"] != [1, 2, 3, 4, 5]:
|
|
raise Exception("Profile has invalid single groove gauge values!")
|
|
if profile["groove_double"] != [5, 4, 3, 2, 1]:
|
|
raise Exception("Profile has invalid double groove gauge values!")
|
|
|
|
# Now, write some scores and verify saving
|
|
for phase in [1, 2]:
|
|
if phase == 1:
|
|
dummyscores = [
|
|
# An okay score on a chart
|
|
{
|
|
"id": 524,
|
|
"chart": 3,
|
|
"score": 800000,
|
|
"combo": 123,
|
|
"rank": 4,
|
|
"halo": 1,
|
|
"score_2nd": 0,
|
|
"combo_2nd": 0,
|
|
"rank_2nd": 0,
|
|
},
|
|
# A good score on an easier chart same song
|
|
{
|
|
"id": 524,
|
|
"chart": 2,
|
|
"score": 990000,
|
|
"combo": 321,
|
|
"rank": 2,
|
|
"halo": 2,
|
|
"score_2nd": 0,
|
|
"combo_2nd": 0,
|
|
"rank_2nd": 0,
|
|
},
|
|
# A perfect score
|
|
{
|
|
"id": 483,
|
|
"chart": 3,
|
|
"score": 1000000,
|
|
"combo": 400,
|
|
"rank": 1,
|
|
"halo": 3,
|
|
"score_2nd": 0,
|
|
"combo_2nd": 0,
|
|
"rank_2nd": 0,
|
|
},
|
|
# A bad score
|
|
{
|
|
"id": 483,
|
|
"chart": 2,
|
|
"score": 100000,
|
|
"combo": 5,
|
|
"rank": 7,
|
|
"halo": 0,
|
|
"score_2nd": 0,
|
|
"combo_2nd": 0,
|
|
"rank_2nd": 0,
|
|
},
|
|
# A score on 2ndMIX
|
|
{
|
|
"id": 483,
|
|
"chart": 3,
|
|
"score": 0,
|
|
"combo": 0,
|
|
"rank": 0,
|
|
"halo": 0,
|
|
"score_2nd": 21608500,
|
|
"combo_2nd": 158,
|
|
"rank_2nd": 0,
|
|
},
|
|
]
|
|
if phase == 2:
|
|
dummyscores = [
|
|
# A better score on a chart
|
|
{
|
|
"id": 524,
|
|
"chart": 3,
|
|
"score": 850000,
|
|
"combo": 234,
|
|
"rank": 3,
|
|
"halo": 2,
|
|
"score_2nd": 0,
|
|
"combo_2nd": 0,
|
|
"rank_2nd": 0,
|
|
},
|
|
# A worse score on another chart
|
|
{
|
|
"id": 524,
|
|
"chart": 2,
|
|
"score": 980000,
|
|
"combo": 300,
|
|
"rank": 3,
|
|
"halo": 0,
|
|
"expected_score": 990000,
|
|
"expected_rank": 2,
|
|
"expected_halo": 2,
|
|
"score_2nd": 0,
|
|
"combo_2nd": 0,
|
|
"rank_2nd": 0,
|
|
},
|
|
# A worse score on 2ndMIX
|
|
{
|
|
"id": 483,
|
|
"chart": 3,
|
|
"score": 0,
|
|
"combo": 0,
|
|
"rank": 0,
|
|
"halo": 0,
|
|
"score_2nd": 11608500,
|
|
"combo_2nd": 125,
|
|
"rank_2nd": 1,
|
|
"expected_score_2nd": 21608500,
|
|
"expected_rank_2nd": 0,
|
|
},
|
|
]
|
|
|
|
# Verify empty scores for starters
|
|
if phase == 1:
|
|
for score in dummyscores:
|
|
last_five = self.verify_game_score(
|
|
ref_id, score["id"], score["chart"]
|
|
)
|
|
if any([s != 0 for s in last_five]):
|
|
raise Exception(
|
|
"Score already found on song not played yet!"
|
|
)
|
|
for score in dummyscores:
|
|
self.verify_game_save_m(ref_id, score)
|
|
scores = self.verify_game_load_m(ref_id)
|
|
for score in dummyscores:
|
|
data = scores.get(score["id"], {}).get(score["chart"], None)
|
|
if data is None:
|
|
raise Exception(
|
|
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
|
|
)
|
|
|
|
# Verify the attributes of the score
|
|
expected_score = score.get("expected_score", score["score"])
|
|
expected_rank = score.get("expected_rank", score["rank"])
|
|
expected_halo = score.get("expected_halo", score["halo"])
|
|
expected_score_2nd = score.get(
|
|
"expected_score_2nd", score["score_2nd"]
|
|
)
|
|
expected_rank_2nd = score.get(
|
|
"expected_rank_2nd", score["rank_2nd"]
|
|
)
|
|
|
|
if score["score"] != 0:
|
|
if data["score"] != expected_score:
|
|
raise Exception(
|
|
f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["score"]}\''
|
|
)
|
|
if data["rank"] != expected_rank:
|
|
raise Exception(
|
|
f'Expected a rank of \'{expected_rank}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got rank \'{data["rank"]}\''
|
|
)
|
|
if data["halo"] != expected_halo:
|
|
raise Exception(
|
|
f'Expected a halo of \'{expected_halo}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got halo \'{data["halo"]}\''
|
|
)
|
|
|
|
# Verify that the last score is our score
|
|
last_five = self.verify_game_score(
|
|
ref_id, score["id"], score["chart"]
|
|
)
|
|
if last_five[0] != score["score"]:
|
|
raise Exception(
|
|
f'Invalid score returned for last five scores on song {score["id"]} chart {score["chart"]}!'
|
|
)
|
|
if score["score_2nd"] != 0:
|
|
if data["score_2nd"] != expected_score_2nd:
|
|
raise Exception(
|
|
f'Expected a score_2nd of \'{expected_score_2nd}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score_2nd \'{data["score_2nd"]}\''
|
|
)
|
|
if data["rank_2nd"] != expected_rank_2nd:
|
|
raise Exception(
|
|
f'Expected a rank_2nd of \'{expected_rank_2nd}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got rank_2nd \'{data["rank_2nd"]}\''
|
|
)
|
|
|
|
# Sleep so we don't end up putting in score history on the same second
|
|
time.sleep(1)
|
|
|
|
# Now, write some courses and verify saving
|
|
for phase in [1, 2]:
|
|
if phase == 1:
|
|
dummycourses = [
|
|
# An okay score on a course
|
|
{
|
|
"id": 5,
|
|
"chart": 3,
|
|
"score": 800000,
|
|
"combo": 123,
|
|
"rank": 4,
|
|
"stage": 5,
|
|
"combo_type": 1,
|
|
},
|
|
# A good score on a different coruse
|
|
{
|
|
"id": 7,
|
|
"chart": 2,
|
|
"score": 600000,
|
|
"combo": 23,
|
|
"rank": 5,
|
|
"stage": 5,
|
|
"combo_type": 0,
|
|
},
|
|
]
|
|
if phase == 2:
|
|
dummycourses = [
|
|
# A better score on the same course
|
|
{
|
|
"id": 5,
|
|
"chart": 3,
|
|
"score": 900000,
|
|
"combo": 234,
|
|
"rank": 3,
|
|
"stage": 5,
|
|
"combo_type": 1,
|
|
},
|
|
# A worse score on a different same course
|
|
{
|
|
"id": 7,
|
|
"chart": 2,
|
|
"score": 500000,
|
|
"combo": 12,
|
|
"rank": 7,
|
|
"stage": 4,
|
|
"combo_type": 0,
|
|
"expected_score": 600000,
|
|
"expected_combo": 23,
|
|
"expected_rank": 5,
|
|
"expected_stage": 5,
|
|
},
|
|
]
|
|
|
|
for course in dummycourses:
|
|
self.verify_game_save_c(ref_id, course)
|
|
courses = self.verify_game_load_c(ref_id)
|
|
for course in dummycourses:
|
|
data = courses.get(course["id"], {}).get(course["chart"], None)
|
|
if data is None:
|
|
raise Exception(
|
|
f'Expected to get course back for course {course["id"]} chart {course["chart"]}!'
|
|
)
|
|
|
|
expected_score = course.get("expected_score", course["score"])
|
|
expected_combo = course.get("expected_combo", course["combo"])
|
|
expected_rank = course.get("expected_rank", course["rank"])
|
|
expected_stage = course.get("expected_stage", course["stage"])
|
|
expected_combo_type = course.get(
|
|
"expected_combo_type", course["combo_type"]
|
|
)
|
|
|
|
if data["score"] != expected_score:
|
|
raise Exception(
|
|
f'Expected a score of \'{expected_score}\' for course \'{course["id"]}\' chart \'{course["chart"]}\' but got score \'{data["score"]}\''
|
|
)
|
|
if data["combo"] != expected_combo:
|
|
raise Exception(
|
|
f'Expected a combo of \'{expected_combo}\' for course \'{course["id"]}\' chart \'{course["chart"]}\' but got combo \'{data["combo"]}\''
|
|
)
|
|
if data["rank"] != expected_rank:
|
|
raise Exception(
|
|
f'Expected a rank of \'{expected_rank}\' for course \'{course["id"]}\' chart \'{course["chart"]}\' but got rank \'{data["rank"]}\''
|
|
)
|
|
if data["stage"] != expected_stage:
|
|
raise Exception(
|
|
f'Expected a stage of \'{expected_stage}\' for course \'{course["id"]}\' chart \'{course["chart"]}\' but got stage \'{data["stage"]}\''
|
|
)
|
|
if data["combo_type"] != expected_combo_type:
|
|
raise Exception(
|
|
f'Expected a combo_type of \'{expected_combo_type}\' for course \'{course["id"]}\' chart \'{course["chart"]}\' but got combo_type \'{data["combo_type"]}\''
|
|
)
|
|
|
|
# Sleep so we don't end up putting in score history on the same second
|
|
time.sleep(1)
|
|
else:
|
|
print("Skipping score checks for existing card")
|
|
|
|
# Verify paseli handling
|
|
if paseli_enabled:
|
|
print("PASELI enabled for this PCBID, executing PASELI checks")
|
|
else:
|
|
print("PASELI disabled for this PCBID, skipping PASELI checks")
|
|
return
|
|
|
|
sessid, balance = self.verify_eacoin_checkin(card)
|
|
if balance == 0:
|
|
print("Skipping PASELI consume check because card has 0 balance")
|
|
else:
|
|
self.verify_eacoin_consume(sessid, balance, random.randint(0, balance))
|
|
self.verify_eacoin_checkout(sessid)
|