2019-12-08 22:43:49 +01:00
|
|
|
|
import random
|
|
|
|
|
import time
|
|
|
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
|
|
|
|
|
|
from bemani.client.base import BaseClient
|
|
|
|
|
from bemani.protocol import Node
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DDR2014Client(BaseClient):
|
|
|
|
|
NAME = 'TEST'
|
|
|
|
|
|
|
|
|
|
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('edit_cnt', '0')
|
|
|
|
|
game.set_attribute('edit_used', '1')
|
|
|
|
|
game.set_attribute('first', '1')
|
|
|
|
|
game.set_attribute('ip', '1.5.7.3')
|
|
|
|
|
game.set_attribute('is_freefirstplay', '1')
|
|
|
|
|
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', '2014102700')
|
|
|
|
|
|
|
|
|
|
# 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', '2014102700')
|
|
|
|
|
|
|
|
|
|
# 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_monthly")
|
|
|
|
|
self.assert_path(resp, "response/game/cnt_music_weekly")
|
|
|
|
|
self.assert_path(resp, "response/game/cnt_music_daily")
|
|
|
|
|
|
|
|
|
|
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', '2014102700')
|
|
|
|
|
|
|
|
|
|
# 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', '2014102700')
|
|
|
|
|
|
|
|
|
|
# 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', '2014102700')
|
|
|
|
|
|
|
|
|
|
# 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', '2014102700')
|
|
|
|
|
|
|
|
|
|
# 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', '2014102700')
|
|
|
|
|
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_tax_info(self) -> None:
|
|
|
|
|
call = self.call_node()
|
|
|
|
|
game = Node.void('game')
|
|
|
|
|
call.add_child(game)
|
|
|
|
|
game.set_attribute('method', 'tax_info')
|
|
|
|
|
game.set_attribute('ver', '2014102700')
|
|
|
|
|
|
|
|
|
|
# Swap with server
|
|
|
|
|
resp = self.exchange('', call)
|
|
|
|
|
|
|
|
|
|
# Verify that response is correct
|
|
|
|
|
self.assert_path(resp, "response/game/tax_info/@tax_phase")
|
|
|
|
|
|
|
|
|
|
def verify_game_recorder(self) -> None:
|
|
|
|
|
call = self.call_node()
|
|
|
|
|
game = Node.void('game')
|
|
|
|
|
call.add_child(game)
|
|
|
|
|
game.set_attribute('method', 'recorder')
|
|
|
|
|
game.set_attribute('assert_cnt', '0')
|
|
|
|
|
game.set_attribute('assert_info', '')
|
|
|
|
|
game.set_attribute('assert_path', '')
|
|
|
|
|
game.set_attribute('assert_time', '0')
|
|
|
|
|
game.set_attribute('boot_time', '1706151228')
|
|
|
|
|
game.set_attribute('cnt_demo', '1')
|
|
|
|
|
game.set_attribute('cnt_music', '1')
|
|
|
|
|
game.set_attribute('cnt_play', '0')
|
|
|
|
|
game.set_attribute('last_mid', '481')
|
|
|
|
|
game.set_attribute('last_seq', '36')
|
|
|
|
|
game.set_attribute('last_step', '0')
|
|
|
|
|
game.set_attribute('last_time', '1706151235')
|
|
|
|
|
game.set_attribute('softcode', self.config['model'])
|
|
|
|
|
game.set_attribute('temp_seq', '15')
|
|
|
|
|
game.set_attribute('temp_step', '8')
|
|
|
|
|
game.set_attribute('temp_time', '1706151234')
|
|
|
|
|
game.set_attribute('wd_restart', '0')
|
|
|
|
|
|
|
|
|
|
# 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', '2014102700')
|
|
|
|
|
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', '2014102700')
|
|
|
|
|
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', '2014102700')
|
|
|
|
|
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', '2014102700')
|
|
|
|
|
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/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/option_ver/@ver")
|
|
|
|
|
self.assert_path(resp, "response/game/flag")
|
|
|
|
|
self.assert_path(resp, "response/game/flag_ex")
|
|
|
|
|
self.assert_path(resp, "response/game/rank")
|
|
|
|
|
self.assert_path(resp, "response/game/target/@flag")
|
|
|
|
|
self.assert_path(resp, "response/game/target/@setnum")
|
|
|
|
|
for i in range(55):
|
2020-01-07 22:29:07 +01:00
|
|
|
|
self.assert_path(resp, f"response/game/play_area/@play_cnt{i}")
|
2019-12-08 22:43:49 +01:00
|
|
|
|
|
|
|
|
|
gr_s = resp.child('game/gr_s')
|
|
|
|
|
gr_d = resp.child('game/gr_d')
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
'name': resp.child_value('game/name'),
|
|
|
|
|
'ext_id': resp.child_value('game/code'),
|
|
|
|
|
'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', '2014102700')
|
|
|
|
|
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')
|
|
|
|
|
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'),
|
|
|
|
|
}
|
|
|
|
|
if reclink not in scores:
|
|
|
|
|
scores[reclink] = {}
|
|
|
|
|
scores[reclink][chart] = vals
|
|
|
|
|
return scores
|
|
|
|
|
|
|
|
|
|
def verify_game_load_edit(self, ref_id: str) -> None:
|
|
|
|
|
call = self.call_node()
|
|
|
|
|
game = Node.void('game')
|
|
|
|
|
call.add_child(game)
|
|
|
|
|
game.set_attribute('ver', '2014102700')
|
|
|
|
|
game.set_attribute('pid', '0')
|
|
|
|
|
game.set_attribute('refid', ref_id)
|
|
|
|
|
game.set_attribute('method', 'load_edit')
|
|
|
|
|
|
|
|
|
|
# Swap with server
|
|
|
|
|
resp = self.exchange('', call)
|
|
|
|
|
|
|
|
|
|
# Verify that response is correct
|
|
|
|
|
self.assert_path(resp, "response/game")
|
|
|
|
|
|
|
|
|
|
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', '2014102700')
|
|
|
|
|
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_save_m(self, ref_id: str, ext_id: str, score: Dict[str, Any]) -> None:
|
|
|
|
|
call = self.call_node()
|
|
|
|
|
game = Node.void('game')
|
|
|
|
|
call.add_child(game)
|
|
|
|
|
game.set_attribute('method', 'save_m')
|
|
|
|
|
game.set_attribute('diff', '12345')
|
|
|
|
|
game.set_attribute('mtype', str(score['chart']))
|
|
|
|
|
game.set_attribute('mid', str(score['id']))
|
|
|
|
|
game.set_attribute('refid', ref_id)
|
|
|
|
|
game.set_attribute('ver', '2014102700')
|
|
|
|
|
data = Node.void('data')
|
|
|
|
|
game.add_child(data)
|
|
|
|
|
data.set_attribute('score', str(score['score']))
|
|
|
|
|
data.set_attribute('rank', str(score['rank']))
|
|
|
|
|
data.set_attribute('shop_area', '0')
|
|
|
|
|
data.set_attribute('playmode', '1')
|
|
|
|
|
data.set_attribute('combo', str(score['combo']))
|
|
|
|
|
data.set_attribute('phase', '1')
|
|
|
|
|
data.set_attribute('style', '0')
|
|
|
|
|
data.set_attribute('full', '1' if score['halo'] >= 1 else '0')
|
|
|
|
|
data.set_attribute('great_fc', '1' if score['halo'] == 1 else '0')
|
|
|
|
|
data.set_attribute('good_fc', '1' if score['halo'] == 4 else '0')
|
|
|
|
|
data.set_attribute('perf_fc', '1' if score['halo'] == 2 else '0')
|
|
|
|
|
gauge = Node.void('gauge')
|
|
|
|
|
game.add_child(gauge)
|
|
|
|
|
gauge.set_attribute('life8', '0')
|
|
|
|
|
gauge.set_attribute('assist', '0')
|
|
|
|
|
gauge.set_attribute('risky', '0')
|
|
|
|
|
gauge.set_attribute('life4', '0')
|
|
|
|
|
gauge.set_attribute('hard', '0')
|
|
|
|
|
player = Node.void('player')
|
|
|
|
|
game.add_child(player)
|
|
|
|
|
player.set_attribute('playcnt', '123')
|
|
|
|
|
player.set_attribute('code', ext_id)
|
|
|
|
|
option = Node.void('option_02')
|
|
|
|
|
game.add_child(option)
|
|
|
|
|
option.set_attribute('opt02_0', '6')
|
|
|
|
|
option.set_attribute('opt02_6', '1')
|
|
|
|
|
option.set_attribute('opt02_13', '2')
|
|
|
|
|
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(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_game_recorder()
|
|
|
|
|
self.verify_game_tax_info()
|
|
|
|
|
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()
|
2020-01-07 22:29:07 +01:00
|
|
|
|
print(f"Generated random card ID {card} for use.")
|
2019-12-08 22:43:49 +01:00
|
|
|
|
|
|
|
|
|
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:
|
2020-01-07 22:29:07 +01:00
|
|
|
|
raise Exception(f'Invalid refid \'{ref_id}\' returned when registering card')
|
2019-12-08 22:43:49 +01:00
|
|
|
|
if ref_id != self.verify_cardmng_inquire(card, msg_type='new', paseli_enabled=paseli_enabled):
|
2020-01-07 22:29:07 +01:00
|
|
|
|
raise Exception(f'Invalid refid \'{ref_id}\' returned when querying card')
|
2019-12-08 22:43:49 +01:00
|
|
|
|
# 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):
|
2020-01-07 22:29:07 +01:00
|
|
|
|
raise Exception(f'Invalid refid \'{ref_id}\' returned when querying card')
|
2019-12-08 22:43:49 +01:00
|
|
|
|
|
|
|
|
|
# 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')
|
|
|
|
|
ext_id = str(profile['ext_id'])
|
|
|
|
|
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!')
|
|
|
|
|
|
|
|
|
|
self.verify_game_load_edit(ref_id)
|
|
|
|
|
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': 593,
|
|
|
|
|
'chart': 3,
|
|
|
|
|
'score': 800000,
|
|
|
|
|
'combo': 123,
|
|
|
|
|
'rank': 4,
|
|
|
|
|
'halo': 1,
|
|
|
|
|
},
|
|
|
|
|
# A good score on an easier chart same song
|
|
|
|
|
{
|
|
|
|
|
'id': 593,
|
|
|
|
|
'chart': 2,
|
|
|
|
|
'score': 990000,
|
|
|
|
|
'combo': 321,
|
|
|
|
|
'rank': 2,
|
|
|
|
|
'halo': 2,
|
|
|
|
|
},
|
|
|
|
|
# A perfect score
|
|
|
|
|
{
|
|
|
|
|
'id': 483,
|
|
|
|
|
'chart': 3,
|
|
|
|
|
'score': 1000000,
|
|
|
|
|
'combo': 400,
|
|
|
|
|
'rank': 1,
|
|
|
|
|
'halo': 3,
|
|
|
|
|
},
|
|
|
|
|
# A bad score
|
|
|
|
|
{
|
|
|
|
|
'id': 483,
|
|
|
|
|
'chart': 2,
|
|
|
|
|
'score': 100000,
|
|
|
|
|
'combo': 5,
|
|
|
|
|
'rank': 7,
|
|
|
|
|
'halo': 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'id': 483,
|
|
|
|
|
'chart': 1,
|
|
|
|
|
'score': 60000,
|
|
|
|
|
'combo': 5,
|
|
|
|
|
'rank': 6,
|
|
|
|
|
'halo': 4,
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
if phase == 2:
|
|
|
|
|
dummyscores = [
|
|
|
|
|
# A better score on a chart
|
|
|
|
|
{
|
|
|
|
|
'id': 593,
|
|
|
|
|
'chart': 3,
|
|
|
|
|
'score': 850000,
|
|
|
|
|
'combo': 234,
|
|
|
|
|
'rank': 3,
|
|
|
|
|
'halo': 2,
|
|
|
|
|
},
|
|
|
|
|
# A worse score on another chart
|
|
|
|
|
{
|
|
|
|
|
'id': 593,
|
|
|
|
|
'chart': 2,
|
|
|
|
|
'score': 980000,
|
|
|
|
|
'combo': 300,
|
|
|
|
|
'rank': 3,
|
|
|
|
|
'halo': 0,
|
|
|
|
|
'expected_score': 990000,
|
|
|
|
|
'expected_rank': 2,
|
|
|
|
|
'expected_halo': 2,
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for score in dummyscores:
|
|
|
|
|
self.verify_game_save_m(ref_id, ext_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:
|
2020-01-07 22:29:07 +01:00
|
|
|
|
raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
|
2019-12-08 22:43:49 +01:00
|
|
|
|
|
|
|
|
|
# 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'])
|
|
|
|
|
|
|
|
|
|
if data['score'] != expected_score:
|
2020-01-07 22:29:07 +01:00
|
|
|
|
raise Exception(f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["score"]}\'')
|
2019-12-08 22:43:49 +01:00
|
|
|
|
if data['rank'] != expected_rank:
|
2020-01-07 22:29:07 +01:00
|
|
|
|
raise Exception(f'Expected a rank of \'{expected_rank}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got rank \'{data["rank"]}\'')
|
2019-12-08 22:43:49 +01:00
|
|
|
|
if data['halo'] != expected_halo:
|
2020-01-07 22:29:07 +01:00
|
|
|
|
raise Exception(f'Expected a halo of \'{expected_halo}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got halo \'{data["halo"]}\'')
|
2019-12-08 22:43:49 +01:00
|
|
|
|
|
|
|
|
|
# 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)
|