1
0
mirror of synced 2025-02-17 19:19:19 +01:00

fix issues and verify lint

This commit is contained in:
Shinrin Ouja Moriking 2024-04-01 00:10:37 -06:00
parent 2b6ce21084
commit cd587b19c3
12 changed files with 243 additions and 140 deletions

View File

@ -1,9 +1,7 @@
from typing import Optional
from typing_extensions import Final from typing_extensions import Final
from bemani.backend.base import Base from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
from bemani.common import GameConstants, ValidatedDict from bemani.common import GameConstants
from bemani.protocol import Node
class HelloPopnBase(CoreHandler, CardManagerHandler, PASELIHandler, Base): class HelloPopnBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):

View File

@ -8,6 +8,7 @@ from bemani.common import ValidatedDict, VersionConstants, Profile
from bemani.data import Score from bemani.data import Score
from bemani.protocol import Node from bemani.protocol import Node
class HelloPopnMusic( class HelloPopnMusic(
EventLogHandler, EventLogHandler,
HelloPopnBase, HelloPopnBase,
@ -16,14 +17,11 @@ class HelloPopnMusic(
version = VersionConstants.HELLO_POPN_MUSIC version = VersionConstants.HELLO_POPN_MUSIC
@classmethod @classmethod
def get_settings(cls) -> Dict[str, Any]: def get_settings(cls) -> Dict[str, Any]:
""" """
Return all of our front-end modifiably settings. Return all of our front-end modifiably settings.
""" """
return { return {
"ints": [
],
'bools': [ 'bools': [
{ {
'name': 'Force Song Unlock', 'name': 'Force Song Unlock',
@ -82,7 +80,6 @@ class HelloPopnMusic(
# Load profile values # Load profile values
root = Node.void('game') root = Node.void('game')
userid = self.data.remote.user.from_refid(self.game, self.version, request.attribute('refid')) userid = self.data.remote.user.from_refid(self.game, self.version, request.attribute('refid'))
profile = self.get_profile(userid) profile = self.get_profile(userid)
@ -106,7 +103,6 @@ class HelloPopnMusic(
chara.set_attribute('love', achievement.data.get_str('love')) chara.set_attribute('love', achievement.data.get_str('love'))
root.add_child(chara) root.add_child(chara)
last = Node.void('last') last = Node.void('last')
root.add_child(last) root.add_child(last)
last.set_attribute('chara', profile.get_str('chara')) last.set_attribute('chara', profile.get_str('chara'))
@ -169,30 +165,27 @@ class HelloPopnMusic(
self.put_profile(userid, newprofile) self.put_profile(userid, newprofile)
game_config = self.get_game_config() game_config = self.get_game_config()
force_unlock_songs = game_config.get_bool("force_unlock_songs") force_unlock_songs = game_config.get_bool("force_unlock_songs")
# if we were on force unlock mode, achievements will not be modified # if we were on force unlock mode, achievements will not be modified
if force_unlock_songs is False: if force_unlock_songs is False:
achievements = self.data.local.user.get_achievements(self.game, self.version, userid) achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
love = last.attribute('love') chara = int(last.attribute('chara'))
for achievement in achievements: for achievement in achievements:
if achievement.type == 'toki_love' and achievement.id == int(last.attribute('chara')): if achievement.type == 'toki_love' and achievement.id == chara:
love = str(int(achievement.data["love"]) + 1) love = int(achievement.data["love"])
if achievement.data["love"] == "5": if love > 5:
love = "5"
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
self.version, self.version,
userid, userid,
int(last.attribute('chara')), chara,
'toki_love', 'toki_love',
{ {
'love': love, 'love': str(love + 1),
}, },
) )
break
return root return root
@ -207,7 +200,7 @@ class HelloPopnMusic(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
#pull old score # Pull old score
oldscore = self.data.local.music.get_score( oldscore = self.data.local.music.get_score(
self.game, self.game,
self.version, self.version,
@ -235,7 +228,6 @@ class HelloPopnMusic(
# Look up where this score was earned # Look up where this score was earned
lid = self.get_machine_id() lid = self.get_machine_id()
# Write the new score back # Write the new score back
self.data.local.music.put_score( self.data.local.music.put_score(
self.game, self.game,

View File

@ -1,6 +1,6 @@
import base64 import random
import time import time
from typing import Optional from typing import Any, Dict, Optional
from bemani.client.base import BaseClient from bemani.client.base import BaseClient
from bemani.protocol import Node from bemani.protocol import Node
@ -8,8 +8,6 @@ from bemani.protocol import Node
class HelloPopnMuiscClient(BaseClient): class HelloPopnMuiscClient(BaseClient):
NAME = ""
def verify_game_shop(self) -> None: def verify_game_shop(self) -> None:
call = self.call_node() call = self.call_node()
game = Node.void("game") game = Node.void("game")
@ -46,7 +44,6 @@ class HelloPopnMuiscClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/game/@status") self.assert_path(resp, "response/game/@status")
def verify_game_common(self) -> None: def verify_game_common(self) -> None:
call = self.call_node() call = self.call_node()
game = Node.void("game") game = Node.void("game")
@ -57,7 +54,12 @@ class HelloPopnMuiscClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
# Verify that response is correct # Verify that response is correct
#self.__verify_profile(resp) self.assert_path(resp, "response/game/@status")
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_new(self, loc: str, refid: str) -> None: def verify_game_new(self, loc: str, refid: str) -> None:
call = self.call_node() call = self.call_node()
@ -105,23 +107,48 @@ class HelloPopnMuiscClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/game/@status") self.assert_path(resp, "response/game/@status")
def verify_game_save_m(self, refid: str)->None: # Grab scores
scores: Dict[int, Dict[int, int]] = {}
clears: Dict[int, Dict[int, int]] = {}
for child in resp.child("game").children:
if child.name != "music":
continue
score_data = child.child("style").child("level")
musicid = child.attribute("music_id")
chart = score_data.attribute("id")
score = score_data.attribute("score")
clear_type = score_data.attribute("clear_type")
if musicid not in scores:
scores[musicid] = {}
if musicid not in clears:
clears[musicid] = {}
scores[musicid][chart] = score
clears[musicid][chart] = clear_type
return {
"scores": scores,
"clears": clears,
}
def verify_game_save_m(self, refid: str, score: Dict[str, Any]) -> None:
call = self.call_node() call = self.call_node()
# Construct node
game = Node.void("game") game = Node.void("game")
call.add_child(game) call.add_child(game)
game.set_attribute("clear_type", "2") game.set_attribute("clear_type", score["clear_type"])
game.set_attribute("level", "1") game.set_attribute("level", score["chart"])
game.set_attribute("method", "save_m") game.set_attribute("method", "save_m")
game.set_attribute("music_id", "1") game.set_attribute("music_id", score["id"])
game.set_attribute("refid", refid) game.set_attribute("refid", refid)
game.set_attribute("score", "736000") game.set_attribute("score", score["score"])
game.set_attribute("style", "0") game.set_attribute("style", "0")
game.set_attribute("ver", "0") game.set_attribute("ver", "0")
# Swap with server # Swap with server
resp = self.exchange("", call) resp = self.exchange("", call)
# Verify that response is correct
self.assert_path(resp, "response/game/@status") self.assert_path(resp, "response/game/@status")
def verify_game_save(self, loc: str , refid: str) -> None: def verify_game_save(self, loc: str , refid: str) -> None:
@ -146,7 +173,6 @@ class HelloPopnMuiscClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/game/@status") self.assert_path(resp, "response/game/@status")
def verify(self, cardid: Optional[str]) -> None: def verify(self, cardid: Optional[str]) -> None:
# Verify boot sequence is okay # Verify boot sequence is okay
self.verify_services_get( self.verify_services_get(
@ -204,8 +230,99 @@ class HelloPopnMuiscClient(BaseClient):
raise Exception(f'Invalid refid \'{ref_id}\' returned when querying card') raise Exception(f'Invalid refid \'{ref_id}\' returned when querying card')
self.verify_game_load(ref_id) self.verify_game_load(ref_id)
self.verify_game_load_m(ref_id) self.verify_game_load_m(ref_id)
self.verify_game_save_m(ref_id) if cardid is None:
# verify score saving
for phase in [1, 2]:
if phase == 1:
dummyscores = [
# An okay score on a chart
{
"id": "1",
"chart": "1",
"clear_type": "1",
"score": "813144",
},
# A good score on an easier chart of the same song
{
"id": "1",
"chart": "0",
"clear_type": "4",
"score": "1000000",
},
# A bad score on a hard chart
{
"id": "35",
"chart": "2",
"clear_type": "1",
"score": "590523",
},
# A terrible score on an easy chart
{
"id": "28",
"chart": "0",
"clear_type": "1",
"score": "1",
},
]
# Random score to add in
songid = str(random.randint(1, 35))
chartid = str(random.randint(0, 2))
clear_type = str(random.randint(1, 4))
score = str(random.randint(0, 1000000))
dummyscores.append(
{
"id": songid,
"chart": chartid,
"clear_type": clear_type,
"score": score,
}
)
if phase == 2:
dummyscores = [
# A better score on the same chart
{
"id": "1",
"chart": "1",
"clear_type": "3",
"score": "950144",
},
# A worse score on another same chart
{
"id": "1",
"chart": "0",
"clear_type": "1",
"score": "672381",
"expected_score": "1000000",
"expected_clear": "4",
},
]
for dummyscore in dummyscores:
self.verify_game_save_m(ref_id, dummyscore)
# Sleep so we don't end up putting in score history on the same second
time.sleep(1)
scores = self.verify_game_load_m(ref_id)
for expected in dummyscores:
newscore = scores["scores"][expected["id"]][expected["chart"]]
newclear = scores["clears"][expected["id"]][expected["chart"]]
if "expected_score" in expected:
expected_score = expected["expected_score"]
else:
expected_score = expected["score"]
if "expected_clear" in expected:
expected_clear = expected["expected_clear"]
else:
expected_clear = expected["clear_type"]
if newscore != expected_score:
raise Exception(
f'Expected a score of \'{expected_score}\' for song \'{expected["id"]}\' chart \'{expected["chart"]}\' but got score \'{newscore}\''
)
if newclear != expected_clear:
raise Exception(
f'Expected a medal of \'{expected_clear}\' for song \'{expected["id"]}\' chart \'{expected["chart"]}\' but got medal \'{newclear}\''
)
else:
print("Skipping score checks for existing card")
self.verify_game_save(location, ref_id) self.verify_game_save(location, ref_id)

View File

@ -1,19 +1,12 @@
from bemani.data import Config, Data from bemani.data import Config, Data
from flask_caching import Cache from bemani.common import cache
from bemani.frontend.app import app
from bemani.frontend.hellopopn.hellopopn import HelloPopnMusicFrontend from bemani.frontend.hellopopn.hellopopn import HelloPopnMusicFrontend
class HelloPopnMusicCache: class HelloPopnMusicCache:
@classmethod @classmethod
def preload(cls, data: Data, config: Config) -> None: def preload(cls, data: Data, config: Config) -> None:
cache = Cache(
app,
config={
"CACHE_TYPE": "filesystem",
"CACHE_DIR": config.cache_dir,
},
)
frontend = HelloPopnMusicFrontend(data, config, cache) frontend = HelloPopnMusicFrontend(data, config, cache)
frontend.get_all_songs(force_db_load=True) frontend.get_all_songs(force_db_load=True)

View File

@ -1,5 +1,4 @@
import re import re
from flask import Blueprint
from bemani.frontend.templates import templates_location from bemani.frontend.templates import templates_location
from bemani.frontend.static import static_location from bemani.frontend.static import static_location
from bemani.data import UserID from bemani.data import UserID
@ -29,7 +28,6 @@ def viewnetworkscores() -> Response:
if len(network_scores["attempts"]) > 10: if len(network_scores["attempts"]) > 10:
network_scores["attempts"] = frontend.round_to_ten(network_scores["attempts"]) network_scores["attempts"] = frontend.round_to_ten(network_scores["attempts"])
return render_react( return render_react(
"Global Hello Pop'n Music Scores", "Global Hello Pop'n Music Scores",
"hpnm/scores.react.js", "hpnm/scores.react.js",
@ -47,6 +45,7 @@ def viewnetworkscores() -> Response:
}, },
) )
@hpnm_pages.route("/scores/list") @hpnm_pages.route("/scores/list")
@jsonify @jsonify
@loginrequired @loginrequired
@ -54,6 +53,7 @@ def listnetworkscores() -> Dict[str, Any]:
frontend = HelloPopnMusicFrontend(g.data, g.config, g.cache) frontend = HelloPopnMusicFrontend(g.data, g.config, g.cache)
return frontend.get_network_scores() return frontend.get_network_scores()
@hpnm_pages.route('/scores/<int:userid>') @hpnm_pages.route('/scores/<int:userid>')
@loginrequired @loginrequired
def viewscores(userid: UserID) -> Response: def viewscores(userid: UserID) -> Response:
@ -83,6 +83,7 @@ def viewscores(userid: UserID) -> Response:
}, },
) )
@hpnm_pages.route("/scores/<int:userid>/list") @hpnm_pages.route("/scores/<int:userid>/list")
@jsonify @jsonify
@loginrequired @loginrequired
@ -93,6 +94,7 @@ def listscores(userid: UserID) -> Dict[str, Any]:
"players": {}, "players": {},
} }
@hpnm_pages.route("/topscores/<int:musicid>") @hpnm_pages.route("/topscores/<int:musicid>")
@loginrequired @loginrequired
def viewtopscores(musicid: int) -> Response: def viewtopscores(musicid: int) -> Response:
@ -161,6 +163,7 @@ def viewplayers() -> Response:
}, },
) )
@hpnm_pages.route('/players/list') @hpnm_pages.route('/players/list')
@jsonify @jsonify
@loginrequired @loginrequired
@ -208,6 +211,7 @@ def listplayer(userid: UserID) -> Dict[str, Any]:
"player": info, "player": info,
} }
@hpnm_pages.route("/options") @hpnm_pages.route("/options")
@loginrequired @loginrequired
def viewsettings() -> Response: def viewsettings() -> Response:
@ -270,6 +274,7 @@ def updatename() -> Dict[str, Any]:
"name": name, "name": name,
} }
@hpnm_pages.route("/records") @hpnm_pages.route("/records")
@loginrequired @loginrequired
def viewnetworkrecords() -> Response: def viewnetworkrecords() -> Response:

View File

@ -1,4 +1,3 @@
import copy
from typing import Any, Dict, Iterator, List, Tuple from typing import Any, Dict, Iterator, List, Tuple
from flask_caching import Cache # type: ignore from flask_caching import Cache # type: ignore
from bemani.backend.hellopopn import HelloPopnFactory, HelloPopnBase from bemani.backend.hellopopn import HelloPopnFactory, HelloPopnBase
@ -6,6 +5,7 @@ from bemani.common import Profile, ValidatedDict, GameConstants
from bemani.data import Data, UserID, Attempt, Song from bemani.data import Data, UserID, Attempt, Song
from bemani.frontend.base import FrontendBase from bemani.frontend.base import FrontendBase
class HelloPopnMusicFrontend(FrontendBase): class HelloPopnMusicFrontend(FrontendBase):
game = GameConstants.HELLO_POPN game = GameConstants.HELLO_POPN

View File

@ -16,7 +16,6 @@ from bemani.common import GameConstants, cache
from bemani.data import Config, Data from bemani.data import Config, Data
def load_config(filename: str, config: Config) -> None: def load_config(filename: str, config: Config) -> None:
config.update(yaml.safe_load(open(filename))) config.update(yaml.safe_load(open(filename)))
config["database"]["engine"] = Data.create_engine(config) config["database"]["engine"] = Data.create_engine(config)

View File

@ -4591,9 +4591,9 @@ class ImportHelloPopn(ImportBase):
'artist': song.artist, 'artist': song.artist,
'genre': song.genre, 'genre': song.genre,
'difficulty': { 'difficulty': {
'easy': 0, 'easy': 1,
'normal': 1, 'normal': 10,
'hard': 2, 'hard': 100,
}, },
'category': self.version 'category': self.version
} }
@ -4602,7 +4602,6 @@ class ImportHelloPopn(ImportBase):
# Reassemble the data # Reassemble the data
reassembled_songs = [val for _, val in lut.items()] reassembled_songs = [val for _, val in lut.items()]
return reassembled_songs return reassembled_songs
def import_music_db(self, songs: List[Dict[str, Any]], version: int) -> None: def import_music_db(self, songs: List[Dict[str, Any]], version: int) -> None: