1
0
mirror of synced 2024-11-27 23:50:47 +01:00

Make black do 120 character lines instead of 80.

This commit is contained in:
Jennifer Taylor 2024-01-02 02:46:24 +00:00
parent d3413715f3
commit f6a9aa69fd
211 changed files with 3914 additions and 12437 deletions

View File

@ -91,9 +91,7 @@ def jsonify(func: Callable) -> Callable:
@app.errorhandler(Exception) @app.errorhandler(Exception)
def server_exception(exception: Any) -> Response: def server_exception(exception: Any) -> Response:
stack = "".join( stack = "".join(traceback.format_exception(type(exception), exception, exception.__traceback__))
traceback.format_exception(type(exception), exception, exception.__traceback__)
)
print(stack) print(stack)
try: try:
g.data.local.network.put_event( g.data.local.network.put_event(

View File

@ -14,15 +14,11 @@ class BaseObject:
various fetch versions. various fetch versions.
""" """
def __init__( def __init__(self, data: Data, game: GameConstants, version: int, omnimix: bool) -> None:
self, data: Data, game: GameConstants, version: int, omnimix: bool
) -> None:
self.data = data self.data = data
self.game = game self.game = game
self.version = version self.version = version
self.omnimix = omnimix self.omnimix = omnimix
def fetch_v1( def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> Any:
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
) -> Any:
raise APIException("Object fetch not supported for this version!") raise APIException("Object fetch not supported for this version!")

View File

@ -65,9 +65,7 @@ class CatalogObject(BaseObject):
} }
return { return {
"difficulty": song.data.get_int("difficulty"), "difficulty": song.data.get_int("difficulty"),
"category": categorymapping.get( "category": categorymapping.get(song.data.get_int("version", defaultcategory), "1"),
song.data.get_int("version", defaultcategory), "1"
),
"bpm_min": song.data.get_int("bpm_min"), "bpm_min": song.data.get_int("bpm_min"),
"bpm_max": song.data.get_int("bpm_max"), "bpm_max": song.data.get_int("bpm_max"),
} }
@ -228,9 +226,7 @@ class CatalogObject(BaseObject):
else: else:
return self.version return self.version
def fetch_v1( def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> Dict[str, List[Dict[str, Any]]]:
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
) -> Dict[str, List[Dict[str, Any]]]:
# Verify IDs # Verify IDs
if idtype != APIConstants.ID_TYPE_SERVER: if idtype != APIConstants.ID_TYPE_SERVER:
raise APIException( raise APIException(
@ -240,10 +236,7 @@ class CatalogObject(BaseObject):
# Fetch the songs # Fetch the songs
songs = self.data.local.music.get_all_songs(self.game, self.music_version) songs = self.data.local.music.get_all_songs(self.game, self.music_version)
if ( if self.game == GameConstants.JUBEAT and self.version == VersionConstants.JUBEAT_CLAN:
self.game == GameConstants.JUBEAT
and self.version == VersionConstants.JUBEAT_CLAN
):
# There's always a special case. We don't store all music IDs since those in # There's always a special case. We don't store all music IDs since those in
# the range of 80000301-80000347 are actually the same song, but copy-pasted # the range of 80000301-80000347 are actually the same song, but copy-pasted
# for different prefectures and slightly different charts. So, we need to copy # for different prefectures and slightly different charts. So, we need to copy

View File

@ -74,15 +74,11 @@ class ProfileObject(BaseObject):
return base return base
def fetch_v1( def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> List[Dict[str, Any]]:
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
) -> List[Dict[str, Any]]:
# Fetch the profiles # Fetch the profiles
profiles: List[Tuple[UserID, Profile]] = [] profiles: List[Tuple[UserID, Profile]] = []
if idtype == APIConstants.ID_TYPE_SERVER: if idtype == APIConstants.ID_TYPE_SERVER:
profiles.extend( profiles.extend(self.data.local.user.get_all_profiles(self.game, self.version))
self.data.local.user.get_all_profiles(self.game, self.version)
)
elif idtype == APIConstants.ID_TYPE_SONG: elif idtype == APIConstants.ID_TYPE_SONG:
raise APIException( raise APIException(
"Unsupported ID for lookup!", "Unsupported ID for lookup!",
@ -108,9 +104,7 @@ class ProfileObject(BaseObject):
# in the case that we returned scores for a user that doesn't have a # in the case that we returned scores for a user that doesn't have a
# profile on a particular version. We allow that on this network, so in # profile on a particular version. We allow that on this network, so in
# order to not break remote networks, try our best to return any profile. # order to not break remote networks, try our best to return any profile.
profile = self.data.local.user.get_any_profile( profile = self.data.local.user.get_any_profile(self.game, self.version, userid)
self.game, self.version, userid
)
if profile is not None: if profile is not None:
profiles.append((userid, profile)) profiles.append((userid, profile))
else: else:

View File

@ -235,9 +235,7 @@ class RecordsObject(BaseObject):
else: else:
return self.version return self.version
def fetch_v1( def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> List[Dict[str, Any]]:
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
) -> List[Dict[str, Any]]:
since = params.get("since") since = params.get("since")
until = params.get("until") until = params.get("until")
@ -247,9 +245,7 @@ class RecordsObject(BaseObject):
# Because of the way this query works, we can't apply since/until to it directly. # Because of the way this query works, we can't apply since/until to it directly.
# If we did, it would miss higher scores earned before since or after until, and # If we did, it would miss higher scores earned before since or after until, and
# incorrectly report records. # incorrectly report records.
records.extend( records.extend(self.data.local.music.get_all_records(self.game, self.music_version))
self.data.local.music.get_all_records(self.game, self.music_version)
)
elif idtype == APIConstants.ID_TYPE_SONG: elif idtype == APIConstants.ID_TYPE_SONG:
if len(ids) == 1: if len(ids) == 1:
songid = int(ids[0]) songid = int(ids[0])
@ -273,9 +269,7 @@ class RecordsObject(BaseObject):
cardid = ids[2] cardid = ids[2]
userid = self.data.local.user.from_cardid(cardid) userid = self.data.local.user.from_cardid(cardid)
if userid is not None: if userid is not None:
score = self.data.local.music.get_score( score = self.data.local.music.get_score(self.game, self.music_version, userid, songid, chart)
self.game, self.music_version, userid, songid, chart
)
if score is not None: if score is not None:
records.append((userid, score)) records.append((userid, score))
elif idtype == APIConstants.ID_TYPE_CARD: elif idtype == APIConstants.ID_TYPE_CARD:

View File

@ -17,9 +17,7 @@ class StatisticsObject(BaseObject):
"combos": stats.get("combos", -1), "combos": stats.get("combos", -1),
} }
def __format_user_statistics( def __format_user_statistics(self, cardids: List[str], stats: Dict[str, Any]) -> Dict[str, Any]:
self, cardids: List[str], stats: Dict[str, Any]
) -> Dict[str, Any]:
base = self.__format_statistics(stats) base = self.__format_statistics(stats)
base["cards"] = cardids base["cards"] = cardids
return base return base
@ -48,20 +46,11 @@ class StatisticsObject(BaseObject):
}: }:
return True return True
if self.game == GameConstants.IIDX: if self.game == GameConstants.IIDX:
return ( return attempt.data.get_int("clear_status") != DBConstants.IIDX_CLEAR_STATUS_NO_PLAY
attempt.data.get_int("clear_status")
!= DBConstants.IIDX_CLEAR_STATUS_NO_PLAY
)
if self.game == GameConstants.REFLEC_BEAT: if self.game == GameConstants.REFLEC_BEAT:
return ( return attempt.data.get_int("clear_type") != DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY
attempt.data.get_int("clear_type")
!= DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY
)
if self.game == GameConstants.SDVX: if self.game == GameConstants.SDVX:
return ( return attempt.data.get_int("clear_type") != DBConstants.SDVX_CLEAR_TYPE_NO_PLAY
attempt.data.get_int("clear_type")
!= DBConstants.SDVX_CLEAR_TYPE_NO_PLAY
)
return False return False
@ -72,17 +61,11 @@ class StatisticsObject(BaseObject):
if self.game == GameConstants.DDR: if self.game == GameConstants.DDR:
return attempt.data.get_int("rank") != DBConstants.DDR_RANK_E return attempt.data.get_int("rank") != DBConstants.DDR_RANK_E
if self.game == GameConstants.IIDX: if self.game == GameConstants.IIDX:
return ( return attempt.data.get_int("clear_status") != DBConstants.IIDX_CLEAR_STATUS_FAILED
attempt.data.get_int("clear_status")
!= DBConstants.IIDX_CLEAR_STATUS_FAILED
)
if self.game == GameConstants.JUBEAT: if self.game == GameConstants.JUBEAT:
return attempt.data.get_int("medal") != DBConstants.JUBEAT_PLAY_MEDAL_FAILED return attempt.data.get_int("medal") != DBConstants.JUBEAT_PLAY_MEDAL_FAILED
if self.game == GameConstants.MUSECA: if self.game == GameConstants.MUSECA:
return ( return attempt.data.get_int("clear_type") != DBConstants.MUSECA_CLEAR_TYPE_FAILED
attempt.data.get_int("clear_type")
!= DBConstants.MUSECA_CLEAR_TYPE_FAILED
)
if self.game == GameConstants.POPN_MUSIC: if self.game == GameConstants.POPN_MUSIC:
return attempt.data.get_int("medal") not in [ return attempt.data.get_int("medal") not in [
DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FAILED, DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FAILED,
@ -90,14 +73,9 @@ class StatisticsObject(BaseObject):
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FAILED, DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FAILED,
] ]
if self.game == GameConstants.REFLEC_BEAT: if self.game == GameConstants.REFLEC_BEAT:
return ( return attempt.data.get_int("clear_type") != DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED
attempt.data.get_int("clear_type")
!= DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED
)
if self.game == GameConstants.SDVX: if self.game == GameConstants.SDVX:
return attempt.data.get_int( return attempt.data.get_int("grade") != DBConstants.SDVX_GRADE_NO_PLAY and attempt.data.get_int(
"grade"
) != DBConstants.SDVX_GRADE_NO_PLAY and attempt.data.get_int(
"clear_type" "clear_type"
) not in [ ) not in [
DBConstants.SDVX_CLEAR_TYPE_NO_PLAY, DBConstants.SDVX_CLEAR_TYPE_NO_PLAY,
@ -113,10 +91,7 @@ class StatisticsObject(BaseObject):
if self.game == GameConstants.DDR: if self.game == GameConstants.DDR:
return attempt.data.get_int("halo") != DBConstants.DDR_HALO_NONE return attempt.data.get_int("halo") != DBConstants.DDR_HALO_NONE
if self.game == GameConstants.IIDX: if self.game == GameConstants.IIDX:
return ( return attempt.data.get_int("clear_status") == DBConstants.IIDX_CLEAR_STATUS_FULL_COMBO
attempt.data.get_int("clear_status")
== DBConstants.IIDX_CLEAR_STATUS_FULL_COMBO
)
if self.game == GameConstants.JUBEAT: if self.game == GameConstants.JUBEAT:
return attempt.data.get_int("medal") in [ return attempt.data.get_int("medal") in [
DBConstants.JUBEAT_PLAY_MEDAL_FULL_COMBO, DBConstants.JUBEAT_PLAY_MEDAL_FULL_COMBO,
@ -124,10 +99,7 @@ class StatisticsObject(BaseObject):
DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT, DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT,
] ]
if self.game == GameConstants.MUSECA: if self.game == GameConstants.MUSECA:
return ( return attempt.data.get_int("clear_type") == DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO
attempt.data.get_int("clear_type")
== DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO
)
if self.game == GameConstants.POPN_MUSIC: if self.game == GameConstants.POPN_MUSIC:
return attempt.data.get_int("medal") in [ return attempt.data.get_int("medal") in [
DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FULL_COMBO, DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FULL_COMBO,
@ -213,20 +185,13 @@ class StatisticsObject(BaseObject):
return retval return retval
def fetch_v1( def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> List[Dict[str, Any]]:
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
) -> List[Dict[str, Any]]:
retval: List[Dict[str, Any]] = [] retval: List[Dict[str, Any]] = []
# Fetch the attempts # Fetch the attempts
if idtype == APIConstants.ID_TYPE_SERVER: if idtype == APIConstants.ID_TYPE_SERVER:
retval = self.__aggregate_global( retval = self.__aggregate_global(
[ [attempt[1] for attempt in self.data.local.music.get_all_attempts(self.game, self.music_version)]
attempt[1]
for attempt in self.data.local.music.get_all_attempts(
self.game, self.music_version
)
]
) )
elif idtype == APIConstants.ID_TYPE_SONG: elif idtype == APIConstants.ID_TYPE_SONG:
if len(ids) == 1: if len(ids) == 1:
@ -272,9 +237,7 @@ class StatisticsObject(BaseObject):
id_to_cards[userid] = self.data.local.user.get_cards(userid) id_to_cards[userid] = self.data.local.user.get_cards(userid)
attempts.extend( attempts.extend(
self.data.local.music.get_all_attempts( self.data.local.music.get_all_attempts(self.game, self.music_version, userid=userid)
self.game, self.music_version, userid=userid
)
) )
retval = self.__aggregate_local(id_to_cards, attempts) retval = self.__aggregate_local(id_to_cards, attempts)
else: else:

View File

@ -226,9 +226,7 @@ class Base(ABC):
return Base(data, config, model) return Base(data, config, model)
else: else:
# Return the registered module providing this game # Return the registered module providing this game
return cls.__registered_games[model.gamecode].create( return cls.__registered_games[model.gamecode].create(data, config, model, parentmodel=parentmodel)
data, config, model, parentmodel=parentmodel
)
@classmethod @classmethod
def register(cls, gamecode: str, handler: Type[Factory]) -> None: def register(cls, gamecode: str, handler: Type[Factory]) -> None:
@ -244,9 +242,7 @@ class Base(ABC):
cls.__registered_handlers.add(handler) cls.__registered_handlers.add(handler)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Config) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Config
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Run any out-of-band scheduled work that is applicable to this game. Run any out-of-band scheduled work that is applicable to this game.
""" """
@ -297,10 +293,7 @@ class Base(ABC):
Returns: Returns:
True if the profile exists, False if not. True if the profile exists, False if not.
""" """
return ( return self.data.local.user.get_profile(self.game, self.version, userid) is not None
self.data.local.user.get_profile(self.game, self.version, userid)
is not None
)
def get_profile(self, userid: UserID) -> Optional[Profile]: def get_profile(self, userid: UserID) -> Optional[Profile]:
""" """
@ -354,15 +347,11 @@ class Base(ABC):
or an empty dictionary if nothing was found. or an empty dictionary if nothing was found.
""" """
userids = list(set(userids)) userids = list(set(userids))
profiles = self.data.remote.user.get_any_profiles( profiles = self.data.remote.user.get_any_profiles(self.game, self.version, userids)
self.game, self.version, userids
)
return [ return [
( (
userid, userid,
profile profile if profile is not None else Profile(self.game, self.version, "", 0),
if profile is not None
else Profile(self.game, self.version, "", 0),
) )
for (userid, profile) in profiles for (userid, profile) in profiles
] ]
@ -379,9 +368,7 @@ class Base(ABC):
raise Exception("Trying to save a remote profile locally!") raise Exception("Trying to save a remote profile locally!")
self.data.local.user.put_profile(self.game, self.version, userid, profile) self.data.local.user.put_profile(self.game, self.version, userid, profile)
def update_play_statistics( def update_play_statistics(self, userid: UserID, stats: Optional[PlayStatistics] = None) -> None:
self, userid: UserID, stats: Optional[PlayStatistics] = None
) -> None:
""" """
Given a user ID, calculate new play statistics. Given a user ID, calculate new play statistics.
@ -397,9 +384,7 @@ class Base(ABC):
# We store the play statistics in a series-wide settings blob so its available # We store the play statistics in a series-wide settings blob so its available
# across all game versions, since it isn't game-specific. # across all game versions, since it isn't game-specific.
settings = self.data.local.game.get_settings( settings = self.data.local.game.get_settings(self.game, userid) or ValidatedDict({})
self.game, userid
) or ValidatedDict({})
if stats is not None: if stats is not None:
for key in stats: for key in stats:
@ -418,9 +403,7 @@ class Base(ABC):
settings[key] = stats[key] settings[key] = stats[key]
settings.replace_int("total_plays", settings.get_int("total_plays") + 1) settings.replace_int("total_plays", settings.get_int("total_plays") + 1)
settings.replace_int( settings.replace_int("first_play_timestamp", settings.get_int("first_play_timestamp", Time.now()))
"first_play_timestamp", settings.get_int("first_play_timestamp", Time.now())
)
settings.replace_int("last_play_timestamp", Time.now()) settings.replace_int("last_play_timestamp", Time.now())
last_play_date = settings.get_int_array("last_play_date", 3) last_play_date = settings.get_int_array("last_play_date", 3)
@ -445,9 +428,7 @@ class Base(ABC):
and last_play_date[2] == yesterday_play_date[2] and last_play_date[2] == yesterday_play_date[2]
): ):
# We played yesterday, add one to consecutive days # We played yesterday, add one to consecutive days
settings.replace_int( settings.replace_int("consecutive_days", settings.get_int("consecutive_days") + 1)
"consecutive_days", settings.get_int("consecutive_days") + 1
)
else: else:
# We haven't played yesterday, so we have only one consecutive day. # We haven't played yesterday, so we have only one consecutive day.
settings.replace_int("consecutive_days", 1) settings.replace_int("consecutive_days", 1)
@ -490,13 +471,9 @@ class Base(ABC):
def get_machine_region(self) -> int: def get_machine_region(self) -> int:
arcade = self.get_arcade() arcade = self.get_arcade()
if arcade is None: if arcade is None:
return RegionConstants.db_to_game_region( return RegionConstants.db_to_game_region(self.requires_extended_regions, self.config.server.region)
self.requires_extended_regions, self.config.server.region
)
else: else:
return RegionConstants.db_to_game_region( return RegionConstants.db_to_game_region(self.requires_extended_regions, arcade.region)
self.requires_extended_regions, arcade.region
)
def get_game_config(self) -> ValidatedDict: def get_game_config(self) -> ValidatedDict:
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
@ -504,9 +481,7 @@ class Base(ABC):
# If this machine belongs to an arcade, use its settings. If the settings aren't present, # If this machine belongs to an arcade, use its settings. If the settings aren't present,
# default to the game's defaults. # default to the game's defaults.
if machine.arcade is not None: if machine.arcade is not None:
settings = self.data.local.machine.get_settings( settings = self.data.local.machine.get_settings(machine.arcade, self.game, self.version, "game_config")
machine.arcade, self.game, self.version, "game_config"
)
if settings is None: if settings is None:
settings = ValidatedDict() settings = ValidatedDict()
return settings return settings
@ -582,11 +557,7 @@ class Base(ABC):
total_days = settings.get_int("total_days", 1) total_days = settings.get_int("total_days", 1)
consecutive_days = settings.get_int("consecutive_days", 1) consecutive_days = settings.get_int("consecutive_days", 1)
else: else:
if ( if last_play_date[0] != 0 and last_play_date[1] != 0 and last_play_date[2] != 0:
last_play_date[0] != 0
and last_play_date[1] != 0
and last_play_date[2] != 0
):
# We've played before but not today, so the total days is # We've played before but not today, so the total days is
# the stored count plus today. # the stored count plus today.
total_days = settings.get_int("total_days") + 1 total_days = settings.get_int("total_days") + 1

View File

@ -98,9 +98,7 @@ class TheStarBishiBashi(
data = data.replace(";", "#;") data = data.replace(";", "#;")
return data return data
def __generate_setting( def __generate_setting(self, key: str, values: Union[int, str, Sequence[int], Sequence[str]]) -> str:
self, key: str, values: Union[int, str, Sequence[int], Sequence[str]]
) -> str:
if isinstance(values, Iterable) and not isinstance(values, str): if isinstance(values, Iterable) and not isinstance(values, str):
values = ",".join(self.__escape_string(x) for x in values) values = ",".join(self.__escape_string(x) for x in values)
else: else:
@ -184,9 +182,7 @@ class TheStarBishiBashi(
enable_dlc_levels = game_config.get_bool("enable_dlc_levels") enable_dlc_levels = game_config.get_bool("enable_dlc_levels")
if enable_dlc_levels: if enable_dlc_levels:
settings["MAL"] = 1 settings["MAL"] = 1
force_unlock_characters = game_config.get_bool( force_unlock_characters = game_config.get_bool("force_unlock_eamuse_characters")
"force_unlock_eamuse_characters"
)
if force_unlock_characters: if force_unlock_characters:
settings["ALL"] = 1 settings["ALL"] = 1
scrolling_message = game_config.get_str("big_announcement") scrolling_message = game_config.get_str("big_announcement")
@ -197,9 +193,7 @@ class TheStarBishiBashi(
settings["IM"] = bb_message settings["IM"] = bb_message
# Generate system message # Generate system message
settings_str = ";".join( settings_str = ";".join(self.__generate_setting(key, vals) for key, vals in settings.items())
self.__generate_setting(key, vals) for key, vals in settings.items()
)
# Send it to the client, making sure to inform the client that it was valid. # Send it to the client, making sure to inform the client that it was valid.
root.add_child( root.add_child(
@ -223,9 +217,7 @@ class TheStarBishiBashi(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is None: if userid is None:
root = Node.void("playerdata") root = Node.void("playerdata")
root.add_child( root.add_child(Node.s32("result", 1)) # Unclear if this is the right thing to do here.
Node.s32("result", 1)
) # Unclear if this is the right thing to do here.
return root return root
# Extract new profile info from old profile # Extract new profile info from old profile
@ -258,14 +250,10 @@ class TheStarBishiBashi(
return self.format_profile(userid, profiletype, profile) return self.format_profile(userid, profiletype, profile)
else: else:
root = Node.void("playerdata") root = Node.void("playerdata")
root.add_child( root.add_child(Node.s32("result", 1)) # Unclear if this is the right thing to do here.
Node.s32("result", 1)
) # Unclear if this is the right thing to do here.
return root return root
def format_profile( def format_profile(self, userid: UserID, profiletype: str, profile: Profile) -> Node:
self, userid: UserID, profiletype: str, profile: Profile
) -> Node:
root = Node.void("playerdata") root = Node.void("playerdata")
root.add_child(Node.s32("result", 0)) root.add_child(Node.s32("result", 0))
player = Node.void("player") player = Node.void("player")
@ -342,9 +330,7 @@ class TheStarBishiBashi(
player.add_child(Node.u32("record_num", records)) player.add_child(Node.u32("record_num", records))
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile, is_new: bool) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile, is_new: bool
) -> Profile:
# Profile save request, data values are base64 encoded. # Profile save request, data values are base64 encoded.
# d is a CSV, and bin1 is binary data. # d is a CSV, and bin1 is binary data.
newprofile = oldprofile.clone() newprofile = oldprofile.clone()

View File

@ -43,10 +43,7 @@ class CardManagerHandler(Base):
refid = self.data.local.user.get_refid(self.game, self.version, userid) refid = self.data.local.user.get_refid(self.game, self.version, userid)
paseli_enabled = self.supports_paseli and self.config.paseli.enabled paseli_enabled = self.supports_paseli and self.config.paseli.enabled
newflag = ( newflag = self.data.remote.user.get_any_profile(self.game, self.version, userid) is None
self.data.remote.user.get_any_profile(self.game, self.version, userid)
is None
)
root = Node.void("cardmng") root = Node.void("cardmng")
root.set_attribute("refid", refid) root.set_attribute("refid", refid)
@ -81,9 +78,7 @@ class CardManagerHandler(Base):
else: else:
valid = False valid = False
root = Node.void("cardmng") root = Node.void("cardmng")
root.set_attribute( root.set_attribute("status", str(Status.SUCCESS if valid else Status.INVALID_PIN))
"status", str(Status.SUCCESS if valid else Status.INVALID_PIN)
)
return root return root
def handle_cardmng_getrefid_request(self, request: Node) -> Node: def handle_cardmng_getrefid_request(self, request: Node) -> Node:

View File

@ -177,9 +177,7 @@ class CoreHandler(Base):
root = Node.void("facility") root = Node.void("facility")
root.set_attribute("expire", "600") root.set_attribute("expire", "600")
location = Node.void("location") location = Node.void("location")
location.add_child( location.add_child(Node.string("id", ID.format_machine_id(machine.id, region=country)))
Node.string("id", ID.format_machine_id(machine.id, region=country))
)
location.add_child(Node.string("country", country)) location.add_child(Node.string("country", country))
location.add_child(Node.string("region", regionstr)) location.add_child(Node.string("region", regionstr))
location.add_child(Node.string("name", machine.name)) location.add_child(Node.string("name", machine.name))
@ -213,21 +211,11 @@ class CoreHandler(Base):
eapass.add_child(Node.u16("valid", 365)) eapass.add_child(Node.u16("valid", 365))
url = Node.void("url") url = Node.void("url")
url.add_child( url.add_child(Node.string("eapass", self.config.server.uri or "www.ea-pass.konami.net"))
Node.string("eapass", self.config.server.uri or "www.ea-pass.konami.net") url.add_child(Node.string("arcadefan", self.config.server.uri or "www.konami.jp/am"))
) url.add_child(Node.string("konaminetdx", self.config.server.uri or "http://am.573.jp"))
url.add_child( url.add_child(Node.string("konamiid", self.config.server.uri or "https://id.konami.net"))
Node.string("arcadefan", self.config.server.uri or "www.konami.jp/am") url.add_child(Node.string("eagate", self.config.server.uri or "http://eagate.573.jp"))
)
url.add_child(
Node.string("konaminetdx", self.config.server.uri or "http://am.573.jp")
)
url.add_child(
Node.string("konamiid", self.config.server.uri or "https://id.konami.net")
)
url.add_child(
Node.string("eagate", self.config.server.uri or "http://eagate.573.jp")
)
share.add_child(eacoin) share.add_child(eacoin)
share.add_child(url) share.add_child(url)

View File

@ -65,9 +65,7 @@ class PASELIHandler(Base):
# enabled, so there's no way to find a balance. # enabled, so there's no way to find a balance.
balance = 0 balance = 0
else: else:
balance = self.data.local.user.get_balance( balance = self.data.local.user.get_balance(userid, self.config.machine.arcade)
userid, self.config.machine.arcade
)
root.add_child(Node.s16("sequence", 0)) root.add_child(Node.s16("sequence", 0))
root.add_child(Node.u8("acstatus", 0)) root.add_child(Node.u8("acstatus", 0))
@ -158,17 +156,13 @@ class PASELIHandler(Base):
else: else:
# Look up the new balance based on this delta. If there isn't enough, # Look up the new balance based on this delta. If there isn't enough,
# we will end up returning None here and exit without performing. # we will end up returning None here and exit without performing.
balance = self.data.local.user.update_balance( balance = self.data.local.user.update_balance(userid, self.config.machine.arcade, -payment)
userid, self.config.machine.arcade, -payment
)
if balance is None: if balance is None:
print("Not enough balance for eacoin consume request") print("Not enough balance for eacoin consume request")
return make_resp( return make_resp(
1, 1,
self.data.local.user.get_balance( self.data.local.user.get_balance(userid, self.config.machine.arcade),
userid, self.config.machine.arcade
),
) )
else: else:
self.data.local.network.put_event( self.data.local.network.put_event(
@ -253,16 +247,13 @@ class PASELIHandler(Base):
end_of_week = beginning_of_today end_of_week = beginning_of_today
beginning_of_week = end_of_week - Time.SECONDS_IN_WEEK beginning_of_week = end_of_week - Time.SECONDS_IN_WEEK
topic.add_child( topic.add_child(Node.string("sumfrom", Time.format(beginning_of_week, date_format)))
Node.string("sumfrom", Time.format(beginning_of_week, date_format))
)
topic.add_child(Node.string("sumto", Time.format(end_of_week, date_format))) topic.add_child(Node.string("sumto", Time.format(end_of_week, date_format)))
today_total = sum( today_total = sum(
[ [
-event.data.get_int("delta") -event.data.get_int("delta")
for event in events for event in events
if event.timestamp >= beginning_of_today if event.timestamp >= beginning_of_today and event.timestamp < end_of_today
and event.timestamp < end_of_today
] ]
) )
@ -270,15 +261,13 @@ class PASELIHandler(Base):
[ [
-event.data.get_int("delta") -event.data.get_int("delta")
for event in events for event in events
if event.timestamp >= beginning_of_today if event.timestamp >= beginning_of_today and event.timestamp < end_of_today
and event.timestamp < end_of_today
] ]
) )
week_txns = [ week_txns = [
-event.data.get_int("delta") -event.data.get_int("delta")
for event in events for event in events
if event.timestamp >= beginning_of_week if event.timestamp >= beginning_of_week and event.timestamp < end_of_week
and event.timestamp < end_of_week
] ]
week_total = sum(week_txns) week_total = sum(week_txns)
if len(week_txns) > 0: if len(week_txns) > 0:
@ -298,8 +287,7 @@ class PASELIHandler(Base):
[ [
-event.data.get_int("delta") -event.data.get_int("delta")
for event in events for event in events
if event.timestamp >= start_of_day if event.timestamp >= start_of_day and event.timestamp < end_of_day
and event.timestamp < end_of_day
] ]
) )
) )
@ -317,14 +305,10 @@ class PASELIHandler(Base):
topic.add_child( topic.add_child(
Node.string( Node.string(
"sumfrom", "sumfrom",
Time.format( Time.format(end_of_52_weeks - (52 * Time.SECONDS_IN_WEEK), date_format),
end_of_52_weeks - (52 * Time.SECONDS_IN_WEEK), date_format
),
) )
) )
topic.add_child( topic.add_child(Node.string("sumto", Time.format(end_of_52_weeks, date_format)))
Node.string("sumto", Time.format(end_of_52_weeks, date_format))
)
# We index backwards, where index 0 = the first week back, 1 = the next week back after that, etc... # We index backwards, where index 0 = the first week back, 1 = the next week back after that, etc...
items = [] items = []
@ -337,8 +321,7 @@ class PASELIHandler(Base):
[ [
-event.data.get_int("delta") -event.data.get_int("delta")
for event in events for event in events
if event.timestamp >= beginning_of_range if event.timestamp >= beginning_of_range and event.timestamp < end_of_range
and event.timestamp < end_of_range
] ]
) )
) )
@ -366,9 +349,7 @@ class PASELIHandler(Base):
hours = [0] * 24 hours = [0] * 24
for event in events: for event in events:
event_hour = int( event_hour = int((event.timestamp % Time.SECONDS_IN_DAY) / Time.SECONDS_IN_HOUR)
(event.timestamp % Time.SECONDS_IN_DAY) / Time.SECONDS_IN_HOUR
)
hours[event_hour] = hours[event_hour] - event.data.get_int("delta") hours[event_hour] = hours[event_hour] - event.data.get_int("delta")
if event.timestamp < start_ts: if event.timestamp < start_ts:
start_ts = event.timestamp start_ts = event.timestamp
@ -399,15 +380,11 @@ class PASELIHandler(Base):
item = Node.void("item") item = Node.void("item")
history.add_child(item) history.add_child(item)
item.add_child( item.add_child(Node.string("date", Time.format(event.timestamp, time_format)))
Node.string("date", Time.format(event.timestamp, time_format))
)
item.add_child(Node.s32("consume", -event.data.get_int("delta"))) item.add_child(Node.s32("consume", -event.data.get_int("delta")))
item.add_child(Node.s32("service", -event.data.get_int("service"))) item.add_child(Node.s32("service", -event.data.get_int("service")))
item.add_child(Node.string("cardtype", "")) item.add_child(Node.string("cardtype", ""))
item.add_child( item.add_child(Node.string("cardno", " " * self.paseli_padding + card_no))
Node.string("cardno", " " * self.paseli_padding + card_no)
)
item.add_child(Node.string("title", "")) item.add_child(Node.string("title", ""))
item.add_child(Node.string("systemid", "")) item.add_child(Node.string("systemid", ""))
@ -417,9 +394,7 @@ class PASELIHandler(Base):
last_month = Time.timestamp_from_date(year, month - 1) last_month = Time.timestamp_from_date(year, month - 1)
month_before = Time.timestamp_from_date(year, month - 2) month_before = Time.timestamp_from_date(year, month - 2)
topic.add_child( topic.add_child(Node.string("sumfrom", Time.format(month_before, date_format)))
Node.string("sumfrom", Time.format(month_before, date_format))
)
topic.add_child(Node.string("sumto", Time.format(this_month, date_format))) topic.add_child(Node.string("sumto", Time.format(this_month, date_format)))
for start, end in [(month_before, last_month), (last_month, this_month)]: for start, end in [(month_before, last_month), (last_month, this_month)]:
@ -439,8 +414,7 @@ class PASELIHandler(Base):
[ [
-event.data.get_int("delta") -event.data.get_int("delta")
for event in events for event in events
if event.timestamp >= begin_ts if event.timestamp >= begin_ts and event.timestamp < end_ts
and event.timestamp < end_ts
] ]
) )
) )

View File

@ -127,18 +127,14 @@ class DDRBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
return Node.void("game") return Node.void("game")
def format_scores( def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
self, userid: UserID, profile: Profile, scores: List[Score]
) -> Node:
""" """
Base handler for a score list. Given a userid, profile and a score list, Base handler for a score list. Given a userid, profile and a score list,
return a Node representing a score list. Should be overridden. return a Node representing a score list. Should be overridden.
""" """
return Node.void("game") return Node.void("game")
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
""" """
Base handler for profile parsing. Given a request and an old profile, Base handler for profile parsing. Given a request and an old profile,
return a new profile that's been updated with the contents of the request. return a new profile that's been updated with the contents of the request.
@ -164,9 +160,7 @@ class DDRBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# Now, return it # Now, return it
return self.format_profile(userid, profile) return self.format_profile(userid, profile)
def new_profile_by_refid( def new_profile_by_refid(self, refid: Optional[str], name: Optional[str], area: Optional[int]) -> None:
self, refid: Optional[str], name: Optional[str], area: Optional[int]
) -> None:
""" """
Given a RefID and a name/area, create a new profile. Given a RefID and a name/area, create a new profile.
""" """

View File

@ -63,10 +63,7 @@ class DDRGameHiscoreHandler(DDRBase):
sortedrecords[score.id] = {} sortedrecords[score.id] = {}
sortedrecords[score.id][score.chart] = (userid, score) sortedrecords[score.id][score.chart] = (userid, score)
missing_profiles.append(userid) missing_profiles.append(userid)
users = { users = {userid: profile for (userid, profile) in self.get_any_profiles(missing_profiles)}
userid: profile
for (userid, profile) in self.get_any_profiles(missing_profiles)
}
game = Node.void("game") game = Node.void("game")
for song in sortedrecords: for song in sortedrecords:
@ -90,11 +87,7 @@ class DDRGameHiscoreHandler(DDRBase):
typenode.add_child(Node.string("name", users[userid].get_str("name"))) typenode.add_child(Node.string("name", users[userid].get_str("name")))
typenode.add_child(Node.u32("score", score.points)) typenode.add_child(Node.u32("score", score.points))
typenode.add_child( typenode.add_child(Node.u16("area", users[userid].get_int("area", self.get_machine_region())))
Node.u16(
"area", users[userid].get_int("area", self.get_machine_region())
)
)
typenode.add_child(Node.u8("rank", gamerank)) typenode.add_child(Node.u8("rank", gamerank))
typenode.add_child(Node.u8("combo_type", combo_type)) typenode.add_child(Node.u8("combo_type", combo_type))
typenode.add_child(Node.u32("code", users[userid].extid)) typenode.add_child(Node.u32("code", users[userid].extid))
@ -109,16 +102,12 @@ class DDRGameAreaHiscoreHandler(DDRBase):
# First, get all users that are in the current shop's area # First, get all users that are in the current shop's area
area_users = { area_users = {
uid: prof uid: prof
for (uid, prof) in self.data.local.user.get_all_profiles( for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version)
self.game, self.version
)
if prof.get_int("area", self.get_machine_region()) == shop_area if prof.get_int("area", self.get_machine_region()) == shop_area
} }
# Second, look up records belonging only to those users # Second, look up records belonging only to those users
records = self.data.local.music.get_all_records( records = self.data.local.music.get_all_records(self.game, self.music_version, userlist=list(area_users.keys()))
self.game, self.music_version, userlist=list(area_users.keys())
)
# Now, do the same lazy thing as 'hiscore' because I don't want # Now, do the same lazy thing as 'hiscore' because I don't want
# to think about how to change this knowing that we only pulled # to think about how to change this knowing that we only pulled
@ -137,10 +126,7 @@ class DDRGameAreaHiscoreHandler(DDRBase):
for chart in area_records[song]: for chart in area_records[song]:
userid, score = area_records[song][chart] userid, score = area_records[song][chart]
if ( if area_users[userid].get_int("area", self.get_machine_region()) != shop_area:
area_users[userid].get_int("area", self.get_machine_region())
!= shop_area
):
# Don't return this, this user isn't in this area # Don't return this, this user isn't in this area
continue continue
try: try:
@ -155,9 +141,7 @@ class DDRGameAreaHiscoreHandler(DDRBase):
music.add_child(typenode) music.add_child(typenode)
typenode.set_attribute("diff", str(gamechart)) typenode.set_attribute("diff", str(gamechart))
typenode.add_child( typenode.add_child(Node.string("name", area_users[userid].get_str("name")))
Node.string("name", area_users[userid].get_str("name"))
)
typenode.add_child(Node.u32("score", score.points)) typenode.add_child(Node.u32("score", score.points))
typenode.add_child( typenode.add_child(
Node.u16( Node.u16(
@ -309,9 +293,7 @@ class DDRGameOldHandler(DDRBase):
oldprofile = previous_version.get_profile(userid) oldprofile = previous_version.get_profile(userid)
if oldprofile is not None: if oldprofile is not None:
game.set_attribute("name", oldprofile.get_str("name")) game.set_attribute("name", oldprofile.get_str("name"))
game.set_attribute( game.set_attribute("area", str(oldprofile.get_int("area", self.get_machine_region())))
"area", str(oldprofile.get_int("area", self.get_machine_region()))
)
return game return game
@ -361,9 +343,7 @@ class DDRGameFriendHandler(DDRBase):
game.set_attribute("data", "1") game.set_attribute("data", "1")
game.add_child(Node.u32("code", friend.extid)) game.add_child(Node.u32("code", friend.extid))
game.add_child(Node.string("name", friend.get_str("name"))) game.add_child(Node.string("name", friend.get_str("name")))
game.add_child( game.add_child(Node.u8("area", friend.get_int("area", self.get_machine_region())))
Node.u8("area", friend.get_int("area", self.get_machine_region()))
)
game.add_child(Node.u32("exp", play_stats.get_int("exp"))) game.add_child(Node.u32("exp", play_stats.get_int("exp")))
game.add_child(Node.u32("star", friend.get_int("star"))) game.add_child(Node.u32("star", friend.get_int("star")))
@ -421,9 +401,7 @@ class DDRGameLoadCourseHandler(DDRBase):
coursedata = [0] * 3200 coursedata = [0] * 3200
if userid is not None: if userid is not None:
for course in self.data.local.user.get_achievements( for course in self.data.local.user.get_achievements(self.game, self.version, userid):
self.game, self.version, userid
):
if course.type != "course": if course.type != "course":
continue continue
@ -438,9 +416,7 @@ class DDRGameLoadCourseHandler(DDRBase):
coursedata[index + 0] = int(course.data.get_int("score") / 10000) coursedata[index + 0] = int(course.data.get_int("score") / 10000)
coursedata[index + 1] = course.data.get_int("score") % 10000 coursedata[index + 1] = course.data.get_int("score") % 10000
coursedata[index + 2] = course.data.get_int("combo") coursedata[index + 2] = course.data.get_int("combo")
coursedata[index + 3] = self.db_to_game_rank( coursedata[index + 3] = self.db_to_game_rank(course.data.get_int("rank"))
course.data.get_int("rank")
)
coursedata[index + 5] = course.data.get_int("stage") coursedata[index + 5] = course.data.get_int("stage")
coursedata[index + 6] = course.data.get_int("combo_type") coursedata[index + 6] = course.data.get_int("combo_type")

View File

@ -171,9 +171,7 @@ class DDR2013(
flag.set_attribute("area", str(self.get_machine_region())) flag.set_attribute("area", str(self.get_machine_region()))
flag.set_attribute("is_final", "1") flag.set_attribute("is_final", "1")
hit_chart = self.data.local.music.get_hit_chart( hit_chart = self.data.local.music.get_hit_chart(self.game, self.music_version, self.GAME_MAX_SONGS)
self.game, self.music_version, self.GAME_MAX_SONGS
)
counts_by_reflink = [0] * self.GAME_MAX_SONGS counts_by_reflink = [0] * self.GAME_MAX_SONGS
for reflink, plays in hit_chart: for reflink, plays in hit_chart:
if reflink >= 0 and reflink < self.GAME_MAX_SONGS: if reflink >= 0 and reflink < self.GAME_MAX_SONGS:
@ -194,9 +192,7 @@ class DDR2013(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
else: else:
scores = [] scores = []
@ -284,14 +280,10 @@ class DDR2013(
root.add_child(Node.string("seq", "")) root.add_child(Node.string("seq", ""))
root.add_child(Node.u32("code", profile.extid)) root.add_child(Node.u32("code", profile.extid))
root.add_child(Node.string("name", profile.get_str("name"))) root.add_child(Node.string("name", profile.get_str("name")))
root.add_child( root.add_child(Node.u8("area", profile.get_int("area", self.get_machine_region())))
Node.u8("area", profile.get_int("area", self.get_machine_region()))
)
root.add_child(Node.u32("cnt_s", play_stats.get_int("single_plays"))) root.add_child(Node.u32("cnt_s", play_stats.get_int("single_plays")))
root.add_child(Node.u32("cnt_d", play_stats.get_int("double_plays"))) root.add_child(Node.u32("cnt_d", play_stats.get_int("double_plays")))
root.add_child( root.add_child(Node.u32("cnt_b", play_stats.get_int("battle_plays"))) # This could be wrong, its a guess
Node.u32("cnt_b", play_stats.get_int("battle_plays"))
) # This could be wrong, its a guess
root.add_child(Node.u32("cnt_m0", play_stats.get_int("cnt_m0"))) root.add_child(Node.u32("cnt_m0", play_stats.get_int("cnt_m0")))
root.add_child(Node.u32("cnt_m1", play_stats.get_int("cnt_m1"))) root.add_child(Node.u32("cnt_m1", play_stats.get_int("cnt_m1")))
root.add_child(Node.u32("cnt_m2", play_stats.get_int("cnt_m2"))) root.add_child(Node.u32("cnt_m2", play_stats.get_int("cnt_m2")))
@ -309,11 +301,7 @@ class DDR2013(
chara = Node.void("chara") chara = Node.void("chara")
root.add_child(chara) root.add_child(chara)
chara.set_attribute("my", str(profile.get_int("chara", 30))) chara.set_attribute("my", str(profile.get_int("chara", 30)))
root.add_child( root.add_child(Node.u16_array("chara_opt", profile.get_int_array("chara_opt", 96, [208] * 96)))
Node.u16_array(
"chara_opt", profile.get_int_array("chara_opt", 96, [208] * 96)
)
)
# Drill rankings # Drill rankings
if "title_gr" in profile: if "title_gr" in profile:
@ -361,9 +349,7 @@ class DDR2013(
last.set_attribute("rival1", str(lastdict.get_int("rival1", -1))) last.set_attribute("rival1", str(lastdict.get_int("rival1", -1)))
last.set_attribute("rival2", str(lastdict.get_int("rival2", -1))) last.set_attribute("rival2", str(lastdict.get_int("rival2", -1)))
last.set_attribute("rival3", str(lastdict.get_int("rival3", -1))) last.set_attribute("rival3", str(lastdict.get_int("rival3", -1)))
last.set_attribute( last.set_attribute("fri", str(lastdict.get_int("rival1", -1))) # This literally goes to the same memory in 2013
"fri", str(lastdict.get_int("rival1", -1))
) # This literally goes to the same memory in 2013
last.set_attribute("style", str(lastdict.get_int("style"))) last.set_attribute("style", str(lastdict.get_int("style")))
last.set_attribute("mode", str(lastdict.get_int("mode"))) last.set_attribute("mode", str(lastdict.get_int("mode")))
last.set_attribute("cate", str(lastdict.get_int("cate"))) last.set_attribute("cate", str(lastdict.get_int("cate")))
@ -407,9 +393,7 @@ class DDR2013(
root.add_child(Node.s16_array("opt_ex", profile.get_int_array("opt_ex", 16))) root.add_child(Node.s16_array("opt_ex", profile.get_int_array("opt_ex", 16)))
# Unlock flags # Unlock flags
root.add_child( root.add_child(Node.u8_array("flag", profile.get_int_array("flag", 256, [1] * 256)))
Node.u8_array("flag", profile.get_int_array("flag", 256, [1] * 256))
)
# Ranking display? # Ranking display?
root.add_child(Node.u16_array("rank", profile.get_int_array("rank", 100))) root.add_child(Node.u16_array("rank", profile.get_int_array("rank", 100)))
@ -431,9 +415,7 @@ class DDR2013(
friendnode.set_attribute("up", "0") friendnode.set_attribute("up", "0")
friendnode.add_child(Node.u32("code", friend.extid)) friendnode.add_child(Node.u32("code", friend.extid))
friendnode.add_child(Node.string("name", friend.get_str("name"))) friendnode.add_child(Node.string("name", friend.get_str("name")))
friendnode.add_child( friendnode.add_child(Node.u8("area", friend.get_int("area", self.get_machine_region())))
Node.u8("area", friend.get_int("area", self.get_machine_region()))
)
friendnode.add_child(Node.u32("exp", play_stats.get_int("exp"))) friendnode.add_child(Node.u32("exp", play_stats.get_int("exp")))
friendnode.add_child(Node.u32("star", friend.get_int("star"))) friendnode.add_child(Node.u32("star", friend.get_int("star")))
@ -484,9 +466,7 @@ class DDR2013(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -691,9 +671,7 @@ class DDR2013(
newfriends[pos] = None newfriends[pos] = None
else: else:
# Try looking up the userid # Try looking up the userid
newfriends[pos] = self.data.remote.user.from_extid( newfriends[pos] = self.data.remote.user.from_extid(self.game, self.version, code)
self.game, self.version, code
)
# Diff the set of links to determine updates # Diff the set of links to determine updates
for i in range(10): for i in range(10):

View File

@ -166,9 +166,7 @@ class DDR2014(
flag.set_attribute("is_final", "0") flag.set_attribute("is_final", "0")
# Last month's hit chart # Last month's hit chart
hit_chart = self.data.local.music.get_hit_chart( hit_chart = self.data.local.music.get_hit_chart(self.game, self.music_version, self.GAME_MAX_SONGS, 30)
self.game, self.music_version, self.GAME_MAX_SONGS, 30
)
counts_by_reflink = [0] * self.GAME_MAX_SONGS counts_by_reflink = [0] * self.GAME_MAX_SONGS
for reflink, plays in hit_chart: for reflink, plays in hit_chart:
if reflink >= 0 and reflink < self.GAME_MAX_SONGS: if reflink >= 0 and reflink < self.GAME_MAX_SONGS:
@ -176,9 +174,7 @@ class DDR2014(
game.add_child(Node.u32_array("cnt_music_monthly", counts_by_reflink)) game.add_child(Node.u32_array("cnt_music_monthly", counts_by_reflink))
# Last week's hit chart # Last week's hit chart
hit_chart = self.data.local.music.get_hit_chart( hit_chart = self.data.local.music.get_hit_chart(self.game, self.music_version, self.GAME_MAX_SONGS, 7)
self.game, self.music_version, self.GAME_MAX_SONGS, 7
)
counts_by_reflink = [0] * self.GAME_MAX_SONGS counts_by_reflink = [0] * self.GAME_MAX_SONGS
for reflink, plays in hit_chart: for reflink, plays in hit_chart:
if reflink >= 0 and reflink < self.GAME_MAX_SONGS: if reflink >= 0 and reflink < self.GAME_MAX_SONGS:
@ -186,9 +182,7 @@ class DDR2014(
game.add_child(Node.u32_array("cnt_music_weekly", counts_by_reflink)) game.add_child(Node.u32_array("cnt_music_weekly", counts_by_reflink))
# Last day's hit chart # Last day's hit chart
hit_chart = self.data.local.music.get_hit_chart( hit_chart = self.data.local.music.get_hit_chart(self.game, self.music_version, self.GAME_MAX_SONGS, 1)
self.game, self.music_version, self.GAME_MAX_SONGS, 1
)
counts_by_reflink = [0] * self.GAME_MAX_SONGS counts_by_reflink = [0] * self.GAME_MAX_SONGS
for reflink, plays in hit_chart: for reflink, plays in hit_chart:
if reflink >= 0 and reflink < self.GAME_MAX_SONGS: if reflink >= 0 and reflink < self.GAME_MAX_SONGS:
@ -209,9 +203,7 @@ class DDR2014(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
else: else:
scores = [] scores = []
@ -338,14 +330,10 @@ class DDR2014(
root.add_child(Node.string("seq", "")) root.add_child(Node.string("seq", ""))
root.add_child(Node.u32("code", profile.extid)) root.add_child(Node.u32("code", profile.extid))
root.add_child(Node.string("name", profile.get_str("name"))) root.add_child(Node.string("name", profile.get_str("name")))
root.add_child( root.add_child(Node.u8("area", profile.get_int("area", self.get_machine_region())))
Node.u8("area", profile.get_int("area", self.get_machine_region()))
)
root.add_child(Node.u32("cnt_s", play_stats.get_int("single_plays"))) root.add_child(Node.u32("cnt_s", play_stats.get_int("single_plays")))
root.add_child(Node.u32("cnt_d", play_stats.get_int("double_plays"))) root.add_child(Node.u32("cnt_d", play_stats.get_int("double_plays")))
root.add_child( root.add_child(Node.u32("cnt_b", play_stats.get_int("battle_plays"))) # This could be wrong, its a guess
Node.u32("cnt_b", play_stats.get_int("battle_plays"))
) # This could be wrong, its a guess
root.add_child(Node.u32("cnt_m0", play_stats.get_int("cnt_m0"))) root.add_child(Node.u32("cnt_m0", play_stats.get_int("cnt_m0")))
root.add_child(Node.u32("cnt_m1", play_stats.get_int("cnt_m1"))) root.add_child(Node.u32("cnt_m1", play_stats.get_int("cnt_m1")))
root.add_child(Node.u32("cnt_m2", play_stats.get_int("cnt_m2"))) root.add_child(Node.u32("cnt_m2", play_stats.get_int("cnt_m2")))
@ -363,11 +351,7 @@ class DDR2014(
chara = Node.void("chara") chara = Node.void("chara")
root.add_child(chara) root.add_child(chara)
chara.set_attribute("my", str(profile.get_int("chara", 30))) chara.set_attribute("my", str(profile.get_int("chara", 30)))
root.add_child( root.add_child(Node.u16_array("chara_opt", profile.get_int_array("chara_opt", 96, [208] * 96)))
Node.u16_array(
"chara_opt", profile.get_int_array("chara_opt", 96, [208] * 96)
)
)
# Drill rankings # Drill rankings
if "title_gr" in profile: if "title_gr" in profile:
@ -420,9 +404,7 @@ class DDR2014(
last.set_attribute("rival1", str(lastdict.get_int("rival1", -1))) last.set_attribute("rival1", str(lastdict.get_int("rival1", -1)))
last.set_attribute("rival2", str(lastdict.get_int("rival2", -1))) last.set_attribute("rival2", str(lastdict.get_int("rival2", -1)))
last.set_attribute("rival3", str(lastdict.get_int("rival3", -1))) last.set_attribute("rival3", str(lastdict.get_int("rival3", -1)))
last.set_attribute( last.set_attribute("fri", str(lastdict.get_int("rival1", -1))) # This literally goes to the same memory in 2014
"fri", str(lastdict.get_int("rival1", -1))
) # This literally goes to the same memory in 2014
last.set_attribute("style", str(lastdict.get_int("style"))) last.set_attribute("style", str(lastdict.get_int("style")))
last.set_attribute("mode", str(lastdict.get_int("mode"))) last.set_attribute("mode", str(lastdict.get_int("mode")))
last.set_attribute("cate", str(lastdict.get_int("cate"))) last.set_attribute("cate", str(lastdict.get_int("cate")))
@ -462,17 +444,11 @@ class DDR2014(
root.add_child(option_ver) root.add_child(option_ver)
option_ver.set_attribute("ver", str(profile.get_int("option_ver", 2))) option_ver.set_attribute("ver", str(profile.get_int("option_ver", 2)))
if "option_02" in profile: if "option_02" in profile:
root.add_child( root.add_child(Node.s16_array("option_02", profile.get_int_array("option_02", 24)))
Node.s16_array("option_02", profile.get_int_array("option_02", 24))
)
# Unlock flags # Unlock flags
root.add_child( root.add_child(Node.u8_array("flag", profile.get_int_array("flag", 512, [1] * 512)[:256]))
Node.u8_array("flag", profile.get_int_array("flag", 512, [1] * 512)[:256]) root.add_child(Node.u8_array("flag_ex", profile.get_int_array("flag", 512, [1] * 512)))
)
root.add_child(
Node.u8_array("flag_ex", profile.get_int_array("flag", 512, [1] * 512))
)
# Ranking display? # Ranking display?
root.add_child(Node.u16_array("rank", profile.get_int_array("rank", 100))) root.add_child(Node.u16_array("rank", profile.get_int_array("rank", 100)))
@ -494,9 +470,7 @@ class DDR2014(
friendnode.set_attribute("up", "0") friendnode.set_attribute("up", "0")
friendnode.add_child(Node.u32("code", friend.extid)) friendnode.add_child(Node.u32("code", friend.extid))
friendnode.add_child(Node.string("name", friend.get_str("name"))) friendnode.add_child(Node.string("name", friend.get_str("name")))
friendnode.add_child( friendnode.add_child(Node.u8("area", friend.get_int("area", self.get_machine_region())))
Node.u8("area", friend.get_int("area", self.get_machine_region()))
)
friendnode.add_child(Node.u32("exp", play_stats.get_int("exp"))) friendnode.add_child(Node.u32("exp", play_stats.get_int("exp")))
friendnode.add_child(Node.u32("star", friend.get_int("star"))) friendnode.add_child(Node.u32("star", friend.get_int("star")))
@ -553,9 +527,7 @@ class DDR2014(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -760,9 +732,7 @@ class DDR2014(
newfriends[pos] = None newfriends[pos] = None
else: else:
# Try looking up the userid # Try looking up the userid
newfriends[pos] = self.data.remote.user.from_extid( newfriends[pos] = self.data.remote.user.from_extid(self.game, self.version, code)
self.game, self.version, code
)
# Diff the set of links to determine updates # Diff the set of links to determine updates
for i in range(10): for i in range(10):

View File

@ -113,9 +113,7 @@ class DDRAce(
return DDR2014(self.data, self.config, self.model) return DDR2014(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
# DDR Ace has a weird bug where it sends a profile save for a blank # DDR Ace has a weird bug where it sends a profile save for a blank
# profile before reading it back when creating a new profile. If there # profile before reading it back when creating a new profile. If there
# is no profile on read-back, it errors out, and it also uses the name # is no profile on read-back, it errors out, and it also uses the name
@ -134,10 +132,7 @@ class DDRAce(
events = [] events = []
for userid, profile in profiles: for userid, profile in profiles:
if ( if profile.get_str("name") == "" and profile.get_int("write_time") < several_minutes_ago:
profile.get_str("name") == ""
and profile.get_int("write_time") < several_minutes_ago
):
data.local.user.delete_profile(cls.game, cls.version, userid) data.local.user.delete_profile(cls.game, cls.version, userid)
events.append( events.append(
( (
@ -255,21 +250,15 @@ class DDRAce(
tax.add_child(Node.s32("phase", 0)) tax.add_child(Node.s32("phase", 0))
return tax return tax
def __handle_userload( def __handle_userload(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None:
self, userid: Optional[UserID], requestdata: Node, response: Node
) -> None:
has_profile: bool = False has_profile: bool = False
achievements: List[Achievement] = [] achievements: List[Achievement] = []
scores: List[Score] = [] scores: List[Score] = []
if userid is not None: if userid is not None:
has_profile = self.has_profile(userid) has_profile = self.has_profile(userid)
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
)
scores = self.data.remote.music.get_scores(
self.game, self.music_version, userid
)
# Place scores into an arrangement for easier distribution to Ace. # Place scores into an arrangement for easier distribution to Ace.
scores_by_mcode: Dict[int, List[Optional[Score]]] = {} scores_by_mcode: Dict[int, List[Optional[Score]]] = {}
@ -304,11 +293,7 @@ class DDRAce(
note.add_child(Node.s32("ghostid", 0)) note.add_child(Node.s32("ghostid", 0))
else: else:
note.add_child(Node.u16("count", score.plays)) note.add_child(Node.u16("count", score.plays))
note.add_child( note.add_child(Node.u8("rank", self.db_to_game_rank(score.data.get_int("rank"))))
Node.u8(
"rank", self.db_to_game_rank(score.data.get_int("rank"))
)
)
note.add_child( note.add_child(
Node.u8( Node.u8(
"clearkind", "clearkind",
@ -401,9 +386,7 @@ class DDRAce(
eventdata.add_child(Node.u32("eventno", 0)) eventdata.add_child(Node.u32("eventno", 0))
eventdata.add_child(Node.s64("condition", 0)) eventdata.add_child(Node.s64("condition", 0))
eventdata.add_child(Node.u32("reward", 0)) eventdata.add_child(Node.u32("reward", 0))
eventdata.add_child( eventdata.add_child(Node.s32("comptime", 1 if playerstats.get_bool("completed") else 0))
Node.s32("comptime", 1 if playerstats.get_bool("completed") else 0)
)
eventdata.add_child(Node.s64("savedata", 0)) eventdata.add_child(Node.s64("savedata", 0))
for evtprogress in progress: for evtprogress in progress:
@ -414,21 +397,11 @@ class DDRAce(
eventdata.add_child(Node.s32("eventtype", int(evtprogress.type))) eventdata.add_child(Node.s32("eventtype", int(evtprogress.type)))
eventdata.add_child(Node.u32("eventno", 0)) eventdata.add_child(Node.u32("eventno", 0))
eventdata.add_child(Node.s64("condition", 0)) eventdata.add_child(Node.s64("condition", 0))
eventdata.add_child( eventdata.add_child(Node.u32("reward", rewards.get(evtprogress.type, {}).get(evtprogress.id)))
Node.u32( eventdata.add_child(Node.s32("comptime", 1 if evtprogress.data.get_bool("completed") else 0))
"reward", rewards.get(evtprogress.type, {}).get(evtprogress.id) eventdata.add_child(Node.s64("savedata", evtprogress.data.get_int("progress")))
)
)
eventdata.add_child(
Node.s32("comptime", 1 if evtprogress.data.get_bool("completed") else 0)
)
eventdata.add_child(
Node.s64("savedata", evtprogress.data.get_int("progress"))
)
def __handle_usersave( def __handle_usersave(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None:
self, userid: Optional[UserID], requestdata: Node, response: Node
) -> None:
if userid is None: if userid is None:
# the game sends us empty user ID strings when a guest is playing. # the game sends us empty user ID strings when a guest is playing.
# Return early so it doesn't wait a minute and a half to show the # Return early so it doesn't wait a minute and a half to show the
@ -537,9 +510,7 @@ class DDRAce(
ghost=ghost, ghost=ghost,
) )
def __handle_rivalload( def __handle_rivalload(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None:
self, userid: Optional[UserID], requestdata: Node, response: Node
) -> None:
data = Node.void("data") data = Node.void("data")
response.add_child(data) response.add_child(data)
data.add_child(Node.s32("recordtype", requestdata.child_value("loadflag"))) data.add_child(Node.s32("recordtype", requestdata.child_value("loadflag")))
@ -567,9 +538,7 @@ class DDRAce(
if loadkind == self.GAME_RIVAL_TYPE_WORLD: if loadkind == self.GAME_RIVAL_TYPE_WORLD:
# Just load all scores for this network # Just load all scores for this network
scores = self.data.remote.music.get_all_records( scores = self.data.remote.music.get_all_records(self.game, self.music_version)
self.game, self.music_version
)
elif loadkind == self.GAME_RIVAL_TYPE_AREA: elif loadkind == self.GAME_RIVAL_TYPE_AREA:
if thismachine.arcade is not None: if thismachine.arcade is not None:
match_arcade = thismachine.arcade match_arcade = thismachine.arcade
@ -595,14 +564,10 @@ class DDRAce(
userids.append(userid) userids.append(userid)
# Load all scores for users in the area # Load all scores for users in the area
scores = self.data.local.music.get_all_records( scores = self.data.local.music.get_all_records(self.game, self.music_version, userlist=userids)
self.game, self.music_version, userlist=userids
)
elif loadkind == self.GAME_RIVAL_TYPE_MACHINE: elif loadkind == self.GAME_RIVAL_TYPE_MACHINE:
# Load up all scores and filter them by those earned at this location # Load up all scores and filter them by those earned at this location
scores = self.data.local.music.get_all_records( scores = self.data.local.music.get_all_records(self.game, self.music_version, locationlist=[thismachine.id])
self.game, self.music_version, locationlist=[thismachine.id]
)
elif loadkind in [ elif loadkind in [
self.GAME_RIVAL_TYPE_RIVAL1, self.GAME_RIVAL_TYPE_RIVAL1,
self.GAME_RIVAL_TYPE_RIVAL2, self.GAME_RIVAL_TYPE_RIVAL2,
@ -611,17 +576,13 @@ class DDRAce(
# Load up this user's highscores, format the way the below code expects it # Load up this user's highscores, format the way the below code expects it
extid = requestdata.child_value("ddrcode") extid = requestdata.child_value("ddrcode")
otherid = self.data.remote.user.from_extid(self.game, self.version, extid) otherid = self.data.remote.user.from_extid(self.game, self.version, extid)
userscores = self.data.remote.music.get_scores( userscores = self.data.remote.music.get_scores(self.game, self.music_version, otherid)
self.game, self.music_version, otherid
)
scores = [(otherid, score) for score in userscores] scores = [(otherid, score) for score in userscores]
else: else:
# Nothing here # Nothing here
scores = [] scores = []
missing_users = [ missing_users = [userid for (userid, _) in scores if userid not in profiles_by_userid]
userid for (userid, _) in scores if userid not in profiles_by_userid
]
for userid, profile in self.get_any_profiles(missing_users): for userid, profile in self.get_any_profiles(missing_users):
profiles_by_userid[userid] = profile profiles_by_userid[userid] = profile
@ -634,12 +595,8 @@ class DDRAce(
data.add_child(record) data.add_child(record)
record.add_child(Node.u32("mcode", score.id)) record.add_child(Node.u32("mcode", score.id))
record.add_child(Node.u8("notetype", self.db_to_game_chart(score.chart))) record.add_child(Node.u8("notetype", self.db_to_game_chart(score.chart)))
record.add_child( record.add_child(Node.u8("rank", self.db_to_game_rank(score.data.get_int("rank"))))
Node.u8("rank", self.db_to_game_rank(score.data.get_int("rank"))) record.add_child(Node.u8("clearkind", self.db_to_game_halo(score.data.get_int("halo"))))
)
record.add_child(
Node.u8("clearkind", self.db_to_game_halo(score.data.get_int("halo")))
)
record.add_child(Node.u8("flagdata", 0)) record.add_child(Node.u8("flagdata", 0))
record.add_child(Node.string("name", profiledata.get_str("name"))) record.add_child(Node.string("name", profiledata.get_str("name")))
record.add_child(Node.s32("area", profiledata.get_int("area", 58))) record.add_child(Node.s32("area", profiledata.get_int("area", 58)))
@ -647,9 +604,7 @@ class DDRAce(
record.add_child(Node.s32("score", score.points)) record.add_child(Node.s32("score", score.points))
record.add_child(Node.s32("ghostid", score.key)) record.add_child(Node.s32("ghostid", score.key))
def __handle_usernew( def __handle_usernew(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None:
self, userid: Optional[UserID], requestdata: Node, response: Node
) -> None:
if userid is None: if userid is None:
raise Exception("Expecting valid UserID to create new profile!") raise Exception("Expecting valid UserID to create new profile!")
@ -669,26 +624,18 @@ class DDRAce(
response.add_child(Node.s32("code", profile.extid)) response.add_child(Node.s32("code", profile.extid))
response.add_child(Node.string("shoparea", "")) response.add_child(Node.string("shoparea", ""))
def __handle_inheritance( def __handle_inheritance(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None:
self, userid: Optional[UserID], requestdata: Node, response: Node
) -> None:
if userid is not None: if userid is not None:
previous_version = self.previous_version() previous_version = self.previous_version()
profile = previous_version.get_profile(userid) profile = previous_version.get_profile(userid)
else: else:
profile = None profile = None
response.add_child( response.add_child(Node.s32("InheritanceStatus", 1 if profile is not None else 0))
Node.s32("InheritanceStatus", 1 if profile is not None else 0)
)
def __handle_ghostload( def __handle_ghostload(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None:
self, userid: Optional[UserID], requestdata: Node, response: Node
) -> None:
ghostid = requestdata.child_value("ghostid") ghostid = requestdata.child_value("ghostid")
ghost = self.data.local.music.get_score_by_key( ghost = self.data.local.music.get_score_by_key(self.game, self.music_version, ghostid)
self.game, self.music_version, ghostid
)
if ghost is None: if ghost is None:
return return
@ -708,9 +655,7 @@ class DDRAce(
ghostdata.add_child(Node.s32("ghostsize", len(score.data["ghost"]))) ghostdata.add_child(Node.s32("ghostsize", len(score.data["ghost"])))
ghostdata.add_child(Node.string("ghost", score.data["ghost"])) ghostdata.add_child(Node.string("ghost", score.data["ghost"]))
def handle_playerdata_usergamedata_advanced_request( def handle_playerdata_usergamedata_advanced_request(self, request: Node) -> Optional[Node]:
self, request: Node
) -> Optional[Node]:
playerdata = Node.void("playerdata") playerdata = Node.void("playerdata")
# DDR Ace decides to be difficult and have a third level of packet switching # DDR Ace decides to be difficult and have a third level of packet switching
@ -748,9 +693,7 @@ class DDRAce(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is not None: if userid is not None:
profile = self.get_profile(userid) or Profile( profile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
usergamedata = profile.get_dict("usergamedata") usergamedata = profile.get_dict("usergamedata")
for record in request.child("data/record").children: for record in request.child("data/record").children:
@ -781,30 +724,19 @@ class DDRAce(
profile.replace_bool( profile.replace_bool(
"workout_mode", "workout_mode",
int( int(
strdatalist[self.GAME_COMMON_WEIGHT_DISPLAY_OFFSET].decode( strdatalist[self.GAME_COMMON_WEIGHT_DISPLAY_OFFSET].decode("ascii"),
"ascii"
),
16, 16,
) )
!= 0, != 0,
) )
profile.replace_int( profile.replace_int(
"weight", "weight",
int( int(float(strdatalist[self.GAME_COMMON_WEIGHT_OFFSET].decode("ascii")) * 10),
float(
strdatalist[self.GAME_COMMON_WEIGHT_OFFSET].decode(
"ascii"
)
)
* 10
),
) )
profile.replace_int( profile.replace_int(
"character", "character",
int( int(
strdatalist[self.GAME_COMMON_CHARACTER_OFFSET].decode( strdatalist[self.GAME_COMMON_CHARACTER_OFFSET].decode("ascii"),
"ascii"
),
16, 16,
), ),
) )
@ -812,36 +744,28 @@ class DDRAce(
profile.replace_int( profile.replace_int(
"combo", "combo",
int( int(
strdatalist[self.GAME_OPTION_COMBO_POSITION_OFFSET].decode( strdatalist[self.GAME_OPTION_COMBO_POSITION_OFFSET].decode("ascii"),
"ascii"
),
16, 16,
), ),
) )
profile.replace_int( profile.replace_int(
"early_late", "early_late",
int( int(
strdatalist[self.GAME_OPTION_FAST_SLOW_OFFSET].decode( strdatalist[self.GAME_OPTION_FAST_SLOW_OFFSET].decode("ascii"),
"ascii"
),
16, 16,
), ),
) )
profile.replace_int( profile.replace_int(
"arrowskin", "arrowskin",
int( int(
strdatalist[self.GAME_OPTION_ARROW_SKIN_OFFSET].decode( strdatalist[self.GAME_OPTION_ARROW_SKIN_OFFSET].decode("ascii"),
"ascii"
),
16, 16,
), ),
) )
profile.replace_int( profile.replace_int(
"guidelines", "guidelines",
int( int(
strdatalist[self.GAME_OPTION_GUIDELINE_OFFSET].decode( strdatalist[self.GAME_OPTION_GUIDELINE_OFFSET].decode("ascii"),
"ascii"
),
16, 16,
), ),
) )
@ -907,45 +831,39 @@ class DDRAce(
old_profile = previous_version.get_profile(userid) old_profile = previous_version.get_profile(userid)
if old_profile is not None: if old_profile is not None:
name = old_profile.get_str("name") name = old_profile.get_str("name")
area = old_profile.get_int( area = old_profile.get_int("area", self.get_machine_region())
"area", self.get_machine_region()
)
else: else:
area = self.get_machine_region() area = self.get_machine_region()
common = usergamedata[ptype]["strdata"].split(b",") common = usergamedata[ptype]["strdata"].split(b",")
common[self.GAME_COMMON_NAME_OFFSET] = name.encode("ascii") common[self.GAME_COMMON_NAME_OFFSET] = name.encode("ascii")
common[self.GAME_COMMON_AREA_OFFSET] = acehex(area).encode( common[self.GAME_COMMON_AREA_OFFSET] = acehex(area).encode("ascii")
"ascii"
)
common[self.GAME_COMMON_WEIGHT_DISPLAY_OFFSET] = ( common[self.GAME_COMMON_WEIGHT_DISPLAY_OFFSET] = (
b"1" if profile.get_bool("workout_mode") else b"0" b"1" if profile.get_bool("workout_mode") else b"0"
) )
common[self.GAME_COMMON_WEIGHT_OFFSET] = str( common[self.GAME_COMMON_WEIGHT_OFFSET] = str(
float(profile.get_int("weight")) / 10.0 float(profile.get_int("weight")) / 10.0
).encode("ascii") ).encode("ascii")
common[self.GAME_COMMON_CHARACTER_OFFSET] = acehex( common[self.GAME_COMMON_CHARACTER_OFFSET] = acehex(profile.get_int("character")).encode(
profile.get_int("character") "ascii"
).encode("ascii") )
usergamedata[ptype]["strdata"] = b",".join(common) usergamedata[ptype]["strdata"] = b",".join(common)
if ptype == "OPTION": if ptype == "OPTION":
# Return user settings for frontend # Return user settings for frontend
option = usergamedata[ptype]["strdata"].split(b",") option = usergamedata[ptype]["strdata"].split(b",")
option[self.GAME_OPTION_FAST_SLOW_OFFSET] = acehex( option[self.GAME_OPTION_FAST_SLOW_OFFSET] = acehex(profile.get_int("early_late")).encode(
profile.get_int("early_late") "ascii"
).encode("ascii") )
option[self.GAME_OPTION_COMBO_POSITION_OFFSET] = acehex( option[self.GAME_OPTION_COMBO_POSITION_OFFSET] = acehex(profile.get_int("combo")).encode(
profile.get_int("combo") "ascii"
).encode("ascii") )
option[self.GAME_OPTION_ARROW_SKIN_OFFSET] = acehex( option[self.GAME_OPTION_ARROW_SKIN_OFFSET] = acehex(profile.get_int("arrowskin")).encode(
profile.get_int("arrowskin") "ascii"
).encode("ascii") )
option[self.GAME_OPTION_GUIDELINE_OFFSET] = acehex( option[self.GAME_OPTION_GUIDELINE_OFFSET] = acehex(profile.get_int("guidelines")).encode(
profile.get_int("guidelines") "ascii"
).encode("ascii") )
option[self.GAME_OPTION_FILTER_OFFSET] = acehex( option[self.GAME_OPTION_FILTER_OFFSET] = acehex(profile.get_int("filter")).encode("ascii")
profile.get_int("filter")
).encode("ascii")
usergamedata[ptype]["strdata"] = b",".join(option) usergamedata[ptype]["strdata"] = b",".join(option)
if ptype == "LAST": if ptype == "LAST":
# Return the number of calories expended in the last day # Return the number of calories expended in the last day
@ -959,9 +877,7 @@ class DDRAce(
total = sum([w.data.get_int("calories") for w in workouts]) total = sum([w.data.get_int("calories") for w in workouts])
last = usergamedata[ptype]["strdata"].split(b",") last = usergamedata[ptype]["strdata"].split(b",")
last[self.GAME_LAST_CALORIES_OFFSET] = acehex(total).encode( last[self.GAME_LAST_CALORIES_OFFSET] = acehex(total).encode("ascii")
"ascii"
)
usergamedata[ptype]["strdata"] = b",".join(last) usergamedata[ptype]["strdata"] = b",".join(last)
if ptype == "RIVAL": if ptype == "RIVAL":
# Fill in the DDR code and active status of the three active # Fill in the DDR code and active status of the three active
@ -1003,24 +919,18 @@ class DDRAce(
}[rivalno] }[rivalno]
rival[activeslot] = acehex(rivalno).encode("ascii") rival[activeslot] = acehex(rivalno).encode("ascii")
rival[ddrcodeslot] = acehex(friendprofile.extid).encode( rival[ddrcodeslot] = acehex(friendprofile.extid).encode("ascii")
"ascii"
)
usergamedata[ptype]["strdata"] = b",".join(rival) usergamedata[ptype]["strdata"] = b",".join(rival)
dnode = Node.string( dnode = Node.string(
"d", "d",
base64.b64encode(usergamedata[ptype]["strdata"]).decode( base64.b64encode(usergamedata[ptype]["strdata"]).decode("ascii"),
"ascii"
),
) )
dnode.add_child( dnode.add_child(
Node.string( Node.string(
"bin1", "bin1",
base64.b64encode(usergamedata[ptype]["bindata"]).decode( base64.b64encode(usergamedata[ptype]["bindata"]).decode("ascii"),
"ascii"
),
) )
) )
record.add_child(dnode) record.add_child(dnode)

View File

@ -156,9 +156,7 @@ class DDRX2(
flag.set_attribute("s1", "0") flag.set_attribute("s1", "0")
flag.set_attribute("t", "0") flag.set_attribute("t", "0")
hit_chart = self.data.local.music.get_hit_chart( hit_chart = self.data.local.music.get_hit_chart(self.game, self.music_version, self.GAME_MAX_SONGS)
self.game, self.music_version, self.GAME_MAX_SONGS
)
counts_by_reflink = [0] * self.GAME_MAX_SONGS counts_by_reflink = [0] * self.GAME_MAX_SONGS
for reflink, plays in hit_chart: for reflink, plays in hit_chart:
if reflink >= 0 and reflink < self.GAME_MAX_SONGS: if reflink >= 0 and reflink < self.GAME_MAX_SONGS:
@ -180,10 +178,7 @@ class DDRX2(
sortedrecords[score.id] = {} sortedrecords[score.id] = {}
sortedrecords[score.id][score.chart] = (userid, score) sortedrecords[score.id][score.chart] = (userid, score)
missing_profiles.append(userid) missing_profiles.append(userid)
users = { users = {userid: profile for (userid, profile) in self.get_any_profiles(missing_profiles)}
userid: profile
for (userid, profile) in self.get_any_profiles(missing_profiles)
}
game = Node.void("game") game = Node.void("game")
for song in sortedrecords: for song in sortedrecords:
@ -207,11 +202,7 @@ class DDRX2(
typenode.add_child(Node.string("name", users[userid].get_str("name"))) typenode.add_child(Node.string("name", users[userid].get_str("name")))
typenode.add_child(Node.u32("score", score.points)) typenode.add_child(Node.u32("score", score.points))
typenode.add_child( typenode.add_child(Node.u16("area", users[userid].get_int("area", self.get_machine_region())))
Node.u16(
"area", users[userid].get_int("area", self.get_machine_region())
)
)
typenode.add_child(Node.u8("rank", gamerank)) typenode.add_child(Node.u8("rank", gamerank))
typenode.add_child(Node.u8("combo_type", combo_type)) typenode.add_child(Node.u8("combo_type", combo_type))
@ -229,9 +220,7 @@ class DDRX2(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
else: else:
scores = [] scores = []
@ -317,14 +306,10 @@ class DDRX2(
root.add_child(Node.string("seq", "")) root.add_child(Node.string("seq", ""))
root.add_child(Node.u32("code", profile.extid)) root.add_child(Node.u32("code", profile.extid))
root.add_child(Node.string("name", profile.get_str("name"))) root.add_child(Node.string("name", profile.get_str("name")))
root.add_child( root.add_child(Node.u8("area", profile.get_int("area", self.get_machine_region())))
Node.u8("area", profile.get_int("area", self.get_machine_region()))
)
root.add_child(Node.u32("cnt_s", play_stats.get_int("single_plays"))) root.add_child(Node.u32("cnt_s", play_stats.get_int("single_plays")))
root.add_child(Node.u32("cnt_d", play_stats.get_int("double_plays"))) root.add_child(Node.u32("cnt_d", play_stats.get_int("double_plays")))
root.add_child( root.add_child(Node.u32("cnt_b", play_stats.get_int("battle_plays"))) # This could be wrong, its a guess
Node.u32("cnt_b", play_stats.get_int("battle_plays"))
) # This could be wrong, its a guess
root.add_child(Node.u32("cnt_m0", play_stats.get_int("cnt_m0"))) root.add_child(Node.u32("cnt_m0", play_stats.get_int("cnt_m0")))
root.add_child(Node.u32("cnt_m1", play_stats.get_int("cnt_m1"))) root.add_child(Node.u32("cnt_m1", play_stats.get_int("cnt_m1")))
root.add_child(Node.u32("cnt_m2", play_stats.get_int("cnt_m2"))) root.add_child(Node.u32("cnt_m2", play_stats.get_int("cnt_m2")))
@ -342,9 +327,7 @@ class DDRX2(
if "chara" in profile: if "chara" in profile:
chara.set_attribute("my", str(profile.get_int("chara"))) chara.set_attribute("my", str(profile.get_int("chara")))
root.add_child( root.add_child(Node.u8_array("chara_opt", profile.get_int_array("chara_opt", 96)))
Node.u8_array("chara_opt", profile.get_int_array("chara_opt", 96))
)
# Drill rankings # Drill rankings
if "title" in profile: if "title" in profile:
@ -387,53 +370,31 @@ class DDRX2(
e_panel_dict = profile.get_dict("e_panel") e_panel_dict = profile.get_dict("e_panel")
if "play_id" in e_panel_dict: if "play_id" in e_panel_dict:
e_panel.set_attribute("play_id", str(e_panel_dict.get_int("play_id"))) e_panel.set_attribute("play_id", str(e_panel_dict.get_int("play_id")))
e_panel.add_child( e_panel.add_child(Node.u8_array("cell", e_panel_dict.get_int_array("cell", 24)))
Node.u8_array("cell", e_panel_dict.get_int_array("cell", 24)) e_panel.add_child(Node.u8_array("panel_state", e_panel_dict.get_int_array("panel_state", 6)))
)
e_panel.add_child(
Node.u8_array(
"panel_state", e_panel_dict.get_int_array("panel_state", 6)
)
)
if "e_pix" in profile: if "e_pix" in profile:
e_pix = Node.void("e_pix") e_pix = Node.void("e_pix")
root.add_child(e_pix) root.add_child(e_pix)
e_pix_dict = profile.get_dict("e_pix") e_pix_dict = profile.get_dict("e_pix")
if "max_distance" in e_pix_dict: if "max_distance" in e_pix_dict:
e_pix.set_attribute( e_pix.set_attribute("max_distance", str(e_pix_dict.get_int("max_distance")))
"max_distance", str(e_pix_dict.get_int("max_distance"))
)
if "max_planet" in e_pix_dict: if "max_planet" in e_pix_dict:
e_pix.set_attribute("max_planet", str(e_pix_dict.get_int("max_planet"))) e_pix.set_attribute("max_planet", str(e_pix_dict.get_int("max_planet")))
if "total_distance" in e_pix_dict: if "total_distance" in e_pix_dict:
e_pix.set_attribute( e_pix.set_attribute("total_distance", str(e_pix_dict.get_int("total_distance")))
"total_distance", str(e_pix_dict.get_int("total_distance"))
)
if "total_planet" in e_pix_dict: if "total_planet" in e_pix_dict:
e_pix.set_attribute( e_pix.set_attribute("total_planet", str(e_pix_dict.get_int("total_planet")))
"total_planet", str(e_pix_dict.get_int("total_planet"))
)
if "border_character" in e_pix_dict: if "border_character" in e_pix_dict:
e_pix.set_attribute( e_pix.set_attribute("border_character", str(e_pix_dict.get_int("border_character")))
"border_character", str(e_pix_dict.get_int("border_character"))
)
if "border_balloon" in e_pix_dict: if "border_balloon" in e_pix_dict:
e_pix.set_attribute( e_pix.set_attribute("border_balloon", str(e_pix_dict.get_int("border_balloon")))
"border_balloon", str(e_pix_dict.get_int("border_balloon"))
)
if "border_music_aftr" in e_pix_dict: if "border_music_aftr" in e_pix_dict:
e_pix.set_attribute( e_pix.set_attribute("border_music_aftr", str(e_pix_dict.get_int("border_music_aftr")))
"border_music_aftr", str(e_pix_dict.get_int("border_music_aftr"))
)
if "border_music_meii" in e_pix_dict: if "border_music_meii" in e_pix_dict:
e_pix.set_attribute( e_pix.set_attribute("border_music_meii", str(e_pix_dict.get_int("border_music_meii")))
"border_music_meii", str(e_pix_dict.get_int("border_music_meii"))
)
if "border_music_dirt" in e_pix_dict: if "border_music_dirt" in e_pix_dict:
e_pix.set_attribute( e_pix.set_attribute("border_music_dirt", str(e_pix_dict.get_int("border_music_dirt")))
"border_music_dirt", str(e_pix_dict.get_int("border_music_dirt"))
)
if "flags" in e_pix_dict: if "flags" in e_pix_dict:
e_pix.set_attribute("flags", str(e_pix_dict.get_int("flags"))) e_pix.set_attribute("flags", str(e_pix_dict.get_int("flags")))
@ -488,9 +449,7 @@ class DDRX2(
root.add_child(Node.s16_array("opt_ex", profile.get_int_array("opt_ex", 16))) root.add_child(Node.s16_array("opt_ex", profile.get_int_array("opt_ex", 16)))
# Unlock flags # Unlock flags
root.add_child( root.add_child(Node.u8_array("flag", profile.get_int_array("flag", 256, [1] * 256)))
Node.u8_array("flag", profile.get_int_array("flag", 256, [1] * 256))
)
# Ranking display? # Ranking display?
root.add_child(Node.u16_array("rank", profile.get_int_array("rank", 100))) root.add_child(Node.u16_array("rank", profile.get_int_array("rank", 100)))
@ -512,9 +471,7 @@ class DDRX2(
friendnode.set_attribute("up", "0") friendnode.set_attribute("up", "0")
friendnode.add_child(Node.u32("code", friend.extid)) friendnode.add_child(Node.u32("code", friend.extid))
friendnode.add_child(Node.string("name", friend.get_str("name"))) friendnode.add_child(Node.string("name", friend.get_str("name")))
friendnode.add_child( friendnode.add_child(Node.u8("area", friend.get_int("area", self.get_machine_region())))
Node.u8("area", friend.get_int("area", self.get_machine_region()))
)
friendnode.add_child(Node.u32("exp", play_stats.get_int("exp"))) friendnode.add_child(Node.u32("exp", play_stats.get_int("exp")))
friendnode.add_child(Node.u32("star", friend.get_int("star"))) friendnode.add_child(Node.u32("star", friend.get_int("star")))
@ -558,9 +515,7 @@ class DDRX2(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -656,9 +611,7 @@ class DDRX2(
e_panel_dict = newprofile.get_dict("e_panel") e_panel_dict = newprofile.get_dict("e_panel")
e_panel_dict.replace_int("play_id", intish(e_panel.attribute("play_id"))) e_panel_dict.replace_int("play_id", intish(e_panel.attribute("play_id")))
e_panel_dict.replace_int_array("cell", 24, e_panel.child_value("cell")) e_panel_dict.replace_int_array("cell", 24, e_panel.child_value("cell"))
e_panel_dict.replace_int_array( e_panel_dict.replace_int_array("panel_state", 6, e_panel.child_value("panel_state"))
"panel_state", 6, e_panel.child_value("panel_state")
)
newprofile.replace_dict("e_panel", e_panel_dict) newprofile.replace_dict("e_panel", e_panel_dict)
e_pix = request.child("e_pix") e_pix = request.child("e_pix")
@ -777,9 +730,7 @@ class DDRX2(
newfriends[pos] = None newfriends[pos] = None
else: else:
# Try looking up the userid # Try looking up the userid
newfriends[pos] = self.data.remote.user.from_extid( newfriends[pos] = self.data.remote.user.from_extid(self.game, self.version, code)
self.game, self.version, code
)
# Diff the set of links to determine updates # Diff the set of links to determine updates
for i in range(10): for i in range(10):

View File

@ -165,9 +165,7 @@ class DDRX3(
flag.set_attribute("s1", "0") flag.set_attribute("s1", "0")
flag.set_attribute("t", "0") flag.set_attribute("t", "0")
hit_chart = self.data.local.music.get_hit_chart( hit_chart = self.data.local.music.get_hit_chart(self.game, self.music_version, self.GAME_MAX_SONGS)
self.game, self.music_version, self.GAME_MAX_SONGS
)
counts_by_reflink = [0] * self.GAME_MAX_SONGS counts_by_reflink = [0] * self.GAME_MAX_SONGS
for reflink, plays in hit_chart: for reflink, plays in hit_chart:
if reflink >= 0 and reflink < self.GAME_MAX_SONGS: if reflink >= 0 and reflink < self.GAME_MAX_SONGS:
@ -188,14 +186,10 @@ class DDRX3(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
old_scores = [ old_scores = [
score score
for score in self.data.local.user.get_achievements( for score in self.data.local.user.get_achievements(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
if score.type == "2ndmix" if score.type == "2ndmix"
] ]
else: else:
@ -236,12 +230,8 @@ class DDRX3(
if "score" in scoredict: if "score" in scoredict:
# We played the normal version of this song # We played the normal version of this song
gamerank = self.db_to_game_rank( gamerank = self.db_to_game_rank(scoredict["score"].data.get_int("rank"))
scoredict["score"].data.get_int("rank") combo_type = self.db_to_game_halo(scoredict["score"].data.get_int("halo"))
)
combo_type = self.db_to_game_halo(
scoredict["score"].data.get_int("halo")
)
points = scoredict["score"].points # type: ignore points = scoredict["score"].points # type: ignore
plays = scoredict["score"].plays # type: ignore plays = scoredict["score"].plays # type: ignore
else: else:
@ -366,14 +356,10 @@ class DDRX3(
root.add_child(Node.string("seq", "")) root.add_child(Node.string("seq", ""))
root.add_child(Node.u32("code", profile.extid)) root.add_child(Node.u32("code", profile.extid))
root.add_child(Node.string("name", profile.get_str("name"))) root.add_child(Node.string("name", profile.get_str("name")))
root.add_child( root.add_child(Node.u8("area", profile.get_int("area", self.get_machine_region())))
Node.u8("area", profile.get_int("area", self.get_machine_region()))
)
root.add_child(Node.u32("cnt_s", play_stats.get_int("single_plays"))) root.add_child(Node.u32("cnt_s", play_stats.get_int("single_plays")))
root.add_child(Node.u32("cnt_d", play_stats.get_int("double_plays"))) root.add_child(Node.u32("cnt_d", play_stats.get_int("double_plays")))
root.add_child( root.add_child(Node.u32("cnt_b", play_stats.get_int("battle_plays"))) # This could be wrong, its a guess
Node.u32("cnt_b", play_stats.get_int("battle_plays"))
) # This could be wrong, its a guess
root.add_child(Node.u32("cnt_m0", play_stats.get_int("cnt_m0"))) root.add_child(Node.u32("cnt_m0", play_stats.get_int("cnt_m0")))
root.add_child(Node.u32("cnt_m1", play_stats.get_int("cnt_m1"))) root.add_child(Node.u32("cnt_m1", play_stats.get_int("cnt_m1")))
root.add_child(Node.u32("cnt_m2", play_stats.get_int("cnt_m2"))) root.add_child(Node.u32("cnt_m2", play_stats.get_int("cnt_m2")))
@ -391,11 +377,7 @@ class DDRX3(
chara = Node.void("chara") chara = Node.void("chara")
root.add_child(chara) root.add_child(chara)
chara.set_attribute("my", str(profile.get_int("chara", 30))) chara.set_attribute("my", str(profile.get_int("chara", 30)))
root.add_child( root.add_child(Node.u16_array("chara_opt", profile.get_int_array("chara_opt", 96, [208] * 96)))
Node.u16_array(
"chara_opt", profile.get_int_array("chara_opt", 96, [208] * 96)
)
)
# Drill rankings # Drill rankings
if "title_gr" in profile: if "title_gr" in profile:
@ -443,9 +425,7 @@ class DDRX3(
last.set_attribute("rival1", str(lastdict.get_int("rival1", -1))) last.set_attribute("rival1", str(lastdict.get_int("rival1", -1)))
last.set_attribute("rival2", str(lastdict.get_int("rival2", -1))) last.set_attribute("rival2", str(lastdict.get_int("rival2", -1)))
last.set_attribute("rival3", str(lastdict.get_int("rival3", -1))) last.set_attribute("rival3", str(lastdict.get_int("rival3", -1)))
last.set_attribute( last.set_attribute("fri", str(lastdict.get_int("rival1", -1))) # This literally goes to the same memory in X3
"fri", str(lastdict.get_int("rival1", -1))
) # This literally goes to the same memory in X3
last.set_attribute("style", str(lastdict.get_int("style"))) last.set_attribute("style", str(lastdict.get_int("style")))
last.set_attribute("mode", str(lastdict.get_int("mode"))) last.set_attribute("mode", str(lastdict.get_int("mode")))
last.set_attribute("cate", str(lastdict.get_int("cate"))) last.set_attribute("cate", str(lastdict.get_int("cate")))
@ -489,9 +469,7 @@ class DDRX3(
root.add_child(Node.s16_array("opt_ex", profile.get_int_array("opt_ex", 16))) root.add_child(Node.s16_array("opt_ex", profile.get_int_array("opt_ex", 16)))
# Unlock flags # Unlock flags
root.add_child( root.add_child(Node.u8_array("flag", profile.get_int_array("flag", 256, [1] * 256)))
Node.u8_array("flag", profile.get_int_array("flag", 256, [1] * 256))
)
# Ranking display? # Ranking display?
root.add_child(Node.u16_array("rank", profile.get_int_array("rank", 100))) root.add_child(Node.u16_array("rank", profile.get_int_array("rank", 100)))
@ -513,9 +491,7 @@ class DDRX3(
friendnode.set_attribute("up", "0") friendnode.set_attribute("up", "0")
friendnode.add_child(Node.u32("code", friend.extid)) friendnode.add_child(Node.u32("code", friend.extid))
friendnode.add_child(Node.string("name", friend.get_str("name"))) friendnode.add_child(Node.string("name", friend.get_str("name")))
friendnode.add_child( friendnode.add_child(Node.u8("area", friend.get_int("area", self.get_machine_region())))
Node.u8("area", friend.get_int("area", self.get_machine_region()))
)
friendnode.add_child(Node.u32("exp", play_stats.get_int("exp"))) friendnode.add_child(Node.u32("exp", play_stats.get_int("exp")))
friendnode.add_child(Node.u32("star", friend.get_int("star"))) friendnode.add_child(Node.u32("star", friend.get_int("star")))
@ -566,9 +542,7 @@ class DDRX3(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -773,9 +747,7 @@ class DDRX3(
newfriends[pos] = None newfriends[pos] = None
else: else:
# Try looking up the userid # Try looking up the userid
newfriends[pos] = self.data.remote.user.from_extid( newfriends[pos] = self.data.remote.user.from_extid(self.game, self.version, code)
self.game, self.version, code
)
# Diff the set of links to determine updates # Diff the set of links to determine updates
for i in range(10): for i in range(10):

View File

@ -79,9 +79,7 @@ class Dispatch:
pcb = self.__data.local.machine.get_machine(pcbid) pcb = self.__data.local.machine.get_machine(pcbid)
if self.__config.server.enforce_pcbid and pcb is None: if self.__config.server.enforce_pcbid and pcb is None:
self.log("Unrecognized PCBID {}", pcbid) self.log("Unrecognized PCBID {}", pcbid)
raise UnrecognizedPCBIDException( raise UnrecognizedPCBIDException(pcbid, modelstring, self.__config.client.address)
pcbid, modelstring, self.__config.client.address
)
# If we don't have a Machine, but we aren't enforcing, we must create it # If we don't have a Machine, but we aren't enforcing, we must create it
if pcb is None: if pcb is None:
@ -120,9 +118,7 @@ class Dispatch:
pcb.game, pcb.game,
game.game, game.game,
) )
raise UnrecognizedPCBIDException( raise UnrecognizedPCBIDException(pcbid, modelstring, config.client.address)
pcbid, modelstring, config.client.address
)
if pcb.version is not None: if pcb.version is not None:
if pcb.version > 0 and pcb.version != game.version: if pcb.version > 0 and pcb.version != game.version:
self.log( self.log(
@ -133,9 +129,7 @@ class Dispatch:
game.game, game.game,
game.version, game.version,
) )
raise UnrecognizedPCBIDException( raise UnrecognizedPCBIDException(pcbid, modelstring, config.client.address)
pcbid, modelstring, config.client.address
)
if pcb.version < 0 and (-pcb.version) < game.version: if pcb.version < 0 and (-pcb.version) < game.version:
self.log( self.log(
"PCBID {} assigned to game {} maximum version {}, but connected from game {} version {}", "PCBID {} assigned to game {} maximum version {}, but connected from game {} version {}",
@ -145,9 +139,7 @@ class Dispatch:
game.game, game.game,
game.version, game.version,
) )
raise UnrecognizedPCBIDException( raise UnrecognizedPCBIDException(pcbid, modelstring, config.client.address)
pcbid, modelstring, config.client.address
)
# First, try to handle with specific service/method function # First, try to handle with specific service/method function
try: try:

View File

@ -115,9 +115,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
return Node.void("pc") return Node.void("pc")
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
""" """
Base handler for profile parsing. Given a request and an old profile, Base handler for profile parsing. Given a request and an old profile,
return a new profile that's been updated with the contents of the request. return a new profile that's been updated with the contents of the request.
@ -145,9 +143,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
return None return None
return self.format_profile(userid, profile) return self.format_profile(userid, profile)
def new_profile_by_refid( def new_profile_by_refid(self, refid: Optional[str], name: Optional[str], pid: Optional[int]) -> Profile:
self, refid: Optional[str], name: Optional[str], pid: Optional[int]
) -> Profile:
""" """
Given a RefID and an optional name, create a profile and then return Given a RefID and an optional name, create a profile and then return
that newly created profile. that newly created profile.
@ -169,9 +165,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
{ {
"name": name, "name": name,
"pid": pid, "pid": pid,
"settings": { "settings": {"flags": 223}, # Default to turning on all optional folders
"flags": 223 # Default to turning on all optional folders
},
}, },
) )
self.put_profile(userid, profile) self.put_profile(userid, profile)
@ -253,27 +247,18 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
} }
# We saw an attempt, keep the total attempts in sync. # We saw an attempt, keep the total attempts in sync.
attempts[attempt.id][attempt.chart]["total"] = ( attempts[attempt.id][attempt.chart]["total"] = attempts[attempt.id][attempt.chart]["total"] + 1
attempts[attempt.id][attempt.chart]["total"] + 1
)
if ( if attempt.data.get_int("clear_status", self.CLEAR_STATUS_FAILED) == self.CLEAR_STATUS_FAILED:
attempt.data.get_int("clear_status", self.CLEAR_STATUS_FAILED)
== self.CLEAR_STATUS_FAILED
):
# This attempt was a failure, so don't count it against clears of full combos # This attempt was a failure, so don't count it against clears of full combos
continue continue
# It was at least a clear # It was at least a clear
attempts[attempt.id][attempt.chart]["clears"] = ( attempts[attempt.id][attempt.chart]["clears"] = attempts[attempt.id][attempt.chart]["clears"] + 1
attempts[attempt.id][attempt.chart]["clears"] + 1
)
if attempt.data.get_int("clear_status") == self.CLEAR_STATUS_FULL_COMBO: if attempt.data.get_int("clear_status") == self.CLEAR_STATUS_FULL_COMBO:
# This was a full combo clear, so it also counts here # This was a full combo clear, so it also counts here
attempts[attempt.id][attempt.chart]["fcs"] = ( attempts[attempt.id][attempt.chart]["fcs"] = attempts[attempt.id][attempt.chart]["fcs"] + 1
attempts[attempt.id][attempt.chart]["fcs"] + 1
)
# Merge in remote attempts # Merge in remote attempts
for songid in remote_attempts: for songid in remote_attempts:
@ -288,15 +273,9 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
"fcs": 0, "fcs": 0,
} }
attempts[songid][songchart]["total"] += remote_attempts[songid][ attempts[songid][songchart]["total"] += remote_attempts[songid][songchart]["plays"]
songchart attempts[songid][songchart]["clears"] += remote_attempts[songid][songchart]["clears"]
]["plays"] attempts[songid][songchart]["fcs"] += remote_attempts[songid][songchart]["combos"]
attempts[songid][songchart]["clears"] += remote_attempts[songid][
songchart
]["clears"]
attempts[songid][songchart]["fcs"] += remote_attempts[songid][
songchart
]["combos"]
# If requesting a specific song/chart, make sure its in the dict # If requesting a specific song/chart, make sure its in the dict
if songid is not None: if songid is not None:
@ -399,16 +378,12 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
highscore = ex_score >= oldscore.points highscore = ex_score >= oldscore.points
ex_score = max(ex_score, oldscore.points) ex_score = max(ex_score, oldscore.points)
scoredata = oldscore.data scoredata = oldscore.data
scoredata.replace_int( scoredata.replace_int("clear_status", max(scoredata.get_int("clear_status"), clear_status))
"clear_status", max(scoredata.get_int("clear_status"), clear_status)
)
if miss_count != -1: if miss_count != -1:
if scoredata.get_int("miss_count", -1) == -1: if scoredata.get_int("miss_count", -1) == -1:
scoredata.replace_int("miss_count", miss_count) scoredata.replace_int("miss_count", miss_count)
else: else:
scoredata.replace_int( scoredata.replace_int("miss_count", min(scoredata.get_int("miss_count"), miss_count))
"miss_count", min(scoredata.get_int("miss_count"), miss_count)
)
if raised: if raised:
scoredata.replace_int("pgreats", pgreats) scoredata.replace_int("pgreats", pgreats)
scoredata.replace_int("greats", greats) scoredata.replace_int("greats", greats)
@ -514,12 +489,8 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
if dan_score is None: if dan_score is None:
dan_score = ValidatedDict() dan_score = ValidatedDict()
dan_score.replace_int("percent", max(percent, dan_score.get_int("percent"))) dan_score.replace_int("percent", max(percent, dan_score.get_int("percent")))
dan_score.replace_int( dan_score.replace_int("stages_cleared", max(stages_cleared, dan_score.get_int("stages_cleared")))
"stages_cleared", max(stages_cleared, dan_score.get_int("stages_cleared")) self.data.local.user.put_achievement(self.game, self.version, userid, rank, dantype, dan_score)
)
self.data.local.user.put_achievement(
self.game, self.version, userid, rank, dantype, dan_score
)
def db_to_game_status(self, db_status: int) -> int: def db_to_game_status(self, db_status: int) -> int:
""" """
@ -545,9 +516,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
raise Exception("Implement in sub-class!") raise Exception("Implement in sub-class!")
def make_score_struct( def make_score_struct(self, scores: List[Score], cltype: int, index: int) -> List[List[int]]:
self, scores: List[Score], cltype: int, index: int
) -> List[List[int]]:
scorestruct: Dict[int, List[int]] = {} scorestruct: Dict[int, List[int]] = {}
for score in scores: for score in scores:
@ -595,9 +564,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
-1, # Miss count another, -1, # Miss count another,
] ]
scorestruct[musicid][chartindex + 2] = self.db_to_game_status( scorestruct[musicid][chartindex + 2] = self.db_to_game_status(score.data.get_int("clear_status"))
score.data.get_int("clear_status")
)
scorestruct[musicid][chartindex + 5] = score.points scorestruct[musicid][chartindex + 5] = score.points
scorestruct[musicid][chartindex + 8] = score.data.get_int("miss_count", -1) scorestruct[musicid][chartindex + 8] = score.data.get_int("miss_count", -1)
@ -698,9 +665,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
if ghost_type == self.GHOST_TYPE_RIVAL: if ghost_type == self.GHOST_TYPE_RIVAL:
rival_extid = int(parameter) rival_extid = int(parameter)
rival_userid = self.data.remote.user.from_extid( rival_userid = self.data.remote.user.from_extid(self.game, self.version, rival_extid)
self.game, self.version, rival_extid
)
if rival_userid is not None: if rival_userid is not None:
rival_profile = self.get_profile(rival_userid) rival_profile = self.get_profile(rival_userid)
rival_score = self.data.remote.music.get_score( rival_score = self.data.remote.music.get_score(
@ -720,10 +685,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
or ghost_type == self.GHOST_TYPE_GLOBAL_AVERAGE or ghost_type == self.GHOST_TYPE_GLOBAL_AVERAGE
or ghost_type == self.GHOST_TYPE_LOCAL_AVERAGE or ghost_type == self.GHOST_TYPE_LOCAL_AVERAGE
): ):
if ( if ghost_type == self.GHOST_TYPE_LOCAL_TOP or ghost_type == self.GHOST_TYPE_LOCAL_AVERAGE:
ghost_type == self.GHOST_TYPE_LOCAL_TOP
or ghost_type == self.GHOST_TYPE_LOCAL_AVERAGE
):
all_scores = sorted( all_scores = sorted(
self.data.local.music.get_all_scores( self.data.local.music.get_all_scores(
game=self.game, game=self.game,
@ -756,9 +718,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if self.user_joined_arcade( if self.user_joined_arcade(machine, self.get_any_profile(score[0]))
machine, self.get_any_profile(score[0])
)
] ]
else: else:
# Not joined an arcade, so nobody matches our scores # Not joined an arcade, so nobody matches our scores
@ -775,10 +735,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
reverse=True, reverse=True,
) )
if ( if ghost_type == self.GHOST_TYPE_GLOBAL_TOP or ghost_type == self.GHOST_TYPE_LOCAL_TOP:
ghost_type == self.GHOST_TYPE_GLOBAL_TOP
or ghost_type == self.GHOST_TYPE_LOCAL_TOP
):
for potential_top in all_scores: for potential_top in all_scores:
top_userid = potential_top[0] top_userid = potential_top[0]
top_score = potential_top[1] top_score = potential_top[1]
@ -793,23 +750,15 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
} }
break break
if ( if ghost_type == self.GHOST_TYPE_GLOBAL_AVERAGE or ghost_type == self.GHOST_TYPE_LOCAL_AVERAGE:
ghost_type == self.GHOST_TYPE_GLOBAL_AVERAGE average_score, delta_ghost = self.delta_score([score[1] for score in all_scores], ghost_length)
or ghost_type == self.GHOST_TYPE_LOCAL_AVERAGE
):
average_score, delta_ghost = self.delta_score(
[score[1] for score in all_scores], ghost_length
)
if average_score is not None and delta_ghost is not None: if average_score is not None and delta_ghost is not None:
ghost_score = { ghost_score = {
"score": average_score, "score": average_score,
"ghost": bytes([0] * ghost_length), "ghost": bytes([0] * ghost_length),
} }
if ( if ghost_type == self.GHOST_TYPE_DAN_TOP or ghost_type == self.GHOST_TYPE_DAN_AVERAGE:
ghost_type == self.GHOST_TYPE_DAN_TOP
or ghost_type == self.GHOST_TYPE_DAN_AVERAGE
):
is_dp = chart not in [ is_dp = chart not in [
self.CHART_TYPE_N7, self.CHART_TYPE_N7,
self.CHART_TYPE_H7, self.CHART_TYPE_H7,
@ -839,20 +788,13 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
key=lambda s: s[1].points, key=lambda s: s[1].points,
reverse=True, reverse=True,
) )
all_profiles = self.data.local.user.get_all_profiles( all_profiles = self.data.local.user.get_all_profiles(self.game, self.version)
self.game, self.version
)
relevant_userids = { relevant_userids = {
profile[0] profile[0]
for profile in all_profiles for profile in all_profiles
if profile[1].get_int( if profile[1].get_int(self.DAN_RANKING_DOUBLE if is_dp else self.DAN_RANKING_SINGLE) == dan_rank
self.DAN_RANKING_DOUBLE if is_dp else self.DAN_RANKING_SINGLE
)
== dan_rank
} }
relevant_scores = [ relevant_scores = [score for score in all_scores if score[0] in relevant_userids]
score for score in all_scores if score[0] in relevant_userids
]
if ghost_type == self.GHOST_TYPE_DAN_TOP: if ghost_type == self.GHOST_TYPE_DAN_TOP:
for potential_top in relevant_scores: for potential_top in relevant_scores:
top_userid = potential_top[0] top_userid = potential_top[0]
@ -869,23 +811,17 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
break break
if ghost_type == self.GHOST_TYPE_DAN_AVERAGE: if ghost_type == self.GHOST_TYPE_DAN_AVERAGE:
average_score, delta_ghost = self.delta_score( average_score, delta_ghost = self.delta_score([score[1] for score in relevant_scores], ghost_length)
[score[1] for score in relevant_scores], ghost_length
)
if average_score is not None and delta_ghost is not None: if average_score is not None and delta_ghost is not None:
ghost_score = { ghost_score = {
"score": average_score, "score": average_score,
"ghost": bytes([0] * ghost_length), "ghost": bytes([0] * ghost_length),
} }
if ( if ghost_type == self.GHOST_TYPE_RIVAL_TOP or ghost_type == self.GHOST_TYPE_RIVAL_AVERAGE:
ghost_type == self.GHOST_TYPE_RIVAL_TOP
or ghost_type == self.GHOST_TYPE_RIVAL_AVERAGE
):
rival_extids = [int(e[1:-1]) for e in parameter.split(",")] rival_extids = [int(e[1:-1]) for e in parameter.split(",")]
rival_userids = [ rival_userids = [
self.data.remote.user.from_extid(self.game, self.version, rival_extid) self.data.remote.user.from_extid(self.game, self.version, rival_extid) for rival_extid in rival_extids
for rival_extid in rival_extids
] ]
all_scores = sorted( all_scores = sorted(
@ -918,9 +854,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
break break
if ghost_type == self.GHOST_TYPE_RIVAL_AVERAGE: if ghost_type == self.GHOST_TYPE_RIVAL_AVERAGE:
average_score, delta_ghost = self.delta_score( average_score, delta_ghost = self.delta_score([score[1] for score in all_scores], ghost_length)
[score[1] for score in all_scores], ghost_length
)
if average_score is not None and delta_ghost is not None: if average_score is not None and delta_ghost is not None:
ghost_score = { ghost_score = {
"score": average_score, "score": average_score,

View File

@ -107,28 +107,15 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
return IIDXSinobuz(self.data, self.config, self.model) return IIDXSinobuz(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert dailies into the DB. Insert dailies into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "daily_charts", "daily"):
cls.game, cls.version, "daily_charts", "daily"
):
# Generate a new list of three dailies. # Generate a new list of three dailies.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = list( all_songs = list(set([song.id for song in data.local.music.get_all_songs(cls.game, cls.version)]))
set(
[
song.id
for song in data.local.music.get_all_songs(
cls.game, cls.version
)
]
)
)
if len(all_songs) >= 3: if len(all_songs) >= 3:
daily_songs = random.sample(all_songs, 3) daily_songs = random.sample(all_songs, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -152,9 +139,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "daily_charts", "daily")
cls.game, cls.version, "daily_charts", "daily"
)
return events return events
@classmethod @classmethod
@ -389,9 +374,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
root = Node.void("IIDX25shop") root = Node.void("IIDX25shop")
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -414,9 +397,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
course.replace_int("music_2", request.child_value("music_2")) course.replace_int("music_2", request.child_value("music_2"))
course.replace_int("music_3", request.child_value("music_3")) course.replace_int("music_3", request.child_value("music_3"))
course.replace_bool("valid", request.child_value("valid")) course.replace_bool("valid", request.child_value("valid"))
self.data.local.machine.put_settings( self.data.local.machine.put_settings(machine.arcade, self.game, self.music_version, "shop_course", course)
machine.arcade, self.game, self.music_version, "shop_course", course
)
return Node.void("IIDX25shop") return Node.void("IIDX25shop")
@ -436,9 +417,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -575,16 +554,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
root = Node.void("IIDX25music") root = Node.void("IIDX25music")
attempts = self.get_clear_rates() attempts = self.get_clear_rates()
all_songs = list( all_songs = list(set([song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)]))
set(
[
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
]
)
)
for song in all_songs: for song in all_songs:
clears = [] clears = []
fcs = [] fcs = []
@ -628,16 +598,12 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
continue continue
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
# Grab score data for user/rival # Grab score data for user/rival
scoredata = self.make_score_struct( scoredata = self.make_score_struct(
scores, scores,
self.CLEAR_TYPE_SINGLE self.CLEAR_TYPE_SINGLE if cltype == self.GAME_CLTYPE_SINGLE else self.CLEAR_TYPE_DOUBLE,
if cltype == self.GAME_CLTYPE_SINGLE
else self.CLEAR_TYPE_DOUBLE,
rivalid, rivalid,
) )
for s in scoredata: for s in scoredata:
@ -645,10 +611,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
# Grab most played for user/rival # Grab most played for user/rival
most_played = [ most_played = [
play[0] play[0] for play in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)
for play in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
] ]
if len(most_played) < 20: if len(most_played) < 20:
most_played.extend([0] * (20 - len(most_played))) most_played.extend([0] * (20 - len(most_played)))
@ -675,9 +638,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
if userid is not None: if userid is not None:
# Try to look up previous ghost for user # Try to look up previous ghost for user
my_score = self.data.remote.music.get_score( my_score = self.data.remote.music.get_score(self.game, self.music_version, userid, musicid, chart)
self.game, self.music_version, userid, musicid, chart
)
if my_score is not None: if my_score is not None:
mydata = Node.binary("mydata", my_score.data.get_bytes("ghost")) mydata = Node.binary("mydata", my_score.data.get_bytes("ghost"))
mydata.set_attribute("score", str(my_score.points)) mydata.set_attribute("score", str(my_score.points))
@ -768,18 +729,11 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
key=lambda s: (s[1].points, s[1].timestamp), key=lambda s: (s[1].points, s[1].timestamp),
reverse=True, reverse=True,
) )
all_players = { all_players = {uid: prof for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])}
uid: prof
for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])
}
shop_id = ID.parse_machine_id(request.attribute("location_id")) shop_id = ID.parse_machine_id(request.attribute("location_id"))
if not global_scores: if not global_scores:
all_scores = [ all_scores = [score for score in all_scores if (score[0] == userid or score[1].location == shop_id)]
score
for score in all_scores
if (score[0] == userid or score[1].location == shop_id)
]
# Find our actual index # Find our actual index
oldindex = None oldindex = None
@ -830,9 +784,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
# Shop ranking # Shop ranking
shopdata = Node.void("shopdata") shopdata = Node.void("shopdata")
root.add_child(shopdata) root.add_child(shopdata)
shopdata.set_attribute( shopdata.set_attribute("rank", "-1" if oldindex is None else str(oldindex + 1))
"rank", "-1" if oldindex is None else str(oldindex + 1)
)
# Grab the rank of some other players on this song # Grab the rank of some other players on this song
ranklist = Node.void("ranklist") ranklist = Node.void("ranklist")
@ -853,11 +805,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
all_players[uid] = prof all_players[uid] = prof
if not global_scores: if not global_scores:
all_scores = [ all_scores = [score for score in all_scores if (score[0] == userid or score[1].location == shop_id)]
score
for score in all_scores
if (score[0] == userid or score[1].location == shop_id)
]
# Find our actual index # Find our actual index
ourindex = None ourindex = None
@ -990,13 +938,9 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
} }
for item in request.children: for item in request.children:
if item.name == "music_list": if item.name == "music_list":
music_list[int(item.child_value("index"))] = int( music_list[int(item.child_value("index"))] = int(item.child_value("total_notes"))
item.child_value("total_notes")
)
if item.name == "cpu_list": if item.name == "cpu_list":
cpu_list[int(item.child_value("index"))] = int( cpu_list[int(item.child_value("index"))] = int(item.child_value("grade_id"))
item.child_value("grade_id")
)
for index in range(4): for index in range(4):
cpu_score_list = Node.void("cpu_score_list") cpu_score_list = Node.void("cpu_score_list")
cpu_score_list.add_child(Node.s32("index", index)) cpu_score_list.add_child(Node.s32("index", index))
@ -1099,9 +1043,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
root.add_child(event1_phase) root.add_child(event1_phase)
event1_phase.set_attribute("phase", str(event1)) event1_phase.set_attribute("phase", str(event1))
extra_boss_event = Node.void( extra_boss_event = Node.void("extra_boss_event") # Always enable IIDX AIR RACE 5
"extra_boss_event"
) # Always enable IIDX AIR RACE 5
root.add_child(extra_boss_event) root.add_child(extra_boss_event)
extra_boss_event.set_attribute("phase", "4") extra_boss_event.set_attribute("phase", "4")
@ -1270,9 +1212,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
used_secret_ids: List[int] = [] used_secret_ids: List[int] = []
for c in secret_courses: for c in secret_courses:
if c["id"] in used_secret_ids: if c["id"] in used_secret_ids:
raise Exception( raise Exception("Cannot have multiple secret courses with the same ID!")
"Cannot have multiple secret courses with the same ID!"
)
elif c["id"] < 0 or c["id"] >= 20: elif c["id"] < 0 or c["id"] >= 20:
raise Exception("Secret course ID is out of bounds!") raise Exception("Secret course ID is out of bounds!")
else: else:
@ -1483,25 +1423,15 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
root.add_child(arena_cpu_define) root.add_child(arena_cpu_define)
arena_cpu_define.add_child(Node.s32("play_style", playstyle)) arena_cpu_define.add_child(Node.s32("play_style", playstyle))
arena_cpu_define.add_child(Node.s32("arena_class", arena_class)) arena_cpu_define.add_child(Node.s32("arena_class", arena_class))
arena_cpu_define.add_child( arena_cpu_define.add_child(Node.s32("grade_id", cpu_grades[arena_class]))
Node.s32("grade_id", cpu_grades[arena_class]) arena_cpu_define.add_child(Node.s32("low_music_difficult", cpu_low_diff[arena_class]))
) arena_cpu_define.add_child(Node.s32("high_music_difficult", cpu_high_diff[arena_class]))
arena_cpu_define.add_child( arena_cpu_define.add_child(Node.bool("is_leggendaria", arena_class >= 13))
Node.s32("low_music_difficult", cpu_low_diff[arena_class])
)
arena_cpu_define.add_child(
Node.s32("high_music_difficult", cpu_high_diff[arena_class])
)
arena_cpu_define.add_child(
Node.bool("is_leggendaria", arena_class >= 13)
)
for matching_class in range(21): for matching_class in range(21):
matching_class_range = Node.void("matching_class_range") matching_class_range = Node.void("matching_class_range")
root.add_child(matching_class_range) root.add_child(matching_class_range)
matching_class_range.add_child(Node.s32("play_style", playstyle)) matching_class_range.add_child(Node.s32("play_style", playstyle))
matching_class_range.add_child( matching_class_range.add_child(Node.s32("matching_class", matching_class))
Node.s32("matching_class", matching_class)
)
matching_class_range.add_child(Node.s32("low_arena_class", 1)) matching_class_range.add_child(Node.s32("low_arena_class", 1))
matching_class_range.add_child(Node.s32("high_arena_class", 20)) matching_class_range.add_child(Node.s32("high_arena_class", 20))
return root return root
@ -1551,9 +1481,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
best_clear_string = clear_map.get(best_clear, "NO PLAY") best_clear_string = clear_map.get(best_clear, "NO PLAY")
now_clear_string = clear_map.get(now_clear, "NO PLAY") now_clear_string = clear_map.get(now_clear, "NO PLAY")
# let's get the song info first # let's get the song info first
song = self.data.local.music.get_song( song = self.data.local.music.get_song(self.game, self.music_version, music_id, self.game_to_db_chart(class_id))
self.game, self.music_version, music_id, self.game_to_db_chart(class_id)
)
notecount = song.data.get("notecount", 0) notecount = song.data.get("notecount", 0)
# Construct the dictionary for the broadcast # Construct the dictionary for the broadcast
card_data = { card_data = {
@ -1678,15 +1606,9 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
secret.add_child(Node.s64_array("flg2", [-1, -1, -1])) secret.add_child(Node.s64_array("flg2", [-1, -1, -1]))
secret.add_child(Node.s64_array("flg3", [-1, -1, -1])) secret.add_child(Node.s64_array("flg3", [-1, -1, -1]))
else: else:
secret.add_child( secret.add_child(Node.s64_array("flg1", secret_dict.get_int_array("flg1", 3)))
Node.s64_array("flg1", secret_dict.get_int_array("flg1", 3)) secret.add_child(Node.s64_array("flg2", secret_dict.get_int_array("flg2", 3)))
) secret.add_child(Node.s64_array("flg3", secret_dict.get_int_array("flg3", 3)))
secret.add_child(
Node.s64_array("flg2", secret_dict.get_int_array("flg2", 3))
)
secret.add_child(
Node.s64_array("flg3", secret_dict.get_int_array("flg3", 3))
)
# Favorites # Favorites
for folder in ["favorite1", "favorite2", "favorite3"]: for folder in ["favorite1", "favorite2", "favorite3"]:
@ -1748,9 +1670,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
) )
), ),
) )
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for rank in achievements: for rank in achievements:
if rank.type == self.DAN_RANKING_SINGLE: if rank.type == self.DAN_RANKING_SINGLE:
grade.add_child( grade.add_child(
@ -1822,21 +1742,11 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
qpro_secrete_dict = profile.get_dict("qpro_secret") qpro_secrete_dict = profile.get_dict("qpro_secret")
qpro_secret = Node.void("qpro_secret") qpro_secret = Node.void("qpro_secret")
root.add_child(qpro_secret) root.add_child(qpro_secret)
qpro_secret.add_child( qpro_secret.add_child(Node.s64_array("head", qpro_secrete_dict.get_int_array("head", 5)))
Node.s64_array("head", qpro_secrete_dict.get_int_array("head", 5)) qpro_secret.add_child(Node.s64_array("hair", qpro_secrete_dict.get_int_array("hair", 5)))
) qpro_secret.add_child(Node.s64_array("face", qpro_secrete_dict.get_int_array("face", 5)))
qpro_secret.add_child( qpro_secret.add_child(Node.s64_array("body", qpro_secrete_dict.get_int_array("body", 5)))
Node.s64_array("hair", qpro_secrete_dict.get_int_array("hair", 5)) qpro_secret.add_child(Node.s64_array("hand", qpro_secrete_dict.get_int_array("hand", 5)))
)
qpro_secret.add_child(
Node.s64_array("face", qpro_secrete_dict.get_int_array("face", 5))
)
qpro_secret.add_child(
Node.s64_array("body", qpro_secrete_dict.get_int_array("body", 5))
)
qpro_secret.add_child(
Node.s64_array("hand", qpro_secrete_dict.get_int_array("hand", 5))
)
# Rivals # Rivals
rlist = Node.void("rlist") rlist = Node.void("rlist")
@ -1908,9 +1818,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
[ [
courseid, # course ID courseid, # course ID
coursechart, # course chart coursechart, # course chart
self.db_to_game_status( self.db_to_game_status(course.data.get_int("clear_status")), # course clear status
course.data.get_int("clear_status")
), # course clear status
course.data.get_int("pgnum"), # flashing great count course.data.get_int("pgnum"), # flashing great count
course.data.get_int("gnum"), # great count course.data.get_int("gnum"), # great count
], ],
@ -1928,9 +1836,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
[ [
courseid, # course ID courseid, # course ID
coursechart, # course chart coursechart, # course chart
self.db_to_game_status( self.db_to_game_status(course.data.get_int("clear_status")), # course clear status
course.data.get_int("clear_status")
), # course clear status
course.data.get_int("pgnum"), # flashing great count course.data.get_int("pgnum"), # flashing great count
course.data.get_int("gnum"), # great count course.data.get_int("gnum"), # great count
], ],
@ -1965,12 +1871,8 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
dj_rank_node = Node.void("dj_rank") dj_rank_node = Node.void("dj_rank")
root.add_child(dj_rank_node) root.add_child(dj_rank_node)
dj_rank_node.set_attribute("style", str(dj_rank.id)) dj_rank_node.set_attribute("style", str(dj_rank.id))
dj_rank_node.add_child( dj_rank_node.add_child(Node.s32_array("rank", dj_rank.data.get_int_array("rank", 15)))
Node.s32_array("rank", dj_rank.data.get_int_array("rank", 15)) dj_rank_node.add_child(Node.s32_array("point", dj_rank.data.get_int_array("point", 15)))
)
dj_rank_node.add_child(
Node.s32_array("point", dj_rank.data.get_int_array("point", 15))
)
for i in range(2): for i in range(2):
for j in range(15): for j in range(15):
@ -1997,24 +1899,12 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
event1 = Node.void("event1") event1 = Node.void("event1")
root.add_child(event1) root.add_child(event1)
event1.set_attribute("tuneup_point", str(event1_dict.get_int("tuneup_point"))) event1.set_attribute("tuneup_point", str(event1_dict.get_int("tuneup_point")))
event1.set_attribute( event1.set_attribute("body_parts_list", str(event1_dict.get_int("body_parts_list")))
"body_parts_list", str(event1_dict.get_int("body_parts_list")) event1.set_attribute("engine_parts_list", str(event1_dict.get_int("engine_parts_list")))
) event1.set_attribute("tire_parts_list", str(event1_dict.get_int("tire_parts_list")))
event1.set_attribute( event1.set_attribute("body_equip_parts", str(event1_dict.get_int("body_equip_parts")))
"engine_parts_list", str(event1_dict.get_int("engine_parts_list")) event1.set_attribute("engine_equip_parts", str(event1_dict.get_int("engine_equip_parts")))
) event1.set_attribute("tire_equip_parts", str(event1_dict.get_int("tire_equip_parts")))
event1.set_attribute(
"tire_parts_list", str(event1_dict.get_int("tire_parts_list"))
)
event1.set_attribute(
"body_equip_parts", str(event1_dict.get_int("body_equip_parts"))
)
event1.set_attribute(
"engine_equip_parts", str(event1_dict.get_int("engine_equip_parts"))
)
event1.set_attribute(
"tire_equip_parts", str(event1_dict.get_int("tire_equip_parts"))
)
event1.set_attribute("gift_point", str(event1_dict.get_int("play_gift"))) event1.set_attribute("gift_point", str(event1_dict.get_int("play_gift")))
for map_data in achievements: for map_data in achievements:
@ -2023,59 +1913,29 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
map_data_node = Node.void("map_data") map_data_node = Node.void("map_data")
event1.add_child(map_data_node) event1.add_child(map_data_node)
map_data_node.set_attribute("map_id", str(map_data.id)) map_data_node.set_attribute("map_id", str(map_data.id))
map_data_node.set_attribute( map_data_node.set_attribute("play_num", str(map_data.data.get_int("play_num")))
"play_num", str(map_data.data.get_int("play_num")) map_data_node.set_attribute("progress", str(map_data.data.get_int("progress")))
) map_data_node.set_attribute("boost_fuel", str(map_data.data.get_int("boost_fuel")))
map_data_node.set_attribute( map_data_node.set_attribute("is_clear", str(map_data.data.get_int("is_clear")))
"progress", str(map_data.data.get_int("progress")) map_data_node.set_attribute("rare_defeat_list", str(map_data.data.get_int("rare_defeat_list")))
) map_data_node.set_attribute("rare1_appearance", str(map_data.data.get_int("rare1_appearance")))
map_data_node.set_attribute( map_data_node.set_attribute("rare2_appearance", str(map_data.data.get_int("rare2_appearance")))
"boost_fuel", str(map_data.data.get_int("boost_fuel")) map_data_node.set_attribute("rare3_appearance", str(map_data.data.get_int("rare3_appearance")))
) map_data_node.set_attribute("rare4_appearance", str(map_data.data.get_int("rare4_appearance")))
map_data_node.set_attribute( map_data_node.set_attribute("rare5_appearance", str(map_data.data.get_int("rare5_appearance")))
"is_clear", str(map_data.data.get_int("is_clear")) map_data_node.set_attribute("rare6_appearance", str(map_data.data.get_int("rare6_appearance")))
)
map_data_node.set_attribute(
"rare_defeat_list", str(map_data.data.get_int("rare_defeat_list"))
)
map_data_node.set_attribute(
"rare1_appearance", str(map_data.data.get_int("rare1_appearance"))
)
map_data_node.set_attribute(
"rare2_appearance", str(map_data.data.get_int("rare2_appearance"))
)
map_data_node.set_attribute(
"rare3_appearance", str(map_data.data.get_int("rare3_appearance"))
)
map_data_node.set_attribute(
"rare4_appearance", str(map_data.data.get_int("rare4_appearance"))
)
map_data_node.set_attribute(
"rare5_appearance", str(map_data.data.get_int("rare5_appearance"))
)
map_data_node.set_attribute(
"rare6_appearance", str(map_data.data.get_int("rare6_appearance"))
)
# OMES Data # OMES Data
omes_dict = profile.get_dict("omes") omes_dict = profile.get_dict("omes")
onemore_data = Node.void("onemore_event") onemore_data = Node.void("onemore_event")
root.add_child(onemore_data) root.add_child(onemore_data)
for i in range(6): for i in range(6):
onemore_data.set_attribute( onemore_data.set_attribute(f"defeat_{i}", str(omes_dict.get_int(f"defeat_{i}")))
f"defeat_{i}", str(omes_dict.get_int(f"defeat_{i}"))
)
for i in range(3): for i in range(3):
i = i + 1 i = i + 1
onemore_data.set_attribute( onemore_data.set_attribute(f"challenge_num_{i}_n", str(omes_dict.get_int(f"challenge_num_{i}_n")))
f"challenge_num_{i}_n", str(omes_dict.get_int(f"challenge_num_{i}_n")) onemore_data.set_attribute(f"challenge_num_{i}_h", str(omes_dict.get_int(f"challenge_num_{i}_h")))
) onemore_data.set_attribute(f"challenge_num_{i}_a", str(omes_dict.get_int(f"challenge_num_{i}_a")))
onemore_data.set_attribute(
f"challenge_num_{i}_h", str(omes_dict.get_int(f"challenge_num_{i}_h"))
)
onemore_data.set_attribute(
f"challenge_num_{i}_a", str(omes_dict.get_int(f"challenge_num_{i}_a"))
)
# Step up mode # Step up mode
step_dict = profile.get_dict("step") step_dict = profile.get_dict("step")
@ -2084,18 +1944,14 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
step.set_attribute("enemy_damage", str(step_dict.get_int("enemy_damage"))) step.set_attribute("enemy_damage", str(step_dict.get_int("enemy_damage")))
step.set_attribute("progress", str(step_dict.get_int("progress"))) step.set_attribute("progress", str(step_dict.get_int("progress")))
step.set_attribute("point", str(step_dict.get_int("point"))) step.set_attribute("point", str(step_dict.get_int("point")))
step.set_attribute( step.set_attribute("enemy_defeat_flg", str(step_dict.get_int("enemy_defeat_flg")))
"enemy_defeat_flg", str(step_dict.get_int("enemy_defeat_flg"))
)
step.set_attribute("sp_level", str(step_dict.get_int("sp_level"))) step.set_attribute("sp_level", str(step_dict.get_int("sp_level")))
step.set_attribute("dp_level", str(step_dict.get_int("dp_level"))) step.set_attribute("dp_level", str(step_dict.get_int("dp_level")))
step.set_attribute("sp_mplay", str(step_dict.get_int("sp_mplay"))) step.set_attribute("sp_mplay", str(step_dict.get_int("sp_mplay")))
step.set_attribute("dp_mplay", str(step_dict.get_int("dp_mplay"))) step.set_attribute("dp_mplay", str(step_dict.get_int("dp_mplay")))
# Daily recommendations # Daily recommendations
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "dailies")
self.game, self.version, "dailies"
)
if entry is not None: if entry is not None:
packinfo = Node.void("packinfo") packinfo = Node.void("packinfo")
root.add_child(packinfo) root.add_child(packinfo)
@ -2118,36 +1974,24 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
achievement_node.set_attribute("pack", "0") achievement_node.set_attribute("pack", "0")
achievement_node.set_attribute("pack_comp", "0") achievement_node.set_attribute("pack_comp", "0")
else: else:
daily_played = self.data.local.user.get_achievement( daily_played = self.data.local.user.get_achievement(self.game, self.version, userid, pack_id, "daily")
self.game, self.version, userid, pack_id, "daily"
)
if daily_played is None: if daily_played is None:
daily_played = ValidatedDict() daily_played = ValidatedDict()
achievement_node.set_attribute( achievement_node.set_attribute("pack", str(daily_played.get_int("pack_flg")))
"pack", str(daily_played.get_int("pack_flg")) achievement_node.set_attribute("pack_comp", str(daily_played.get_int("pack_comp")))
)
achievement_node.set_attribute(
"pack_comp", str(daily_played.get_int("pack_comp"))
)
# Weeklies # Weeklies
achievement_node.set_attribute( achievement_node.set_attribute("last_weekly", str(profile.get_int("last_weekly")))
"last_weekly", str(profile.get_int("last_weekly"))
)
achievement_node.set_attribute("weekly_num", str(profile.get_int("weekly_num"))) achievement_node.set_attribute("weekly_num", str(profile.get_int("weekly_num")))
# Prefecture visit flag # Prefecture visit flag
achievement_node.set_attribute("visit_flg", str(profile.get_int("visit_flg"))) achievement_node.set_attribute("visit_flg", str(profile.get_int("visit_flg")))
# Number of rivals beaten # Number of rivals beaten
achievement_node.set_attribute( achievement_node.set_attribute("rival_crush", str(profile.get_int("rival_crush")))
"rival_crush", str(profile.get_int("rival_crush"))
)
# Tran medals # Tran medals
achievement_node.add_child( achievement_node.add_child(Node.s64_array("trophy", profile.get_int_array("trophy", 20)))
Node.s64_array("trophy", profile.get_int_array("trophy", 20))
)
# Track deller # Track deller
deller = Node.void("deller") deller = Node.void("deller")
@ -2170,9 +2014,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
detail.set_attribute("course_id", str(rank.id)) detail.set_attribute("course_id", str(rank.id))
detail.set_attribute("n_point", str(rank.data.get_int("normal_points"))) detail.set_attribute("n_point", str(rank.data.get_int("normal_points")))
detail.set_attribute("h_point", str(rank.data.get_int("hyper_points"))) detail.set_attribute("h_point", str(rank.data.get_int("hyper_points")))
detail.set_attribute( detail.set_attribute("a_point", str(rank.data.get_int("another_points")))
"a_point", str(rank.data.get_int("another_points"))
)
nostalgia = Node.void("nostalgia_open") nostalgia = Node.void("nostalgia_open")
root.add_child(nostalgia) root.add_child(nostalgia)
@ -2185,9 +2027,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
pay_per_use.set_attribute("item_num", "99") pay_per_use.set_attribute("item_num", "99")
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -2239,12 +2079,8 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
newprofile.replace_int("d_gauge_disp", int(request.attribute("d_gauge_disp"))) newprofile.replace_int("d_gauge_disp", int(request.attribute("d_gauge_disp")))
newprofile.replace_int("s_lane_brignt", int(request.attribute("s_lane_brignt"))) newprofile.replace_int("s_lane_brignt", int(request.attribute("s_lane_brignt")))
newprofile.replace_int("d_lane_brignt", int(request.attribute("d_lane_brignt"))) newprofile.replace_int("d_lane_brignt", int(request.attribute("d_lane_brignt")))
newprofile.replace_int( newprofile.replace_int("s_camera_layout", int(request.attribute("s_camera_layout")))
"s_camera_layout", int(request.attribute("s_camera_layout")) newprofile.replace_int("d_camera_layout", int(request.attribute("d_camera_layout")))
)
newprofile.replace_int(
"d_camera_layout", int(request.attribute("d_camera_layout"))
)
newprofile.replace_int("s_lift", int(request.attribute("s_lift"))) newprofile.replace_int("s_lift", int(request.attribute("s_lift")))
newprofile.replace_int("d_lift", int(request.attribute("d_lift"))) newprofile.replace_int("d_lift", int(request.attribute("d_lift")))
newprofile.replace_int("mode", int(request.attribute("mode"))) newprofile.replace_int("mode", int(request.attribute("mode")))
@ -2272,15 +2108,9 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
# Basic achievements # Basic achievements
achievements = request.child("achievements") achievements = request.child("achievements")
if achievements is not None: if achievements is not None:
newprofile.replace_int( newprofile.replace_int("visit_flg", int(achievements.attribute("visit_flg")))
"visit_flg", int(achievements.attribute("visit_flg")) newprofile.replace_int("last_weekly", int(achievements.attribute("last_weekly")))
) newprofile.replace_int("weekly_num", int(achievements.attribute("weekly_num")))
newprofile.replace_int(
"last_weekly", int(achievements.attribute("last_weekly"))
)
newprofile.replace_int(
"weekly_num", int(achievements.attribute("weekly_num"))
)
pack_id = int(achievements.attribute("pack_id")) pack_id = int(achievements.attribute("pack_id"))
if pack_id > 0: if pack_id > 0:
@ -2304,9 +2134,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
# Deller saving # Deller saving
deller = request.child("deller") deller = request.child("deller")
if deller is not None: if deller is not None:
newprofile.replace_int( newprofile.replace_int("deller", newprofile.get_int("deller") + int(deller.attribute("deller")))
"deller", newprofile.get_int("deller") + int(deller.attribute("deller"))
)
# Secret course expert point saving # Secret course expert point saving
expert_point = request.child("expert_point") expert_point = request.child("expert_point")
@ -2370,22 +2198,14 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
for i in range(self.FAVORITE_LIST_LENGTH): for i in range(self.FAVORITE_LIST_LENGTH):
singles.append( singles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", single_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", single_music_bin[(i * 4) : ((i + 1) * 4)] "chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[0],
)[0],
"chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[
0
],
} }
) )
doubles.append( doubles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", double_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", double_music_bin[(i * 4) : ((i + 1) * 4)] "chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[0],
)[0],
"chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[
0
],
} }
) )
@ -2426,27 +2246,13 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
event1 = request.child("event1") event1 = request.child("event1")
if event1 is not None: if event1 is not None:
event1_dict = newprofile.get_dict("event1") event1_dict = newprofile.get_dict("event1")
event1_dict.replace_int( event1_dict.replace_int("tuneup_point", int(event1.attribute("tuneup_point")))
"tuneup_point", int(event1.attribute("tuneup_point")) event1_dict.replace_int("body_parts_list", int(event1.attribute("body_parts_list")))
) event1_dict.replace_int("engine_parts_list", int(event1.attribute("engine_parts_list")))
event1_dict.replace_int( event1_dict.replace_int("tire_parts_list", int(event1.attribute("tire_parts_list")))
"body_parts_list", int(event1.attribute("body_parts_list")) event1_dict.replace_int("body_equip_parts", int(event1.attribute("body_equip_parts")))
) event1_dict.replace_int("engine_equip_parts", int(event1.attribute("engine_equip_parts")))
event1_dict.replace_int( event1_dict.replace_int("tire_equip_parts", int(event1.attribute("tire_equip_parts")))
"engine_parts_list", int(event1.attribute("engine_parts_list"))
)
event1_dict.replace_int(
"tire_parts_list", int(event1.attribute("tire_parts_list"))
)
event1_dict.replace_int(
"body_equip_parts", int(event1.attribute("body_equip_parts"))
)
event1_dict.replace_int(
"engine_equip_parts", int(event1.attribute("engine_equip_parts"))
)
event1_dict.replace_int(
"tire_equip_parts", int(event1.attribute("tire_equip_parts"))
)
event1_dict.replace_int("play_gift", int(event1.attribute("play_gift"))) event1_dict.replace_int("play_gift", int(event1.attribute("play_gift")))
event1_dict.replace_bool("is_use_gift", event1.child_value("is_use_gift")) event1_dict.replace_bool("is_use_gift", event1.child_value("is_use_gift"))
for map_data in event1.children: for map_data in event1.children:
@ -2494,9 +2300,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
step_dict.replace_int("enemy_damage", int(step.attribute("enemy_damage"))) step_dict.replace_int("enemy_damage", int(step.attribute("enemy_damage")))
step_dict.replace_int("progress", int(step.attribute("progress"))) step_dict.replace_int("progress", int(step.attribute("progress")))
step_dict.replace_int("point", int(step.attribute("point"))) step_dict.replace_int("point", int(step.attribute("point")))
step_dict.replace_int( step_dict.replace_int("enemy_defeat_flg", int(step.attribute("enemy_defeat_flg")))
"enemy_defeat_flg", int(step.attribute("enemy_defeat_flg"))
)
step_dict.replace_int("sp_level", int(step.attribute("sp_level"))) step_dict.replace_int("sp_level", int(step.attribute("sp_level")))
step_dict.replace_int("dp_level", int(step.attribute("dp_level"))) step_dict.replace_int("dp_level", int(step.attribute("dp_level")))
step_dict.replace_int("sp_mplay", int(step.attribute("sp_mplay"))) step_dict.replace_int("sp_mplay", int(step.attribute("sp_mplay")))
@ -2518,21 +2322,11 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
qpro_secret = request.child("qpro_secret") qpro_secret = request.child("qpro_secret")
if qpro_secret is not None: if qpro_secret is not None:
qpro_secret_dict = newprofile.get_dict("qpro_secret") qpro_secret_dict = newprofile.get_dict("qpro_secret")
qpro_secret_dict.replace_int_array( qpro_secret_dict.replace_int_array("head", 5, qpro_secret.child_value("head"))
"head", 5, qpro_secret.child_value("head") qpro_secret_dict.replace_int_array("hair", 5, qpro_secret.child_value("hair"))
) qpro_secret_dict.replace_int_array("face", 5, qpro_secret.child_value("face"))
qpro_secret_dict.replace_int_array( qpro_secret_dict.replace_int_array("body", 5, qpro_secret.child_value("body"))
"hair", 5, qpro_secret.child_value("hair") qpro_secret_dict.replace_int_array("hand", 5, qpro_secret.child_value("hand"))
)
qpro_secret_dict.replace_int_array(
"face", 5, qpro_secret.child_value("face")
)
qpro_secret_dict.replace_int_array(
"body", 5, qpro_secret.child_value("body")
)
qpro_secret_dict.replace_int_array(
"hand", 5, qpro_secret.child_value("hand")
)
newprofile.replace_dict("qpro_secret", qpro_secret_dict) newprofile.replace_dict("qpro_secret", qpro_secret_dict)
# Orb data saving # Orb data saving
@ -2549,9 +2343,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
if onemore_data is not None: if onemore_data is not None:
omes_dict = newprofile.get_dict("omes") omes_dict = newprofile.get_dict("omes")
for i in range(6): for i in range(6):
omes_dict.replace_int( omes_dict.replace_int(f"defeat_{i}", int(onemore_data.attribute(f"defeat_{i}")))
f"defeat_{i}", int(onemore_data.attribute(f"defeat_{i}"))
)
for i in range(3): for i in range(3):
i = i + 1 i = i + 1
omes_dict.replace_int( omes_dict.replace_int(

View File

@ -104,28 +104,15 @@ class IIDXCopula(IIDXCourse, IIDXBase):
return IIDXPendual(self.data, self.config, self.model) return IIDXPendual(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert dailies into the DB. Insert dailies into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "daily_charts", "daily"):
cls.game, cls.version, "daily_charts", "daily"
):
# Generate a new list of three dailies. # Generate a new list of three dailies.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = list( all_songs = list(set([song.id for song in data.local.music.get_all_songs(cls.game, cls.version)]))
set(
[
song.id
for song in data.local.music.get_all_songs(
cls.game, cls.version
)
]
)
)
if len(all_songs) >= 3: if len(all_songs) >= 3:
daily_songs = random.sample(all_songs, 3) daily_songs = random.sample(all_songs, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -149,9 +136,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "daily_charts", "daily")
cls.game, cls.version, "daily_charts", "daily"
)
return events return events
@classmethod @classmethod
@ -357,9 +342,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
root = Node.void("IIDX23shop") root = Node.void("IIDX23shop")
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -383,9 +366,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
course.replace_int("music_2", request.child_value("music_2")) course.replace_int("music_2", request.child_value("music_2"))
course.replace_int("music_3", request.child_value("music_3")) course.replace_int("music_3", request.child_value("music_3"))
course.replace_bool("valid", request.child_value("valid")) course.replace_bool("valid", request.child_value("valid"))
self.data.local.machine.put_settings( self.data.local.machine.put_settings(machine.arcade, self.game, self.music_version, "shop_course", course)
machine.arcade, self.game, self.music_version, "shop_course", course
)
return root return root
@ -410,9 +391,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -527,16 +506,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
root = Node.void("IIDX23music") root = Node.void("IIDX23music")
attempts = self.get_clear_rates() attempts = self.get_clear_rates()
all_songs = list( all_songs = list(set([song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)]))
set(
[
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
]
)
)
for song in all_songs: for song in all_songs:
clears = [] clears = []
fcs = [] fcs = []
@ -580,16 +550,12 @@ class IIDXCopula(IIDXCourse, IIDXBase):
continue continue
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
# Grab score data for user/rival # Grab score data for user/rival
scoredata = self.make_score_struct( scoredata = self.make_score_struct(
scores, scores,
self.CLEAR_TYPE_SINGLE self.CLEAR_TYPE_SINGLE if cltype == self.GAME_CLTYPE_SINGLE else self.CLEAR_TYPE_DOUBLE,
if cltype == self.GAME_CLTYPE_SINGLE
else self.CLEAR_TYPE_DOUBLE,
rivalid, rivalid,
) )
for s in scoredata: for s in scoredata:
@ -597,10 +563,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
# Grab most played for user/rival # Grab most played for user/rival
most_played = [ most_played = [
play[0] play[0] for play in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)
for play in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
] ]
if len(most_played) < 20: if len(most_played) < 20:
most_played.extend([0] * (20 - len(most_played))) most_played.extend([0] * (20 - len(most_played)))
@ -643,19 +606,13 @@ class IIDXCopula(IIDXCourse, IIDXBase):
key=lambda s: (s[1].points, s[1].timestamp), key=lambda s: (s[1].points, s[1].timestamp),
reverse=True, reverse=True,
) )
all_players = { all_players = {uid: prof for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])}
uid: prof
for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])
}
if not global_scores: if not global_scores:
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -707,9 +664,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
# Shop ranking # Shop ranking
shopdata = Node.void("shopdata") shopdata = Node.void("shopdata")
root.add_child(shopdata) root.add_child(shopdata)
shopdata.set_attribute( shopdata.set_attribute("rank", "-1" if oldindex is None else str(oldindex + 1))
"rank", "-1" if oldindex is None else str(oldindex + 1)
)
# Grab the rank of some other players on this song # Grab the rank of some other players on this song
ranklist = Node.void("ranklist") ranklist = Node.void("ranklist")
@ -733,10 +688,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -884,9 +836,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
if userid is not None: if userid is not None:
# Try to look up previous ghost for user # Try to look up previous ghost for user
my_score = self.data.remote.music.get_score( my_score = self.data.remote.music.get_score(self.game, self.music_version, userid, musicid, chart)
self.game, self.music_version, userid, musicid, chart
)
if my_score is not None: if my_score is not None:
mydata = Node.binary("mydata", my_score.data.get_bytes("ghost")) mydata = Node.binary("mydata", my_score.data.get_bytes("ghost"))
mydata.set_attribute("score", str(my_score.points)) mydata.set_attribute("score", str(my_score.points))
@ -1318,9 +1268,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
used_secret_ids: List[int] = [] used_secret_ids: List[int] = []
for c in secret_courses: for c in secret_courses:
if c["id"] in used_secret_ids: if c["id"] in used_secret_ids:
raise Exception( raise Exception("Cannot have multiple secret courses with the same ID!")
"Cannot have multiple secret courses with the same ID!"
)
elif c["id"] < 0 or c["id"] >= 20: elif c["id"] < 0 or c["id"] >= 20:
raise Exception("Secret course ID is out of bounds!") raise Exception("Secret course ID is out of bounds!")
else: else:
@ -1497,9 +1445,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
best_clear_string = clear_map.get(best_clear, "NO PLAY") best_clear_string = clear_map.get(best_clear, "NO PLAY")
now_clear_string = clear_map.get(now_clear, "NO PLAY") now_clear_string = clear_map.get(now_clear, "NO PLAY")
# let's get the song info first # let's get the song info first
song = self.data.local.music.get_song( song = self.data.local.music.get_song(self.game, self.music_version, music_id, self.game_to_db_chart(class_id))
self.game, self.music_version, music_id, self.game_to_db_chart(class_id)
)
notecount = song.data.get("notecount", 0) notecount = song.data.get("notecount", 0)
# Construct the dictionary for the broadcast # Construct the dictionary for the broadcast
card_data = { card_data = {
@ -1609,15 +1555,9 @@ class IIDXCopula(IIDXCourse, IIDXBase):
secret.add_child(Node.s64_array("flg2", [-1, -1, -1, -1])) secret.add_child(Node.s64_array("flg2", [-1, -1, -1, -1]))
secret.add_child(Node.s64_array("flg3", [-1, -1, -1, -1])) secret.add_child(Node.s64_array("flg3", [-1, -1, -1, -1]))
else: else:
secret.add_child( secret.add_child(Node.s64_array("flg1", secret_dict.get_int_array("flg1", 4)))
Node.s64_array("flg1", secret_dict.get_int_array("flg1", 4)) secret.add_child(Node.s64_array("flg2", secret_dict.get_int_array("flg2", 4)))
) secret.add_child(Node.s64_array("flg3", secret_dict.get_int_array("flg3", 4)))
secret.add_child(
Node.s64_array("flg2", secret_dict.get_int_array("flg2", 4))
)
secret.add_child(
Node.s64_array("flg3", secret_dict.get_int_array("flg3", 4))
)
# Favorites # Favorites
for folder in ["favorite1", "favorite2", "favorite3"]: for folder in ["favorite1", "favorite2", "favorite3"]:
@ -1679,9 +1619,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
) )
), ),
) )
rankings = self.data.local.user.get_achievements( rankings = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for rank in rankings: for rank in rankings:
if rank.type == self.DAN_RANKING_SINGLE: if rank.type == self.DAN_RANKING_SINGLE:
grade.add_child( grade.add_child(
@ -1822,9 +1760,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
[ [
int(rank.id / 6), # course ID int(rank.id / 6), # course ID
rank.id % 6, # course chart rank.id % 6, # course chart
self.db_to_game_status( self.db_to_game_status(rank.data.get_int("clear_status")), # course clear status
rank.data.get_int("clear_status")
), # course clear status
rank.data.get_int("pgnum"), # flashing great count rank.data.get_int("pgnum"), # flashing great count
rank.data.get_int("gnum"), # great count rank.data.get_int("gnum"), # great count
], ],
@ -1841,9 +1777,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
[ [
int(rank.id / 6), # course ID int(rank.id / 6), # course ID
rank.id % 6, # course chart rank.id % 6, # course chart
self.db_to_game_status( self.db_to_game_status(rank.data.get_int("clear_status")), # course clear status
rank.data.get_int("clear_status")
), # course clear status
rank.data.get_int("pgnum"), # flashing great count rank.data.get_int("pgnum"), # flashing great count
rank.data.get_int("gnum"), # great count rank.data.get_int("gnum"), # great count
], ],
@ -1881,16 +1815,12 @@ class IIDXCopula(IIDXCourse, IIDXBase):
step.add_child( step.add_child(
Node.binary( Node.binary(
"tokimeki", "tokimeki",
step_dict.get_bytes( step_dict.get_bytes("tokimeki", b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
"tokimeki", b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
),
) )
) )
# Daily recommendations # Daily recommendations
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "dailies")
self.game, self.version, "dailies"
)
if entry is not None: if entry is not None:
packinfo = Node.void("packinfo") packinfo = Node.void("packinfo")
root.add_child(packinfo) root.add_child(packinfo)
@ -1913,15 +1843,11 @@ class IIDXCopula(IIDXCourse, IIDXBase):
achievements.set_attribute("pack", "0") achievements.set_attribute("pack", "0")
achievements.set_attribute("pack_comp", "0") achievements.set_attribute("pack_comp", "0")
else: else:
daily_played = self.data.local.user.get_achievement( daily_played = self.data.local.user.get_achievement(self.game, self.version, userid, pack_id, "daily")
self.game, self.version, userid, pack_id, "daily"
)
if daily_played is None: if daily_played is None:
daily_played = ValidatedDict() daily_played = ValidatedDict()
achievements.set_attribute("pack", str(daily_played.get_int("pack_flg"))) achievements.set_attribute("pack", str(daily_played.get_int("pack_flg")))
achievements.set_attribute( achievements.set_attribute("pack_comp", str(daily_played.get_int("pack_comp")))
"pack_comp", str(daily_played.get_int("pack_comp"))
)
# Weeklies # Weeklies
achievements.set_attribute("last_weekly", str(profile.get_int("last_weekly"))) achievements.set_attribute("last_weekly", str(profile.get_int("last_weekly")))
@ -1934,9 +1860,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
achievements.set_attribute("rival_crush", str(profile.get_int("rival_crush"))) achievements.set_attribute("rival_crush", str(profile.get_int("rival_crush")))
# Tran medals # Tran medals
achievements.add_child( achievements.add_child(Node.s64_array("trophy", profile.get_int_array("trophy", 10)))
Node.s64_array("trophy", profile.get_int_array("trophy", 10))
)
# Track deller # Track deller
deller = Node.void("deller") deller = Node.void("deller")
@ -1959,9 +1883,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
detail.set_attribute("course_id", str(rank.id)) detail.set_attribute("course_id", str(rank.id))
detail.set_attribute("n_point", str(rank.data.get_int("normal_points"))) detail.set_attribute("n_point", str(rank.data.get_int("normal_points")))
detail.set_attribute("h_point", str(rank.data.get_int("hyper_points"))) detail.set_attribute("h_point", str(rank.data.get_int("hyper_points")))
detail.set_attribute( detail.set_attribute("a_point", str(rank.data.get_int("another_points")))
"a_point", str(rank.data.get_int("another_points"))
)
# Tokotoko Line Event # Tokotoko Line Event
if "event1" in profile: if "event1" in profile:
@ -1969,31 +1891,15 @@ class IIDXCopula(IIDXCourse, IIDXBase):
event1_dict = profile.get_dict("event1") event1_dict = profile.get_dict("event1")
event1_data = Node.void("event1_data") event1_data = Node.void("event1_data")
root.add_child(event1_data) root.add_child(event1_data)
event1_data.set_attribute( event1_data.set_attribute("point_map_0", str(event1_dict.get_int("point_map_0")))
"point_map_0", str(event1_dict.get_int("point_map_0")) event1_data.set_attribute("point_map_1", str(event1_dict.get_int("point_map_1")))
) event1_data.set_attribute("point_map_2", str(event1_dict.get_int("point_map_2")))
event1_data.set_attribute( event1_data.set_attribute("point_map_3", str(event1_dict.get_int("point_map_3")))
"point_map_1", str(event1_dict.get_int("point_map_1")) event1_data.set_attribute("point_map_4", str(event1_dict.get_int("point_map_4")))
) event1_data.set_attribute("hold_point", str(event1_dict.get_int("hold_point")))
event1_data.set_attribute(
"point_map_2", str(event1_dict.get_int("point_map_2"))
)
event1_data.set_attribute(
"point_map_3", str(event1_dict.get_int("point_map_3"))
)
event1_data.set_attribute(
"point_map_4", str(event1_dict.get_int("point_map_4"))
)
event1_data.set_attribute(
"hold_point", str(event1_dict.get_int("hold_point"))
)
event1_data.set_attribute("last_map", str(event1_dict.get_int("last_map"))) event1_data.set_attribute("last_map", str(event1_dict.get_int("last_map")))
event1_data.set_attribute( event1_data.set_attribute("rank_point", str(event1_dict.get_int("rank_point")))
"rank_point", str(event1_dict.get_int("rank_point")) event1_data.set_attribute("tips_list", str(event1_dict.get_int("tips_list")))
)
event1_data.set_attribute(
"tips_list", str(event1_dict.get_int("tips_list"))
)
event1_data.set_attribute("gift_point", "0") event1_data.set_attribute("gift_point", "0")
# Mystery Line Event # Mystery Line Event
@ -2004,16 +1910,10 @@ class IIDXCopula(IIDXCourse, IIDXBase):
root.add_child(event2_data) root.add_child(event2_data)
event2_data.set_attribute("play_num", str(event2_dict.get_int("play_num"))) event2_data.set_attribute("play_num", str(event2_dict.get_int("play_num")))
event2_data.set_attribute("now_area", str(event2_dict.get_int("now_area"))) event2_data.set_attribute("now_area", str(event2_dict.get_int("now_area")))
event2_data.set_attribute( event2_data.set_attribute("now_note_grade", str(event2_dict.get_int("now_note_grade")))
"now_note_grade", str(event2_dict.get_int("now_note_grade")) event2_data.set_attribute("stop_area_time", str(event2_dict.get_int("stop_area_time")))
)
event2_data.set_attribute(
"stop_area_time", str(event2_dict.get_int("stop_area_time"))
)
areas = self.data.local.user.get_achievements( areas = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for area in areas: for area in areas:
if area.type != "event2_area_data": if area.type != "event2_area_data":
continue continue
@ -2021,18 +1921,10 @@ class IIDXCopula(IIDXCourse, IIDXBase):
event2_area_data = Node.void("event2_area_data") event2_area_data = Node.void("event2_area_data")
event2_data.add_child(event2_area_data) event2_data.add_child(event2_area_data)
event2_area_data.set_attribute("area_no", str(area.id)) event2_area_data.set_attribute("area_no", str(area.id))
event2_area_data.set_attribute( event2_area_data.set_attribute("area_play", str(area.data.get_int("play_num")))
"area_play", str(area.data.get_int("play_num")) event2_area_data.set_attribute("normal_point", str(area.data.get_int("normal_point")))
) event2_area_data.set_attribute("hyper_point", str(area.data.get_int("hyper_point")))
event2_area_data.set_attribute( event2_area_data.set_attribute("another_point", str(area.data.get_int("another_point")))
"normal_point", str(area.data.get_int("normal_point"))
)
event2_area_data.set_attribute(
"hyper_point", str(area.data.get_int("hyper_point"))
)
event2_area_data.set_attribute(
"another_point", str(area.data.get_int("another_point"))
)
# One More Event # One More Event
if "onemore" in profile: if "onemore" in profile:
@ -2040,42 +1932,22 @@ class IIDXCopula(IIDXCourse, IIDXBase):
onemore_dict = profile.get_dict("onemore") onemore_dict = profile.get_dict("onemore")
onemore_data = Node.void("onemore_data") onemore_data = Node.void("onemore_data")
root.add_child(onemore_data) root.add_child(onemore_data)
onemore_data.set_attribute( onemore_data.set_attribute("defeat_0", str(onemore_dict.get_int("defeat_0")))
"defeat_0", str(onemore_dict.get_int("defeat_0")) onemore_data.set_attribute("defeat_1", str(onemore_dict.get_int("defeat_1")))
) onemore_data.set_attribute("defeat_2", str(onemore_dict.get_int("defeat_2")))
onemore_data.set_attribute( onemore_data.set_attribute("defeat_3", str(onemore_dict.get_int("defeat_3")))
"defeat_1", str(onemore_dict.get_int("defeat_1")) onemore_data.set_attribute("defeat_4", str(onemore_dict.get_int("defeat_4")))
) onemore_data.set_attribute("defeat_5", str(onemore_dict.get_int("defeat_5")))
onemore_data.set_attribute( onemore_data.set_attribute("challenge_num_n", str(onemore_dict.get_int("challenge_num_n")))
"defeat_2", str(onemore_dict.get_int("defeat_2")) onemore_data.set_attribute("challenge_num_h", str(onemore_dict.get_int("challenge_num_h")))
) onemore_data.set_attribute("challenge_num_a", str(onemore_dict.get_int("challenge_num_a")))
onemore_data.set_attribute(
"defeat_3", str(onemore_dict.get_int("defeat_3"))
)
onemore_data.set_attribute(
"defeat_4", str(onemore_dict.get_int("defeat_4"))
)
onemore_data.set_attribute(
"defeat_5", str(onemore_dict.get_int("defeat_5"))
)
onemore_data.set_attribute(
"challenge_num_n", str(onemore_dict.get_int("challenge_num_n"))
)
onemore_data.set_attribute(
"challenge_num_h", str(onemore_dict.get_int("challenge_num_h"))
)
onemore_data.set_attribute(
"challenge_num_a", str(onemore_dict.get_int("challenge_num_a"))
)
# Ea app features # Ea app features
if self.data.triggers.has_broadcast_destination(self.game): if self.data.triggers.has_broadcast_destination(self.game):
root.add_child(Node.void("bind_eaappli")) root.add_child(Node.void("bind_eaappli"))
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -2151,15 +2023,9 @@ class IIDXCopula(IIDXCourse, IIDXBase):
# Basic achievements # Basic achievements
achievements = request.child("achievements") achievements = request.child("achievements")
if achievements is not None: if achievements is not None:
newprofile.replace_int( newprofile.replace_int("visit_flg", int(achievements.attribute("visit_flg")))
"visit_flg", int(achievements.attribute("visit_flg")) newprofile.replace_int("last_weekly", int(achievements.attribute("last_weekly")))
) newprofile.replace_int("weekly_num", int(achievements.attribute("weekly_num")))
newprofile.replace_int(
"last_weekly", int(achievements.attribute("last_weekly"))
)
newprofile.replace_int(
"weekly_num", int(achievements.attribute("weekly_num"))
)
pack_id = int(achievements.attribute("pack_id")) pack_id = int(achievements.attribute("pack_id"))
if pack_id > 0: if pack_id > 0:
@ -2183,9 +2049,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
# Deller saving # Deller saving
deller = request.child("deller") deller = request.child("deller")
if deller is not None: if deller is not None:
newprofile.replace_int( newprofile.replace_int("deller", newprofile.get_int("deller") + int(deller.attribute("deller")))
"deller", newprofile.get_int("deller") + int(deller.attribute("deller"))
)
# Secret course expert point saving # Secret course expert point saving
expert_point = request.child("expert_point") expert_point = request.child("expert_point")
@ -2249,22 +2113,14 @@ class IIDXCopula(IIDXCourse, IIDXBase):
for i in range(self.FAVORITE_LIST_LENGTH): for i in range(self.FAVORITE_LIST_LENGTH):
singles.append( singles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", single_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", single_music_bin[(i * 4) : ((i + 1) * 4)] "chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[0],
)[0],
"chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[
0
],
} }
) )
doubles.append( doubles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", double_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", double_music_bin[(i * 4) : ((i + 1) * 4)] "chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[0],
)[0],
"chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[
0
],
} }
) )
@ -2312,47 +2168,25 @@ class IIDXCopula(IIDXCourse, IIDXBase):
event1_data = request.child("event1_data") event1_data = request.child("event1_data")
if event1_data is not None: if event1_data is not None:
event1_dict = newprofile.get_dict("event1") event1_dict = newprofile.get_dict("event1")
event1_dict.replace_int( event1_dict.replace_int("hold_point", int(event1_data.attribute("hold_point")))
"hold_point", int(event1_data.attribute("hold_point"))
)
event1_dict.replace_int("last_map", int(event1_data.attribute("last_map"))) event1_dict.replace_int("last_map", int(event1_data.attribute("last_map")))
event1_dict.replace_int( event1_dict.replace_int("rank_point", int(event1_data.attribute("rank_point")))
"rank_point", int(event1_data.attribute("rank_point")) event1_dict.replace_int("tips_list", int(event1_data.attribute("tips_list")))
) event1_dict.replace_int("point_map_0", int(event1_data.attribute("point_map_0")))
event1_dict.replace_int( event1_dict.replace_int("point_map_1", int(event1_data.attribute("point_map_1")))
"tips_list", int(event1_data.attribute("tips_list")) event1_dict.replace_int("point_map_2", int(event1_data.attribute("point_map_2")))
) event1_dict.replace_int("point_map_3", int(event1_data.attribute("point_map_3")))
event1_dict.replace_int( event1_dict.replace_int("point_map_4", int(event1_data.attribute("point_map_4")))
"point_map_0", int(event1_data.attribute("point_map_0"))
)
event1_dict.replace_int(
"point_map_1", int(event1_data.attribute("point_map_1"))
)
event1_dict.replace_int(
"point_map_2", int(event1_data.attribute("point_map_2"))
)
event1_dict.replace_int(
"point_map_3", int(event1_data.attribute("point_map_3"))
)
event1_dict.replace_int(
"point_map_4", int(event1_data.attribute("point_map_4"))
)
newprofile.replace_dict("event1", event1_dict) newprofile.replace_dict("event1", event1_dict)
# Mystery Line Event # Mystery Line Event
event2_data = request.child("event2_data") event2_data = request.child("event2_data")
if event2_data is not None: if event2_data is not None:
event2_dict = newprofile.get_dict("event2") event2_dict = newprofile.get_dict("event2")
event2_dict.replace_int( event2_dict.replace_int("now_area", int(event2_data.attribute("now_stay_area")))
"now_area", int(event2_data.attribute("now_stay_area")) event2_dict.replace_int("now_note_grade", int(event2_data.attribute("now_stay_note_grade")))
)
event2_dict.replace_int(
"now_note_grade", int(event2_data.attribute("now_stay_note_grade"))
)
event2_dict.replace_int("play_num", int(event2_data.attribute("play_num"))) event2_dict.replace_int("play_num", int(event2_data.attribute("play_num")))
event2_dict.replace_int( event2_dict.replace_int("stop_area_time", int(event2_data.attribute("stop_area_time")))
"stop_area_time", int(event2_data.attribute("stop_area_time"))
)
newprofile.replace_dict("event2", event2_dict) newprofile.replace_dict("event2", event2_dict)
for area_data in event2_data.children: for area_data in event2_data.children:
@ -2378,33 +2212,15 @@ class IIDXCopula(IIDXCourse, IIDXBase):
onemore_data = request.child("onemore_data") onemore_data = request.child("onemore_data")
if onemore_data is not None: if onemore_data is not None:
onemore_dict = newprofile.get_dict("onemore") onemore_dict = newprofile.get_dict("onemore")
onemore_dict.replace_int( onemore_dict.replace_int("defeat_0", int(onemore_data.attribute("defeat_0")))
"defeat_0", int(onemore_data.attribute("defeat_0")) onemore_dict.replace_int("defeat_1", int(onemore_data.attribute("defeat_1")))
) onemore_dict.replace_int("defeat_2", int(onemore_data.attribute("defeat_2")))
onemore_dict.replace_int( onemore_dict.replace_int("defeat_3", int(onemore_data.attribute("defeat_3")))
"defeat_1", int(onemore_data.attribute("defeat_1")) onemore_dict.replace_int("defeat_4", int(onemore_data.attribute("defeat_4")))
) onemore_dict.replace_int("defeat_5", int(onemore_data.attribute("defeat_5")))
onemore_dict.replace_int( onemore_dict.replace_int("challenge_num_n", int(onemore_data.attribute("challenge_num_n")))
"defeat_2", int(onemore_data.attribute("defeat_2")) onemore_dict.replace_int("challenge_num_h", int(onemore_data.attribute("challenge_num_h")))
) onemore_dict.replace_int("challenge_num_a", int(onemore_data.attribute("challenge_num_a")))
onemore_dict.replace_int(
"defeat_3", int(onemore_data.attribute("defeat_3"))
)
onemore_dict.replace_int(
"defeat_4", int(onemore_data.attribute("defeat_4"))
)
onemore_dict.replace_int(
"defeat_5", int(onemore_data.attribute("defeat_5"))
)
onemore_dict.replace_int(
"challenge_num_n", int(onemore_data.attribute("challenge_num_n"))
)
onemore_dict.replace_int(
"challenge_num_h", int(onemore_data.attribute("challenge_num_h"))
)
onemore_dict.replace_int(
"challenge_num_a", int(onemore_data.attribute("challenge_num_a"))
)
newprofile.replace_dict("onemore", onemore_dict) newprofile.replace_dict("onemore", onemore_dict)
# Keep track of play statistics across all mixes # Keep track of play statistics across all mixes

View File

@ -56,12 +56,8 @@ class IIDXCourse(IIDXBase):
) )
if course_score is None: if course_score is None:
course_score = ValidatedDict() course_score = ValidatedDict()
course_score.replace_int( course_score.replace_int("clear_status", max(clear_status, course_score.get_int("clear_status")))
"clear_status", max(clear_status, course_score.get_int("clear_status")) old_ex_score = (course_score.get_int("pgnum") * 2) + course_score.get_int("gnum")
)
old_ex_score = (course_score.get_int("pgnum") * 2) + course_score.get_int(
"gnum"
)
if old_ex_score < ((pgreats * 2) + greats): if old_ex_score < ((pgreats * 2) + greats):
course_score.replace_int("pgnum", pgreats) course_score.replace_int("pgnum", pgreats)
course_score.replace_int("gnum", greats) course_score.replace_int("gnum", greats)

View File

@ -101,28 +101,15 @@ class IIDXPendual(IIDXCourse, IIDXBase):
return IIDXSpada(self.data, self.config, self.model) return IIDXSpada(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert dailies into the DB. Insert dailies into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "daily_charts", "daily"):
cls.game, cls.version, "daily_charts", "daily"
):
# Generate a new list of three dailies. # Generate a new list of three dailies.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = list( all_songs = list(set([song.id for song in data.local.music.get_all_songs(cls.game, cls.version)]))
set(
[
song.id
for song in data.local.music.get_all_songs(
cls.game, cls.version
)
]
)
)
if len(all_songs) >= 3: if len(all_songs) >= 3:
daily_songs = random.sample(all_songs, 3) daily_songs = random.sample(all_songs, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -146,9 +133,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "daily_charts", "daily")
cls.game, cls.version, "daily_charts", "daily"
)
return events return events
@classmethod @classmethod
@ -243,9 +228,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
root = Node.void("IIDX22shop") root = Node.void("IIDX22shop")
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -269,9 +252,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
course.replace_int("music_2", request.child_value("music_2")) course.replace_int("music_2", request.child_value("music_2"))
course.replace_int("music_3", request.child_value("music_3")) course.replace_int("music_3", request.child_value("music_3"))
course.replace_bool("valid", request.child_value("valid")) course.replace_bool("valid", request.child_value("valid"))
self.data.local.machine.put_settings( self.data.local.machine.put_settings(machine.arcade, self.game, self.music_version, "shop_course", course)
machine.arcade, self.game, self.music_version, "shop_course", course
)
return root return root
@ -291,9 +272,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -530,16 +509,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
root = Node.void("IIDX22music") root = Node.void("IIDX22music")
attempts = self.get_clear_rates() attempts = self.get_clear_rates()
all_songs = list( all_songs = list(set([song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)]))
set(
[
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
]
)
)
for song in all_songs: for song in all_songs:
clears = [] clears = []
fcs = [] fcs = []
@ -583,16 +553,12 @@ class IIDXPendual(IIDXCourse, IIDXBase):
continue continue
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
# Grab score data for user/rival # Grab score data for user/rival
scoredata = self.make_score_struct( scoredata = self.make_score_struct(
scores, scores,
self.CLEAR_TYPE_SINGLE self.CLEAR_TYPE_SINGLE if cltype == self.GAME_CLTYPE_SINGLE else self.CLEAR_TYPE_DOUBLE,
if cltype == self.GAME_CLTYPE_SINGLE
else self.CLEAR_TYPE_DOUBLE,
rivalid, rivalid,
) )
for s in scoredata: for s in scoredata:
@ -600,10 +566,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
# Grab most played for user/rival # Grab most played for user/rival
most_played = [ most_played = [
play[0] play[0] for play in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)
for play in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
] ]
if len(most_played) < 20: if len(most_played) < 20:
most_played.extend([0] * (20 - len(most_played))) most_played.extend([0] * (20 - len(most_played)))
@ -646,19 +609,13 @@ class IIDXPendual(IIDXCourse, IIDXBase):
key=lambda s: (s[1].points, s[1].timestamp), key=lambda s: (s[1].points, s[1].timestamp),
reverse=True, reverse=True,
) )
all_players = { all_players = {uid: prof for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])}
uid: prof
for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])
}
if not global_scores: if not global_scores:
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -710,9 +667,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
# Shop ranking # Shop ranking
shopdata = Node.void("shopdata") shopdata = Node.void("shopdata")
root.add_child(shopdata) root.add_child(shopdata)
shopdata.set_attribute( shopdata.set_attribute("rank", "-1" if oldindex is None else str(oldindex + 1))
"rank", "-1" if oldindex is None else str(oldindex + 1)
)
# Grab the rank of some other players on this song # Grab the rank of some other players on this song
ranklist = Node.void("ranklist") ranklist = Node.void("ranklist")
@ -736,10 +691,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -887,9 +839,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
if userid is not None: if userid is not None:
# Try to look up previous ghost for user # Try to look up previous ghost for user
my_score = self.data.remote.music.get_score( my_score = self.data.remote.music.get_score(self.game, self.music_version, userid, musicid, chart)
self.game, self.music_version, userid, musicid, chart
)
if my_score is not None: if my_score is not None:
mydata = Node.binary("mydata", my_score.data.get_bytes("ghost")) mydata = Node.binary("mydata", my_score.data.get_bytes("ghost"))
mydata.set_attribute("score", str(my_score.points)) mydata.set_attribute("score", str(my_score.points))
@ -1240,9 +1190,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
used_secret_ids: List[int] = [] used_secret_ids: List[int] = []
for c in secret_courses: for c in secret_courses:
if c["id"] in used_secret_ids: if c["id"] in used_secret_ids:
raise Exception( raise Exception("Cannot have multiple secret courses with the same ID!")
"Cannot have multiple secret courses with the same ID!"
)
elif c["id"] < 0 or c["id"] >= 10: elif c["id"] < 0 or c["id"] >= 10:
raise Exception("Secret course ID is out of bounds!") raise Exception("Secret course ID is out of bounds!")
else: else:
@ -1272,13 +1220,9 @@ class IIDXPendual(IIDXCourse, IIDXBase):
common_timeshift_phase = Node.void("common_timeshift_phase") common_timeshift_phase = Node.void("common_timeshift_phase")
root.add_child(common_timeshift_phase) root.add_child(common_timeshift_phase)
if timeshift_override == 0: if timeshift_override == 0:
common_timeshift_phase.set_attribute( common_timeshift_phase.set_attribute("phase", "1" if (days_since_epoch % 2) == 0 else "2")
"phase", "1" if (days_since_epoch % 2) == 0 else "2"
)
elif timeshift_override == 1: elif timeshift_override == 1:
common_timeshift_phase.set_attribute( common_timeshift_phase.set_attribute("phase", "2" if (days_since_epoch % 2) == 0 else "1")
"phase", "2" if (days_since_epoch % 2) == 0 else "1"
)
elif timeshift_override == 2: elif timeshift_override == 2:
common_timeshift_phase.set_attribute("phase", "1") common_timeshift_phase.set_attribute("phase", "1")
elif timeshift_override == 3: elif timeshift_override == 3:
@ -1306,9 +1250,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
# Ranking details in title screen # Ranking details in title screen
rankingcharts = [] rankingcharts = []
for mid, _plays in self.data.local.music.get_hit_chart( for mid, _plays in self.data.local.music.get_hit_chart(self.game, self.music_version, 20):
self.game, self.music_version, 20
):
rankingcharts.append(mid) rankingcharts.append(mid)
root.add_child(Node.u16_array("monthly_mranking", rankingcharts)) root.add_child(Node.u16_array("monthly_mranking", rankingcharts))
root.add_child(Node.u16_array("total_mranking", rankingcharts)) root.add_child(Node.u16_array("total_mranking", rankingcharts))
@ -1467,9 +1409,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
best_clear_string = clear_map.get(best_clear, "NO PLAY") best_clear_string = clear_map.get(best_clear, "NO PLAY")
now_clear_string = clear_map.get(now_clear, "NO PLAY") now_clear_string = clear_map.get(now_clear, "NO PLAY")
# let's get the song info first # let's get the song info first
song = self.data.local.music.get_song( song = self.data.local.music.get_song(self.game, self.music_version, music_id, self.game_to_db_chart(class_id))
self.game, self.music_version, music_id, self.game_to_db_chart(class_id)
)
notecount = song.data.get("notecount", 0) notecount = song.data.get("notecount", 0)
# Construct the dictionary for the broadcast # Construct the dictionary for the broadcast
card_data = { card_data = {
@ -1578,9 +1518,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
join_shop.set_attribute("join_name", machine.name) join_shop.set_attribute("join_name", machine.name)
# Daily recommendations # Daily recommendations
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "dailies")
self.game, self.version, "dailies"
)
if entry is not None: if entry is not None:
packinfo = Node.void("packinfo") packinfo = Node.void("packinfo")
root.add_child(packinfo) root.add_child(packinfo)
@ -1611,15 +1549,9 @@ class IIDXPendual(IIDXCourse, IIDXBase):
secret.add_child(Node.s64_array("flg2", [-1, -1, -1])) secret.add_child(Node.s64_array("flg2", [-1, -1, -1]))
secret.add_child(Node.s64_array("flg3", [-1, -1, -1])) secret.add_child(Node.s64_array("flg3", [-1, -1, -1]))
else: else:
secret.add_child( secret.add_child(Node.s64_array("flg1", secret_dict.get_int_array("flg1", 3)))
Node.s64_array("flg1", secret_dict.get_int_array("flg1", 3)) secret.add_child(Node.s64_array("flg2", secret_dict.get_int_array("flg2", 3)))
) secret.add_child(Node.s64_array("flg3", secret_dict.get_int_array("flg3", 3)))
secret.add_child(
Node.s64_array("flg2", secret_dict.get_int_array("flg2", 3))
)
secret.add_child(
Node.s64_array("flg3", secret_dict.get_int_array("flg3", 3))
)
# Tran medals and shit # Tran medals and shit
achievements = Node.void("achievements") achievements = Node.void("achievements")
@ -1630,15 +1562,11 @@ class IIDXPendual(IIDXCourse, IIDXBase):
achievements.set_attribute("pack", "0") achievements.set_attribute("pack", "0")
achievements.set_attribute("pack_comp", "0") achievements.set_attribute("pack_comp", "0")
else: else:
daily_played = self.data.local.user.get_achievement( daily_played = self.data.local.user.get_achievement(self.game, self.version, userid, pack_id, "daily")
self.game, self.version, userid, pack_id, "daily"
)
if daily_played is None: if daily_played is None:
daily_played = ValidatedDict() daily_played = ValidatedDict()
achievements.set_attribute("pack", str(daily_played.get_int("pack_flg"))) achievements.set_attribute("pack", str(daily_played.get_int("pack_flg")))
achievements.set_attribute( achievements.set_attribute("pack_comp", str(daily_played.get_int("pack_comp")))
"pack_comp", str(daily_played.get_int("pack_comp"))
)
# Weeklies # Weeklies
achievements.set_attribute("last_weekly", str(profile.get_int("last_weekly"))) achievements.set_attribute("last_weekly", str(profile.get_int("last_weekly")))
@ -1651,9 +1579,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
achievements.set_attribute("rival_crush", str(profile.get_int("rival_crush"))) achievements.set_attribute("rival_crush", str(profile.get_int("rival_crush")))
# Tran medals # Tran medals
achievements.add_child( achievements.add_child(Node.s64_array("trophy", profile.get_int_array("trophy", 10)))
Node.s64_array("trophy", profile.get_int_array("trophy", 10))
)
# User settings # User settings
settings_dict = profile.get_dict("settings") settings_dict = profile.get_dict("settings")
@ -1699,9 +1625,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
) )
), ),
) )
rankings = self.data.local.user.get_achievements( rankings = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for rank in rankings: for rank in rankings:
if rank.type == self.DAN_RANKING_SINGLE: if rank.type == self.DAN_RANKING_SINGLE:
grade.add_child( grade.add_child(
@ -1739,9 +1663,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
[ [
int(rank.id / 6), # course ID int(rank.id / 6), # course ID
rank.id % 6, # course chart rank.id % 6, # course chart
self.db_to_game_status( self.db_to_game_status(rank.data.get_int("clear_status")), # course clear status
rank.data.get_int("clear_status")
), # course clear status
rank.data.get_int("pgnum"), # flashing great count rank.data.get_int("pgnum"), # flashing great count
rank.data.get_int("gnum"), # great count rank.data.get_int("gnum"), # great count
], ],
@ -1758,9 +1680,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
[ [
int(rank.id / 6), # course ID int(rank.id / 6), # course ID
rank.id % 6, # course chart rank.id % 6, # course chart
self.db_to_game_status( self.db_to_game_status(rank.data.get_int("clear_status")), # course clear status
rank.data.get_int("clear_status")
), # course clear status
rank.data.get_int("pgnum"), # flashing great count rank.data.get_int("pgnum"), # flashing great count
rank.data.get_int("gnum"), # great count rank.data.get_int("gnum"), # great count
], ],
@ -1776,9 +1696,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
detail.set_attribute("course_id", str(rank.id)) detail.set_attribute("course_id", str(rank.id))
detail.set_attribute("n_point", str(rank.data.get_int("normal_points"))) detail.set_attribute("n_point", str(rank.data.get_int("normal_points")))
detail.set_attribute("h_point", str(rank.data.get_int("hyper_points"))) detail.set_attribute("h_point", str(rank.data.get_int("hyper_points")))
detail.set_attribute( detail.set_attribute("a_point", str(rank.data.get_int("another_points")))
"a_point", str(rank.data.get_int("another_points"))
)
# Qpro data # Qpro data
qpro_dict = profile.get_dict("qpro") qpro_dict = profile.get_dict("qpro")
@ -1880,9 +1798,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
step.add_child( step.add_child(
Node.binary( Node.binary(
"album", "album",
step_dict.get_bytes( step_dict.get_bytes("album", b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
"album", b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
),
) )
) )
@ -1962,9 +1878,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
present_time_sandglass.set_attribute("item_num", "99") present_time_sandglass.set_attribute("item_num", "99")
# TODO: Same as above. # TODO: Same as above.
pointsdict = profile.get_dict( pointsdict = profile.get_dict("point_events") # used for summer, dcat, and pyramid
"point_events"
) # used for summer, dcat, and pyramid
# destiny event # destiny event
dcat = Node.void("destiny_catharsis") dcat = Node.void("destiny_catharsis")
root.add_child(dcat) root.add_child(dcat)
@ -1980,46 +1894,20 @@ class IIDXPendual(IIDXCourse, IIDXBase):
cdive = Node.void("chrono_diver") cdive = Node.void("chrono_diver")
root.add_child(cdive) root.add_child(cdive)
cdive.set_attribute("play_count", str(diverdict.get_int("play_count", 0))) cdive.set_attribute("play_count", str(diverdict.get_int("play_count", 0)))
cdive.set_attribute( cdive.set_attribute("present_unlock", str(diverdict.get_int("present_unlock", 0)))
"present_unlock", str(diverdict.get_int("present_unlock", 0))
)
cdive.set_attribute("future_unlock", str(diverdict.get_int("future_unlock", 0))) cdive.set_attribute("future_unlock", str(diverdict.get_int("future_unlock", 0)))
cdive.set_attribute( cdive.set_attribute("success_count_0_n", str(diverdict.get_int("success_count_0_n", 0)))
"success_count_0_n", str(diverdict.get_int("success_count_0_n", 0)) cdive.set_attribute("success_count_0_h", str(diverdict.get_int("success_count_0_h", 0)))
) cdive.set_attribute("success_count_0_a", str(diverdict.get_int("success_count_0_a", 0)))
cdive.set_attribute( cdive.set_attribute("success_count_1_n", str(diverdict.get_int("success_count_1_n", 0)))
"success_count_0_h", str(diverdict.get_int("success_count_0_h", 0)) cdive.set_attribute("success_count_1_h", str(diverdict.get_int("success_count_1_h", 0)))
) cdive.set_attribute("success_count_1_a", str(diverdict.get_int("success_count_1_a", 0)))
cdive.set_attribute( cdive.set_attribute("success_count_2_n", str(diverdict.get_int("success_count_2_n", 0)))
"success_count_0_a", str(diverdict.get_int("success_count_0_a", 0)) cdive.set_attribute("success_count_2_h", str(diverdict.get_int("success_count_2_h", 0)))
) cdive.set_attribute("success_count_2_a", str(diverdict.get_int("success_count_2_a", 0)))
cdive.set_attribute( cdive.set_attribute("success_count_3_n", str(diverdict.get_int("success_count_3_n", 0)))
"success_count_1_n", str(diverdict.get_int("success_count_1_n", 0)) cdive.set_attribute("success_count_3_h", str(diverdict.get_int("success_count_3_h", 0)))
) cdive.set_attribute("success_count_3_a", str(diverdict.get_int("success_count_3_a", 0)))
cdive.set_attribute(
"success_count_1_h", str(diverdict.get_int("success_count_1_h", 0))
)
cdive.set_attribute(
"success_count_1_a", str(diverdict.get_int("success_count_1_a", 0))
)
cdive.set_attribute(
"success_count_2_n", str(diverdict.get_int("success_count_2_n", 0))
)
cdive.set_attribute(
"success_count_2_h", str(diverdict.get_int("success_count_2_h", 0))
)
cdive.set_attribute(
"success_count_2_a", str(diverdict.get_int("success_count_2_a", 0))
)
cdive.set_attribute(
"success_count_3_n", str(diverdict.get_int("success_count_3_n", 0))
)
cdive.set_attribute(
"success_count_3_h", str(diverdict.get_int("success_count_3_h", 0))
)
cdive.set_attribute(
"success_count_3_a", str(diverdict.get_int("success_count_3_a", 0))
)
cdive.set_attribute("story_list", str(diverdict.get_int("story_list", 0))) cdive.set_attribute("story_list", str(diverdict.get_int("story_list", 0)))
# reflec beat collaboration # reflec beat collaboration
@ -2048,9 +1936,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -2126,15 +2012,9 @@ class IIDXPendual(IIDXCourse, IIDXBase):
# Basic achievements # Basic achievements
achievements = request.child("achievements") achievements = request.child("achievements")
if achievements is not None: if achievements is not None:
newprofile.replace_int( newprofile.replace_int("visit_flg", int(achievements.attribute("visit_flg")))
"visit_flg", int(achievements.attribute("visit_flg")) newprofile.replace_int("last_weekly", int(achievements.attribute("last_weekly")))
) newprofile.replace_int("weekly_num", int(achievements.attribute("weekly_num")))
newprofile.replace_int(
"last_weekly", int(achievements.attribute("last_weekly"))
)
newprofile.replace_int(
"weekly_num", int(achievements.attribute("weekly_num"))
)
pack_id = int(achievements.attribute("pack_id")) pack_id = int(achievements.attribute("pack_id"))
if pack_id > 0: if pack_id > 0:
@ -2158,9 +2038,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
# Deller saving # Deller saving
deller = request.child("deller") deller = request.child("deller")
if deller is not None: if deller is not None:
newprofile.replace_int( newprofile.replace_int("deller", newprofile.get_int("deller") + int(deller.attribute("deller")))
"deller", newprofile.get_int("deller") + int(deller.attribute("deller"))
)
# Secret course expert point saving # Secret course expert point saving
expert_point = request.child("expert_point") expert_point = request.child("expert_point")
@ -2212,17 +2090,13 @@ class IIDXPendual(IIDXCourse, IIDXBase):
for i in range(self.FAVORITE_LIST_LENGTH): for i in range(self.FAVORITE_LIST_LENGTH):
singles.append( singles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", single_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", single_music_bin[(i * 4) : ((i + 1) * 4)]
)[0],
"chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[0], "chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[0],
} }
) )
doubles.append( doubles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", double_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", double_music_bin[(i * 4) : ((i + 1) * 4)]
)[0],
"chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[0], "chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[0],
} }
) )
@ -2272,61 +2146,29 @@ class IIDXPendual(IIDXCourse, IIDXBase):
diverdict = newprofile.get_dict("diver_dict") diverdict = newprofile.get_dict("diver_dict")
diverreq = request.child("chrono_diver") diverreq = request.child("chrono_diver")
if diverreq is not None: if diverreq is not None:
diverdict.replace_int( diverdict.replace_int("future_unlock", int(diverreq.attribute("future_unlock")))
"future_unlock", int(diverreq.attribute("future_unlock"))
)
diverdict.replace_int("play_count", int(diverreq.attribute("play_count"))) diverdict.replace_int("play_count", int(diverreq.attribute("play_count")))
diverdict.replace_int( diverdict.replace_int("present_unlock", int(diverreq.attribute("present_unlock")))
"present_unlock", int(diverreq.attribute("present_unlock"))
)
diverdict.replace_int("story_list", int(diverreq.attribute("story_list"))) diverdict.replace_int("story_list", int(diverreq.attribute("story_list")))
diverdict.replace_int( diverdict.replace_int("success_count_0_a", int(diverreq.attribute("success_count_0_a")))
"success_count_0_a", int(diverreq.attribute("success_count_0_a")) diverdict.replace_int("success_count_0_h", int(diverreq.attribute("success_count_0_h")))
) diverdict.replace_int("success_count_0_n", int(diverreq.attribute("success_count_0_n")))
diverdict.replace_int( diverdict.replace_int("success_count_1_a", int(diverreq.attribute("success_count_1_a")))
"success_count_0_h", int(diverreq.attribute("success_count_0_h")) diverdict.replace_int("success_count_1_h", int(diverreq.attribute("success_count_1_h")))
) diverdict.replace_int("success_count_1_n", int(diverreq.attribute("success_count_1_n")))
diverdict.replace_int( diverdict.replace_int("success_count_2_a", int(diverreq.attribute("success_count_2_a")))
"success_count_0_n", int(diverreq.attribute("success_count_0_n")) diverdict.replace_int("success_count_2_h", int(diverreq.attribute("success_count_2_h")))
) diverdict.replace_int("success_count_2_n", int(diverreq.attribute("success_count_2_n")))
diverdict.replace_int( diverdict.replace_int("success_count_3_a", int(diverreq.attribute("success_count_3_a")))
"success_count_1_a", int(diverreq.attribute("success_count_1_a")) diverdict.replace_int("success_count_3_h", int(diverreq.attribute("success_count_3_h")))
) diverdict.replace_int("success_count_3_n", int(diverreq.attribute("success_count_3_n")))
diverdict.replace_int(
"success_count_1_h", int(diverreq.attribute("success_count_1_h"))
)
diverdict.replace_int(
"success_count_1_n", int(diverreq.attribute("success_count_1_n"))
)
diverdict.replace_int(
"success_count_2_a", int(diverreq.attribute("success_count_2_a"))
)
diverdict.replace_int(
"success_count_2_h", int(diverreq.attribute("success_count_2_h"))
)
diverdict.replace_int(
"success_count_2_n", int(diverreq.attribute("success_count_2_n"))
)
diverdict.replace_int(
"success_count_3_a", int(diverreq.attribute("success_count_3_a"))
)
diverdict.replace_int(
"success_count_3_h", int(diverreq.attribute("success_count_3_h"))
)
diverdict.replace_int(
"success_count_3_n", int(diverreq.attribute("success_count_3_n"))
)
newprofile.replace_dict("diver_dict", diverdict) newprofile.replace_dict("diver_dict", diverdict)
reflecdict = newprofile.get_dict("reflec_collab") reflecdict = newprofile.get_dict("reflec_collab")
reflecreq = request.child("reflec_collabo") reflecreq = request.child("reflec_collabo")
if reflecreq is not None: if reflecreq is not None:
reflecdict.replace_int( reflecdict.replace_int("phase1_item", int(reflecreq.attribute("phase1_iidx_item")))
"phase1_item", int(reflecreq.attribute("phase1_iidx_item")) reflecdict.replace_int("phase2_item", int(reflecreq.attribute("phase2_iidx_item")))
)
reflecdict.replace_int(
"phase2_item", int(reflecreq.attribute("phase2_iidx_item"))
)
newprofile.replace_dict("reflec_collab", reflecdict) newprofile.replace_dict("reflec_collab", reflecdict)
# boss event pendual tailsman points # boss event pendual tailsman points
@ -2342,42 +2184,18 @@ class IIDXPendual(IIDXCourse, IIDXBase):
chorddict = newprofile.get_dict("chord_dict") chorddict = newprofile.get_dict("chord_dict")
chordreq = request.child("qpronicle_chord") chordreq = request.child("qpronicle_chord")
if chordreq is not None: if chordreq is not None:
chorddict.replace_int( chorddict.replace_int("is_first_select_map", int(chordreq.attribute("is_first_select_map")))
"is_first_select_map", int(chordreq.attribute("is_first_select_map")) chorddict.replace_int("is_use_login_bonus", int(chordreq.attribute("is_use_login_bonus")))
) chorddict.replace_int("last_select_map", int(chordreq.attribute("last_select_map")))
chorddict.replace_int( chorddict.replace_int("patona_leader", int(chordreq.attribute("patona_leader")))
"is_use_login_bonus", int(chordreq.attribute("is_use_login_bonus")) chorddict.replace_int("patona_sub_1", int(chordreq.attribute("patona_sub_1")))
) chorddict.replace_int("patona_sub_2", int(chordreq.attribute("patona_sub_2")))
chorddict.replace_int( chorddict.replace_int("rare_enemy_damage1", int(chordreq.attribute("rare_enemy_damage1")))
"last_select_map", int(chordreq.attribute("last_select_map")) chorddict.replace_int("rare_enemy_damage2", int(chordreq.attribute("rare_enemy_damage2")))
) chorddict.replace_int("rare_enemy_damage3", int(chordreq.attribute("rare_enemy_damage3")))
chorddict.replace_int( chorddict.replace_int("rare_enemy_damage4", int(chordreq.attribute("rare_enemy_damage4")))
"patona_leader", int(chordreq.attribute("patona_leader")) chorddict.replace_int("rare_enemy_damage5", int(chordreq.attribute("rare_enemy_damage5")))
) chorddict.replace_int("story_view_list", int(chordreq.attribute("story_view_list")))
chorddict.replace_int(
"patona_sub_1", int(chordreq.attribute("patona_sub_1"))
)
chorddict.replace_int(
"patona_sub_2", int(chordreq.attribute("patona_sub_2"))
)
chorddict.replace_int(
"rare_enemy_damage1", int(chordreq.attribute("rare_enemy_damage1"))
)
chorddict.replace_int(
"rare_enemy_damage2", int(chordreq.attribute("rare_enemy_damage2"))
)
chorddict.replace_int(
"rare_enemy_damage3", int(chordreq.attribute("rare_enemy_damage3"))
)
chorddict.replace_int(
"rare_enemy_damage4", int(chordreq.attribute("rare_enemy_damage4"))
)
chorddict.replace_int(
"rare_enemy_damage5", int(chordreq.attribute("rare_enemy_damage5"))
)
chorddict.replace_int(
"story_view_list", int(chordreq.attribute("story_view_list"))
)
newprofile.replace_dict("chord_dict", chorddict) newprofile.replace_dict("chord_dict", chorddict)
# Keep track of play statistics across all mixes # Keep track of play statistics across all mixes

View File

@ -107,28 +107,15 @@ class IIDXRootage(IIDXCourse, IIDXBase):
return IIDXCannonBallers(self.data, self.config, self.model) return IIDXCannonBallers(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert dailies into the DB. Insert dailies into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "daily_charts", "daily"):
cls.game, cls.version, "daily_charts", "daily"
):
# Generate a new list of three dailies. # Generate a new list of three dailies.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = list( all_songs = list(set([song.id for song in data.local.music.get_all_songs(cls.game, cls.version)]))
set(
[
song.id
for song in data.local.music.get_all_songs(
cls.game, cls.version
)
]
)
)
if len(all_songs) >= 3: if len(all_songs) >= 3:
daily_songs = random.sample(all_songs, 3) daily_songs = random.sample(all_songs, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -152,9 +139,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "daily_charts", "daily")
cls.game, cls.version, "daily_charts", "daily"
)
return events return events
@classmethod @classmethod
@ -390,9 +375,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
root = Node.void("IIDX26shop") root = Node.void("IIDX26shop")
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -415,9 +398,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
course.replace_int("music_2", request.child_value("music_2")) course.replace_int("music_2", request.child_value("music_2"))
course.replace_int("music_3", request.child_value("music_3")) course.replace_int("music_3", request.child_value("music_3"))
course.replace_bool("valid", request.child_value("valid")) course.replace_bool("valid", request.child_value("valid"))
self.data.local.machine.put_settings( self.data.local.machine.put_settings(machine.arcade, self.game, self.music_version, "shop_course", course)
machine.arcade, self.game, self.music_version, "shop_course", course
)
return Node.void("IIDX26shop") return Node.void("IIDX26shop")
@ -429,16 +410,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
root = Node.void("IIDX26music") root = Node.void("IIDX26music")
attempts = self.get_clear_rates() attempts = self.get_clear_rates()
all_songs = list( all_songs = list(set([song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)]))
set(
[
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
]
)
)
for song in all_songs: for song in all_songs:
clears = [] clears = []
fcs = [] fcs = []
@ -482,16 +454,12 @@ class IIDXRootage(IIDXCourse, IIDXBase):
continue continue
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
# Grab score data for user/rival # Grab score data for user/rival
scoredata = self.make_score_struct( scoredata = self.make_score_struct(
scores, scores,
self.CLEAR_TYPE_SINGLE self.CLEAR_TYPE_SINGLE if cltype == self.GAME_CLTYPE_SINGLE else self.CLEAR_TYPE_DOUBLE,
if cltype == self.GAME_CLTYPE_SINGLE
else self.CLEAR_TYPE_DOUBLE,
rivalid, rivalid,
) )
for s in scoredata: for s in scoredata:
@ -499,10 +467,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
# Grab most played for user/rival # Grab most played for user/rival
most_played = [ most_played = [
play[0] play[0] for play in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)
for play in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
] ]
if len(most_played) < 20: if len(most_played) < 20:
most_played.extend([0] * (20 - len(most_played))) most_played.extend([0] * (20 - len(most_played)))
@ -529,9 +494,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
if userid is not None: if userid is not None:
# Try to look up previous ghost for user # Try to look up previous ghost for user
my_score = self.data.remote.music.get_score( my_score = self.data.remote.music.get_score(self.game, self.music_version, userid, musicid, chart)
self.game, self.music_version, userid, musicid, chart
)
if my_score is not None: if my_score is not None:
mydata = Node.binary("mydata", my_score.data.get_bytes("ghost")) mydata = Node.binary("mydata", my_score.data.get_bytes("ghost"))
mydata.set_attribute("score", str(my_score.points)) mydata.set_attribute("score", str(my_score.points))
@ -622,18 +585,11 @@ class IIDXRootage(IIDXCourse, IIDXBase):
key=lambda s: (s[1].points, s[1].timestamp), key=lambda s: (s[1].points, s[1].timestamp),
reverse=True, reverse=True,
) )
all_players = { all_players = {uid: prof for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])}
uid: prof
for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])
}
shop_id = ID.parse_machine_id(request.attribute("location_id")) shop_id = ID.parse_machine_id(request.attribute("location_id"))
if not global_scores: if not global_scores:
all_scores = [ all_scores = [score for score in all_scores if (score[0] == userid or score[1].location == shop_id)]
score
for score in all_scores
if (score[0] == userid or score[1].location == shop_id)
]
# Find our actual index # Find our actual index
oldindex = None oldindex = None
@ -684,9 +640,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
# Shop ranking # Shop ranking
shopdata = Node.void("shopdata") shopdata = Node.void("shopdata")
root.add_child(shopdata) root.add_child(shopdata)
shopdata.set_attribute( shopdata.set_attribute("rank", "-1" if oldindex is None else str(oldindex + 1))
"rank", "-1" if oldindex is None else str(oldindex + 1)
)
# Grab the rank of some other players on this song # Grab the rank of some other players on this song
ranklist = Node.void("ranklist") ranklist = Node.void("ranklist")
@ -707,11 +661,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
all_players[uid] = prof all_players[uid] = prof
if not global_scores: if not global_scores:
all_scores = [ all_scores = [score for score in all_scores if (score[0] == userid or score[1].location == shop_id)]
score
for score in all_scores
if (score[0] == userid or score[1].location == shop_id)
]
# Find our actual index # Find our actual index
ourindex = None ourindex = None
@ -844,13 +794,9 @@ class IIDXRootage(IIDXCourse, IIDXBase):
} }
for item in request.children: for item in request.children:
if item.name == "music_list": if item.name == "music_list":
music_list[int(item.child_value("index"))] = int( music_list[int(item.child_value("index"))] = int(item.child_value("total_notes"))
item.child_value("total_notes")
)
if item.name == "cpu_list": if item.name == "cpu_list":
cpu_list[int(item.child_value("index"))] = int( cpu_list[int(item.child_value("index"))] = int(item.child_value("grade_id"))
item.child_value("grade_id")
)
for index in range(4): for index in range(4):
cpu_score_list = Node.void("cpu_score_list") cpu_score_list = Node.void("cpu_score_list")
cpu_score_list.add_child(Node.s32("index", index)) cpu_score_list.add_child(Node.s32("index", index))
@ -991,9 +937,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
root.set_attribute("pflg", "0") root.set_attribute("pflg", "0")
return root return root
def handle_IIDX26pc_shopregister_request( def handle_IIDX26pc_shopregister_request(self, request: Node) -> Node: # Not used anymore????
self, request: Node
) -> Node: # Not used anymore????
root = Node.void("IIDX26pc") root = Node.void("IIDX26pc")
return root return root
@ -1115,9 +1059,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
best_clear_string = clear_map.get(best_clear, "NO PLAY") best_clear_string = clear_map.get(best_clear, "NO PLAY")
now_clear_string = clear_map.get(now_clear, "NO PLAY") now_clear_string = clear_map.get(now_clear, "NO PLAY")
# let's get the song info first # let's get the song info first
song = self.data.local.music.get_song( song = self.data.local.music.get_song(self.game, self.music_version, music_id, self.game_to_db_chart(class_id))
self.game, self.music_version, music_id, self.game_to_db_chart(class_id)
)
notecount = song.data.get("notecount", 0) notecount = song.data.get("notecount", 0)
# Construct the dictionary for the broadcast # Construct the dictionary for the broadcast
card_data = { card_data = {
@ -1239,25 +1181,15 @@ class IIDXRootage(IIDXCourse, IIDXBase):
root.add_child(arena_cpu_define) root.add_child(arena_cpu_define)
arena_cpu_define.add_child(Node.s32("play_style", playstyle)) arena_cpu_define.add_child(Node.s32("play_style", playstyle))
arena_cpu_define.add_child(Node.s32("arena_class", arena_class)) arena_cpu_define.add_child(Node.s32("arena_class", arena_class))
arena_cpu_define.add_child( arena_cpu_define.add_child(Node.s32("grade_id", cpu_grades[arena_class]))
Node.s32("grade_id", cpu_grades[arena_class]) arena_cpu_define.add_child(Node.s32("low_music_difficult", cpu_low_diff[arena_class]))
) arena_cpu_define.add_child(Node.s32("high_music_difficult", cpu_high_diff[arena_class]))
arena_cpu_define.add_child( arena_cpu_define.add_child(Node.bool("is_leggendaria", arena_class >= 13))
Node.s32("low_music_difficult", cpu_low_diff[arena_class])
)
arena_cpu_define.add_child(
Node.s32("high_music_difficult", cpu_high_diff[arena_class])
)
arena_cpu_define.add_child(
Node.bool("is_leggendaria", arena_class >= 13)
)
for matching_class in range(21): for matching_class in range(21):
matching_class_range = Node.void("matching_class_range") matching_class_range = Node.void("matching_class_range")
root.add_child(matching_class_range) root.add_child(matching_class_range)
matching_class_range.add_child(Node.s32("play_style", playstyle)) matching_class_range.add_child(Node.s32("play_style", playstyle))
matching_class_range.add_child( matching_class_range.add_child(Node.s32("matching_class", matching_class))
Node.s32("matching_class", matching_class)
)
matching_class_range.add_child(Node.s32("low_arena_class", 1)) matching_class_range.add_child(Node.s32("low_arena_class", 1))
matching_class_range.add_child(Node.s32("high_arena_class", 20)) matching_class_range.add_child(Node.s32("high_arena_class", 20))
return root return root
@ -1330,12 +1262,8 @@ class IIDXRootage(IIDXCourse, IIDXBase):
pcdata.set_attribute("d_camera_layout", str(profile.get_int("d_camera_layout"))) pcdata.set_attribute("d_camera_layout", str(profile.get_int("d_camera_layout")))
pcdata.set_attribute("s_ghost_score", str(profile.get_int("s_ghost_score"))) pcdata.set_attribute("s_ghost_score", str(profile.get_int("s_ghost_score")))
pcdata.set_attribute("d_ghost_score", str(profile.get_int("d_ghost_score"))) pcdata.set_attribute("d_ghost_score", str(profile.get_int("d_ghost_score")))
pcdata.set_attribute( pcdata.set_attribute("s_tsujigiri_disp", str(profile.get_int("s_tsujigiri_disp")))
"s_tsujigiri_disp", str(profile.get_int("s_tsujigiri_disp")) pcdata.set_attribute("d_tsujigiri_disp", str(profile.get_int("d_tsujigiri_disp")))
)
pcdata.set_attribute(
"d_tsujigiri_disp", str(profile.get_int("d_tsujigiri_disp"))
)
# KAC stuff # KAC stuff
# kac_entry_info = Node.void('kac_entry_info') # kac_entry_info = Node.void('kac_entry_info')
@ -1363,15 +1291,9 @@ class IIDXRootage(IIDXCourse, IIDXBase):
secret.add_child(Node.s64_array("flg2", [-1, -1, -1])) secret.add_child(Node.s64_array("flg2", [-1, -1, -1]))
secret.add_child(Node.s64_array("flg3", [-1, -1, -1])) secret.add_child(Node.s64_array("flg3", [-1, -1, -1]))
else: else:
secret.add_child( secret.add_child(Node.s64_array("flg1", secret_dict.get_int_array("flg1", 3)))
Node.s64_array("flg1", secret_dict.get_int_array("flg1", 3)) secret.add_child(Node.s64_array("flg2", secret_dict.get_int_array("flg2", 3)))
) secret.add_child(Node.s64_array("flg3", secret_dict.get_int_array("flg3", 3)))
secret.add_child(
Node.s64_array("flg2", secret_dict.get_int_array("flg2", 3))
)
secret.add_child(
Node.s64_array("flg3", secret_dict.get_int_array("flg3", 3))
)
# Favorites # Favorites
for folder in ["favorite1", "favorite2", "favorite3"]: for folder in ["favorite1", "favorite2", "favorite3"]:
@ -1420,21 +1342,11 @@ class IIDXRootage(IIDXCourse, IIDXBase):
qpro_secrete_dict = profile.get_dict("qpro_secret") qpro_secrete_dict = profile.get_dict("qpro_secret")
qpro_secret = Node.void("qpro_secret") qpro_secret = Node.void("qpro_secret")
root.add_child(qpro_secret) root.add_child(qpro_secret)
qpro_secret.add_child( qpro_secret.add_child(Node.s64_array("head", qpro_secrete_dict.get_int_array("head", 5)))
Node.s64_array("head", qpro_secrete_dict.get_int_array("head", 5)) qpro_secret.add_child(Node.s64_array("hair", qpro_secrete_dict.get_int_array("hair", 5)))
) qpro_secret.add_child(Node.s64_array("face", qpro_secrete_dict.get_int_array("face", 5)))
qpro_secret.add_child( qpro_secret.add_child(Node.s64_array("body", qpro_secrete_dict.get_int_array("body", 5)))
Node.s64_array("hair", qpro_secrete_dict.get_int_array("hair", 5)) qpro_secret.add_child(Node.s64_array("hand", qpro_secrete_dict.get_int_array("hand", 5)))
)
qpro_secret.add_child(
Node.s64_array("face", qpro_secrete_dict.get_int_array("face", 5))
)
qpro_secret.add_child(
Node.s64_array("body", qpro_secrete_dict.get_int_array("body", 5))
)
qpro_secret.add_child(
Node.s64_array("hand", qpro_secrete_dict.get_int_array("hand", 5))
)
# DAN rankings # DAN rankings
grade = Node.void("grade") grade = Node.void("grade")
@ -1457,9 +1369,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
) )
), ),
) )
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for rank in achievements: for rank in achievements:
if rank.type == self.DAN_RANKING_SINGLE: if rank.type == self.DAN_RANKING_SINGLE:
grade.add_child( grade.add_child(
@ -1604,12 +1514,8 @@ class IIDXRootage(IIDXCourse, IIDXBase):
dj_rank_node = Node.void("dj_rank") dj_rank_node = Node.void("dj_rank")
root.add_child(dj_rank_node) root.add_child(dj_rank_node)
dj_rank_node.set_attribute("style", str(dj_rank.id)) dj_rank_node.set_attribute("style", str(dj_rank.id))
dj_rank_node.add_child( dj_rank_node.add_child(Node.s32_array("rank", dj_rank.data.get_int_array("rank", 15)))
Node.s32_array("rank", dj_rank.data.get_int_array("rank", 15)) dj_rank_node.add_child(Node.s32_array("point", dj_rank.data.get_int_array("point", 15)))
)
dj_rank_node.add_child(
Node.s32_array("point", dj_rank.data.get_int_array("point", 15))
)
dj_rank_ranking_node = Node.void("dj_rank_ranking") dj_rank_ranking_node = Node.void("dj_rank_ranking")
root.add_child(dj_rank_ranking_node) root.add_child(dj_rank_ranking_node)
@ -1655,25 +1561,13 @@ class IIDXRootage(IIDXCourse, IIDXBase):
event1_dict = profile.get_dict("event1") event1_dict = profile.get_dict("event1")
event1 = Node.void("event1") event1 = Node.void("event1")
root.add_child(event1) root.add_child(event1)
event1.set_attribute( event1.set_attribute("event_play_num", str(event1_dict.get_int("event_play_num")))
"event_play_num", str(event1_dict.get_int("event_play_num"))
)
event1.set_attribute("fragment_num", str(event1_dict.get_int("fragment_num"))) event1.set_attribute("fragment_num", str(event1_dict.get_int("fragment_num")))
event1.set_attribute( event1.set_attribute("last_select_map_id", str(event1_dict.get_int("last_select_map")))
"last_select_map_id", str(event1_dict.get_int("last_select_map")) event1.set_attribute("read_tips_list", str(event1_dict.get_int("read_tips_list")))
) event1.set_attribute("continuous_correct", str(event1_dict.get_int("continuous_correct")))
event1.set_attribute( event1.set_attribute("bookshelf_release_num", str(event1_dict.get_int("bookshelf_release_num")))
"read_tips_list", str(event1_dict.get_int("read_tips_list")) event1.add_child(Node.binary("quiz_control_list", event1_dict.get_bytes("quiz_control_list")))
)
event1.set_attribute(
"continuous_correct", str(event1_dict.get_int("continuous_correct"))
)
event1.set_attribute(
"bookshelf_release_num", str(event1_dict.get_int("bookshelf_release_num"))
)
event1.add_child(
Node.binary("quiz_control_list", event1_dict.get_bytes("quiz_control_list"))
)
for map_data in achievements: for map_data in achievements:
if map_data.type != "map_data": if map_data.type != "map_data":
continue continue
@ -1681,9 +1575,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
map_data_node = Node.void("map_data") map_data_node = Node.void("map_data")
event1.add_child(map_data_node) event1.add_child(map_data_node)
map_data_node.set_attribute("map_id", str(map_data.id)) map_data_node.set_attribute("map_id", str(map_data.id))
map_data_node.set_attribute( map_data_node.set_attribute("play_num", str(map_data.data.get_int("play_num")))
"play_num", str(map_data.data.get_int("play_num"))
)
map_data_node.set_attribute( map_data_node.set_attribute(
"last_select_route_id", "last_select_route_id",
str(map_data.data.get_int("last_select_route_id")), str(map_data.data.get_int("last_select_route_id")),
@ -1692,14 +1584,8 @@ class IIDXRootage(IIDXCourse, IIDXBase):
"bookshelf_release_num", "bookshelf_release_num",
str(map_data.data.get_int("bookshelf_release_num")), str(map_data.data.get_int("bookshelf_release_num")),
) )
map_data_node.add_child( map_data_node.add_child(Node.bool("is_clear", map_data.data.get_bool("is_clear")))
Node.bool("is_clear", map_data.data.get_bool("is_clear")) map_data_node.add_child(Node.binary("map_route_damage", map_data.data.get_bytes("map_route_damage")))
)
map_data_node.add_child(
Node.binary(
"map_route_damage", map_data.data.get_bytes("map_route_damage")
)
)
# DELABITY LABORATORY event # DELABITY LABORATORY event
event2_dict = profile.get_dict("event2") event2_dict = profile.get_dict("event2")
@ -1707,27 +1593,13 @@ class IIDXRootage(IIDXCourse, IIDXBase):
root.add_child(event2) root.add_child(event2)
event2.set_attribute("play_num", str(event2_dict.get_int("play_num"))) event2.set_attribute("play_num", str(event2_dict.get_int("play_num")))
event2.set_attribute("delabity", str(event2_dict.get_int("delabity"))) event2.set_attribute("delabity", str(event2_dict.get_int("delabity")))
event2.set_attribute( event2.set_attribute("floor_0_last_area", str(event2_dict.get_int("floor_0_last_area")))
"floor_0_last_area", str(event2_dict.get_int("floor_0_last_area")) event2.set_attribute("floor_1_last_area", str(event2_dict.get_int("floor_1_last_area")))
) event2.set_attribute("floor_2_last_area", str(event2_dict.get_int("floor_2_last_area")))
event2.set_attribute( event2.set_attribute("floor_3_last_area", str(event2_dict.get_int("floor_3_last_area")))
"floor_1_last_area", str(event2_dict.get_int("floor_1_last_area")) event2.set_attribute("floor_4_last_area", str(event2_dict.get_int("floor_4_last_area")))
) event2.set_attribute("floor_clear_flg_list", str(event2_dict.get_int("floor_clear_flg_list")))
event2.set_attribute( event2.set_attribute("last_select_floor", str(event2_dict.get_int("last_select_floor")))
"floor_2_last_area", str(event2_dict.get_int("floor_2_last_area"))
)
event2.set_attribute(
"floor_3_last_area", str(event2_dict.get_int("floor_3_last_area"))
)
event2.set_attribute(
"floor_4_last_area", str(event2_dict.get_int("floor_4_last_area"))
)
event2.set_attribute(
"floor_clear_flg_list", str(event2_dict.get_int("floor_clear_flg_list"))
)
event2.set_attribute(
"last_select_floor", str(event2_dict.get_int("last_select_floor"))
)
event2.set_attribute("tips_list", str(event2_dict.get_int("tips_list"))) event2.set_attribute("tips_list", str(event2_dict.get_int("tips_list")))
areas = self.data.local.user.get_achievements(self.game, self.version, userid) areas = self.data.local.user.get_achievements(self.game, self.version, userid)
@ -1738,45 +1610,25 @@ class IIDXRootage(IIDXCourse, IIDXBase):
event2.add_child(area_data) event2.add_child(area_data)
area_data.set_attribute("area_id", str(area.id)) area_data.set_attribute("area_id", str(area.id))
area_data.set_attribute("floor_id", str(area.data.get_int("floor_id"))) area_data.set_attribute("floor_id", str(area.data.get_int("floor_id")))
area_data.set_attribute( area_data.set_attribute("last_select_note", str(area.data.get_int("last_select_note")))
"last_select_note", str(area.data.get_int("last_select_note")) area_data.set_attribute("normal_play_num", str(area.data.get_int("normal_play_num")))
) area_data.set_attribute("hyper_play_num", str(area.data.get_int("hyper_play_num")))
area_data.set_attribute( area_data.set_attribute("another_play_num", str(area.data.get_int("another_play_num")))
"normal_play_num", str(area.data.get_int("normal_play_num")) area_data.set_attribute("area_clear_flg_list", str(area.data.get_int("area_clear_flg_list")))
) area_data.set_attribute("normal_grade_point", str(area.data.get_int("normal_grade_point")))
area_data.set_attribute( area_data.set_attribute("hyper_grade_point", str(area.data.get_int("hyper_grade_point")))
"hyper_play_num", str(area.data.get_int("hyper_play_num")) area_data.set_attribute("another_grade_point", str(area.data.get_int("another_grade_point")))
)
area_data.set_attribute(
"another_play_num", str(area.data.get_int("another_play_num"))
)
area_data.set_attribute(
"area_clear_flg_list", str(area.data.get_int("area_clear_flg_list"))
)
area_data.set_attribute(
"normal_grade_point", str(area.data.get_int("normal_grade_point"))
)
area_data.set_attribute(
"hyper_grade_point", str(area.data.get_int("hyper_grade_point"))
)
area_data.set_attribute(
"another_grade_point", str(area.data.get_int("another_grade_point"))
)
tonyutsu = Node.void("tonyutsu") tonyutsu = Node.void("tonyutsu")
tonyutsu_dict = profile.get_dict("tonyutsu") tonyutsu_dict = profile.get_dict("tonyutsu")
tonyutsu.set_attribute( tonyutsu.set_attribute("platinum_pass", str(tonyutsu_dict.get_int("platiunum_pass")))
"platinum_pass", str(tonyutsu_dict.get_int("platiunum_pass"))
)
tonyutsu.set_attribute("black_pass", str(tonyutsu_dict.get_int("black_pass"))) tonyutsu.set_attribute("black_pass", str(tonyutsu_dict.get_int("black_pass")))
extra_boss_event_dict = profile.get_dict("extra_boss_event") extra_boss_event_dict = profile.get_dict("extra_boss_event")
extra_boss_event = Node.void("extra_boss_event") extra_boss_event = Node.void("extra_boss_event")
root.add_child(extra_boss_event) root.add_child(extra_boss_event)
for i in range(9): for i in range(9):
extra_boss_event.set_attribute( extra_boss_event.set_attribute(f"orb_{i}", str(extra_boss_event_dict.get_int(f"orb_{i}")))
f"orb_{i}", str(extra_boss_event_dict.get_int(f"orb_{i}"))
)
# Step up mode # Step up mode
step_dict = profile.get_dict("step") step_dict = profile.get_dict("step")
@ -1784,49 +1636,25 @@ class IIDXRootage(IIDXCourse, IIDXBase):
root.add_child(step) root.add_child(step)
step.set_attribute("enemy_damage", str(step_dict.get_int("enemy_damage"))) step.set_attribute("enemy_damage", str(step_dict.get_int("enemy_damage")))
step.set_attribute("progress", str(step_dict.get_int("progress"))) step.set_attribute("progress", str(step_dict.get_int("progress")))
step.add_child( step.add_child(Node.bool("is_track_ticket", step_dict.get_bool("is_track_ticket")))
Node.bool("is_track_ticket", step_dict.get_bool("is_track_ticket"))
)
step.set_attribute("sp_level", str(step_dict.get_int("sp_level"))) step.set_attribute("sp_level", str(step_dict.get_int("sp_level")))
step.set_attribute("dp_level", str(step_dict.get_int("dp_level"))) step.set_attribute("dp_level", str(step_dict.get_int("dp_level")))
step.set_attribute( step.set_attribute("sp_mission_point", str(step_dict.get_int("sp_mission_point")))
"sp_mission_point", str(step_dict.get_int("sp_mission_point")) step.set_attribute("dp_mission_point", str(step_dict.get_int("dp_mission_point")))
) step.set_attribute("sp_dj_mission_level", str(step_dict.get_int("sp_dj_mission_level@")))
step.set_attribute( step.set_attribute("dp_dj_mission_level", str(step_dict.get_int("dp_dj_mission_level@")))
"dp_mission_point", str(step_dict.get_int("dp_mission_point")) step.set_attribute("sp_clear_mission_level", str(step_dict.get_int("sp_clear_mission_level")))
) step.set_attribute("dp_clear_mission_level", str(step_dict.get_int("dp_clear_mission_level")))
step.set_attribute( step.set_attribute("sp_dj_mission_clear", str(step_dict.get_int("sp_dj_mission_clear")))
"sp_dj_mission_level", str(step_dict.get_int("sp_dj_mission_level@")) step.set_attribute("dp_dj_mission_clear", str(step_dict.get_int("dp_dj_mission_clear")))
) step.set_attribute("sp_clear_mission_clear", str(step_dict.get_int("sp_clear_mission_clear")))
step.set_attribute( step.set_attribute("dp_clear_mission_clear", str(step_dict.get_int("dp_clear_mission_clear")))
"dp_dj_mission_level", str(step_dict.get_int("dp_dj_mission_level@"))
)
step.set_attribute(
"sp_clear_mission_level", str(step_dict.get_int("sp_clear_mission_level"))
)
step.set_attribute(
"dp_clear_mission_level", str(step_dict.get_int("dp_clear_mission_level"))
)
step.set_attribute(
"sp_dj_mission_clear", str(step_dict.get_int("sp_dj_mission_clear"))
)
step.set_attribute(
"dp_dj_mission_clear", str(step_dict.get_int("dp_dj_mission_clear"))
)
step.set_attribute(
"sp_clear_mission_clear", str(step_dict.get_int("sp_clear_mission_clear"))
)
step.set_attribute(
"dp_clear_mission_clear", str(step_dict.get_int("dp_clear_mission_clear"))
)
step.set_attribute("sp_mplay", str(step_dict.get_int("sp_mplay"))) step.set_attribute("sp_mplay", str(step_dict.get_int("sp_mplay")))
step.set_attribute("dp_mplay", str(step_dict.get_int("dp_mplay"))) step.set_attribute("dp_mplay", str(step_dict.get_int("dp_mplay")))
step.set_attribute("tips_read_list", str(step_dict.get_int("tips_read_list"))) step.set_attribute("tips_read_list", str(step_dict.get_int("tips_read_list")))
# Daily recommendations # Daily recommendations
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "dailies")
self.game, self.version, "dailies"
)
if entry is not None: if entry is not None:
packinfo = Node.void("packinfo") packinfo = Node.void("packinfo")
root.add_child(packinfo) root.add_child(packinfo)
@ -1849,36 +1677,24 @@ class IIDXRootage(IIDXCourse, IIDXBase):
achievement_node.set_attribute("pack", "0") achievement_node.set_attribute("pack", "0")
achievement_node.set_attribute("pack_comp", "0") achievement_node.set_attribute("pack_comp", "0")
else: else:
daily_played = self.data.local.user.get_achievement( daily_played = self.data.local.user.get_achievement(self.game, self.version, userid, pack_id, "daily")
self.game, self.version, userid, pack_id, "daily"
)
if daily_played is None: if daily_played is None:
daily_played = ValidatedDict() daily_played = ValidatedDict()
achievement_node.set_attribute( achievement_node.set_attribute("pack", str(daily_played.get_int("pack_flg")))
"pack", str(daily_played.get_int("pack_flg")) achievement_node.set_attribute("pack_comp", str(daily_played.get_int("pack_comp")))
)
achievement_node.set_attribute(
"pack_comp", str(daily_played.get_int("pack_comp"))
)
# Weeklies # Weeklies
achievement_node.set_attribute( achievement_node.set_attribute("last_weekly", str(profile.get_int("last_weekly")))
"last_weekly", str(profile.get_int("last_weekly"))
)
achievement_node.set_attribute("weekly_num", str(profile.get_int("weekly_num"))) achievement_node.set_attribute("weekly_num", str(profile.get_int("weekly_num")))
# Prefecture visit flag # Prefecture visit flag
achievement_node.set_attribute("visit_flg", str(profile.get_int("visit_flg"))) achievement_node.set_attribute("visit_flg", str(profile.get_int("visit_flg")))
# Number of rivals beaten # Number of rivals beaten
achievement_node.set_attribute( achievement_node.set_attribute("rival_crush", str(profile.get_int("rival_crush")))
"rival_crush", str(profile.get_int("rival_crush"))
)
# Tran medals # Tran medals
achievement_node.add_child( achievement_node.add_child(Node.s64_array("trophy", profile.get_int_array("trophy", 20)))
Node.s64_array("trophy", profile.get_int_array("trophy", 20))
)
# Track deller # Track deller
deller = Node.void("deller") deller = Node.void("deller")
@ -1902,9 +1718,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
detail.set_attribute("course_id", str(rank.id)) detail.set_attribute("course_id", str(rank.id))
detail.set_attribute("n_point", str(rank.data.get_int("normal_points"))) detail.set_attribute("n_point", str(rank.data.get_int("normal_points")))
detail.set_attribute("h_point", str(rank.data.get_int("hyper_points"))) detail.set_attribute("h_point", str(rank.data.get_int("hyper_points")))
detail.set_attribute( detail.set_attribute("a_point", str(rank.data.get_int("another_points")))
"a_point", str(rank.data.get_int("another_points"))
)
nostalgia = Node.void("nostalgia_open") nostalgia = Node.void("nostalgia_open")
root.add_child(nostalgia) root.add_child(nostalgia)
@ -1918,9 +1732,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -1972,20 +1784,12 @@ class IIDXRootage(IIDXCourse, IIDXBase):
newprofile.replace_int("d_gauge_disp", int(request.attribute("d_gauge_disp"))) newprofile.replace_int("d_gauge_disp", int(request.attribute("d_gauge_disp")))
newprofile.replace_int("s_lane_brignt", int(request.attribute("s_lane_brignt"))) newprofile.replace_int("s_lane_brignt", int(request.attribute("s_lane_brignt")))
newprofile.replace_int("d_lane_brignt", int(request.attribute("d_lane_brignt"))) newprofile.replace_int("d_lane_brignt", int(request.attribute("d_lane_brignt")))
newprofile.replace_int( newprofile.replace_int("s_camera_layout", int(request.attribute("s_camera_layout")))
"s_camera_layout", int(request.attribute("s_camera_layout")) newprofile.replace_int("d_camera_layout", int(request.attribute("d_camera_layout")))
)
newprofile.replace_int(
"d_camera_layout", int(request.attribute("d_camera_layout"))
)
newprofile.replace_int("s_ghost_score", int(request.attribute("s_ghost_score"))) newprofile.replace_int("s_ghost_score", int(request.attribute("s_ghost_score")))
newprofile.replace_int("d_ghost_score", int(request.attribute("d_ghost_score"))) newprofile.replace_int("d_ghost_score", int(request.attribute("d_ghost_score")))
newprofile.replace_int( newprofile.replace_int("s_tsujigiri_disp", int(request.attribute("s_tsujigiri_disp")))
"s_tsujigiri_disp", int(request.attribute("s_tsujigiri_disp")) newprofile.replace_int("d_tsujigiri_disp", int(request.attribute("d_tsujigiri_disp")))
)
newprofile.replace_int(
"d_tsujigiri_disp", int(request.attribute("d_tsujigiri_disp"))
)
newprofile.replace_int("s_lift", int(request.attribute("s_lift"))) newprofile.replace_int("s_lift", int(request.attribute("s_lift")))
newprofile.replace_int("d_lift", int(request.attribute("d_lift"))) newprofile.replace_int("d_lift", int(request.attribute("d_lift")))
newprofile.replace_int("mode", int(request.attribute("mode"))) newprofile.replace_int("mode", int(request.attribute("mode")))
@ -2014,15 +1818,9 @@ class IIDXRootage(IIDXCourse, IIDXBase):
# Basic achievements # Basic achievements
achievements = request.child("achievements") achievements = request.child("achievements")
if achievements is not None: if achievements is not None:
newprofile.replace_int( newprofile.replace_int("visit_flg", int(achievements.attribute("visit_flg")))
"visit_flg", int(achievements.attribute("visit_flg")) newprofile.replace_int("last_weekly", int(achievements.attribute("last_weekly")))
) newprofile.replace_int("weekly_num", int(achievements.attribute("weekly_num")))
newprofile.replace_int(
"last_weekly", int(achievements.attribute("last_weekly"))
)
newprofile.replace_int(
"weekly_num", int(achievements.attribute("weekly_num"))
)
pack_id = int(achievements.attribute("pack_id")) pack_id = int(achievements.attribute("pack_id"))
if pack_id > 0: if pack_id > 0:
@ -2046,9 +1844,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
# Deller saving # Deller saving
deller = request.child("deller") deller = request.child("deller")
if deller is not None: if deller is not None:
newprofile.replace_int( newprofile.replace_int("deller", newprofile.get_int("deller") + int(deller.attribute("deller")))
"deller", newprofile.get_int("deller") + int(deller.attribute("deller"))
)
# Secret course expert point saving # Secret course expert point saving
expert_point = request.child("expert_point") expert_point = request.child("expert_point")
@ -2112,22 +1908,14 @@ class IIDXRootage(IIDXCourse, IIDXBase):
for i in range(self.FAVORITE_LIST_LENGTH): for i in range(self.FAVORITE_LIST_LENGTH):
singles.append( singles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", single_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", single_music_bin[(i * 4) : ((i + 1) * 4)] "chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[0],
)[0],
"chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[
0
],
} }
) )
doubles.append( doubles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", double_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", double_music_bin[(i * 4) : ((i + 1) * 4)] "chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[0],
)[0],
"chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[
0
],
} }
) )
@ -2172,21 +1960,11 @@ class IIDXRootage(IIDXCourse, IIDXBase):
event1_dict.increment_int("event_play_num") event1_dict.increment_int("event_play_num")
last_select_map = int(event1.attribute("last_select_map_id")) last_select_map = int(event1.attribute("last_select_map_id"))
event1_dict.replace_int("play_gift", int(event1.attribute("play_gift"))) event1_dict.replace_int("play_gift", int(event1.attribute("play_gift")))
event1_dict.replace_int( event1_dict.replace_int("fragment_num", int(event1.attribute("fragment_num")))
"fragment_num", int(event1.attribute("fragment_num")) event1_dict.replace_int("continuous_correct", int(event1.attribute("continuous_correct")))
) event1_dict.replace_int("bookshelf_release_num", int(event1.attribute("bookshelf_release_num")))
event1_dict.replace_int( event1_dict.replace_int("read_tips_list", int(event1.attribute("read_tips_list")))
"continuous_correct", int(event1.attribute("continuous_correct")) event1_dict.replace_bytes("quiz_control_list", event1.child_value("quiz_control_list"))
)
event1_dict.replace_int(
"bookshelf_release_num", int(event1.attribute("bookshelf_release_num"))
)
event1_dict.replace_int(
"read_tips_list", int(event1.attribute("read_tips_list"))
)
event1_dict.replace_bytes(
"quiz_control_list", event1.child_value("quiz_control_list")
)
# Save any map data, also see if we need to update last_select_map # Save any map data, also see if we need to update last_select_map
for map_data in event1.children: for map_data in event1.children:
if map_data.name != "map_data": if map_data.name != "map_data":
@ -2227,27 +2005,13 @@ class IIDXRootage(IIDXCourse, IIDXBase):
event2_dict = newprofile.get_dict("event2") event2_dict = newprofile.get_dict("event2")
event2_dict.replace_int("play_num", int(event2.attribute("play_num"))) event2_dict.replace_int("play_num", int(event2.attribute("play_num")))
event2_dict.replace_int("delabity", int(event2.attribute("delabity"))) event2_dict.replace_int("delabity", int(event2.attribute("delabity")))
event2_dict.replace_int( event2_dict.replace_int("floor_0_last_area", int(event2.attribute("floor_0_last_area")))
"floor_0_last_area", int(event2.attribute("floor_0_last_area")) event2_dict.replace_int("floor_1_last_area", int(event2.attribute("floor_1_last_area")))
) event2_dict.replace_int("floor_2_last_area", int(event2.attribute("floor_2_last_area")))
event2_dict.replace_int( event2_dict.replace_int("floor_3_last_area", int(event2.attribute("floor_3_last_area")))
"floor_1_last_area", int(event2.attribute("floor_1_last_area")) event2_dict.replace_int("floor_4_last_area", int(event2.attribute("floor_4_last_area")))
) event2_dict.replace_int("floor_clear_flg_list", int(event2.attribute("floor_clear_flg_list")))
event2_dict.replace_int( event2_dict.replace_int("last_select_floor", int(event2.attribute("last_select_floor")))
"floor_2_last_area", int(event2.attribute("floor_2_last_area"))
)
event2_dict.replace_int(
"floor_3_last_area", int(event2.attribute("floor_3_last_area"))
)
event2_dict.replace_int(
"floor_4_last_area", int(event2.attribute("floor_4_last_area"))
)
event2_dict.replace_int(
"floor_clear_flg_list", int(event2.attribute("floor_clear_flg_list"))
)
event2_dict.replace_int(
"last_select_floor", int(event2.attribute("last_select_floor"))
)
event2_dict.replace_int("tips_list", int(event2.attribute("tips_list"))) event2_dict.replace_int("tips_list", int(event2.attribute("tips_list")))
for area_data in event2.children: for area_data in event2.children:
@ -2263,26 +2027,14 @@ class IIDXRootage(IIDXCourse, IIDXBase):
f"area_data_floor_{floor_id}", # Save floor_id twice since the game seems to key by both f"area_data_floor_{floor_id}", # Save floor_id twice since the game seems to key by both
{ {
"floor_id": floor_id, "floor_id": floor_id,
"last_select_note": int( "last_select_note": int(area_data.attribute("last_select_note")),
area_data.attribute("last_select_note")
),
"normal_play_num": int(area_data.attribute("normal_play_num")), "normal_play_num": int(area_data.attribute("normal_play_num")),
"hyper_play_num": int(area_data.attribute("hyper_play_num")), "hyper_play_num": int(area_data.attribute("hyper_play_num")),
"another_play_num": int( "another_play_num": int(area_data.attribute("another_play_num")),
area_data.attribute("another_play_num") "area_clear_flg_list": int(area_data.attribute("area_clear_flg_list")),
), "normal_grade_point": int(area_data.attribute("normal_grade_point")),
"area_clear_flg_list": int( "hyper_grade_point": int(area_data.attribute("hyper_grade_point")),
area_data.attribute("area_clear_flg_list") "another_grade_point": int(area_data.attribute("another_grade_point")),
),
"normal_grade_point": int(
area_data.attribute("normal_grade_point")
),
"hyper_grade_point": int(
area_data.attribute("hyper_grade_point")
),
"another_grade_point": int(
area_data.attribute("another_grade_point")
),
}, },
) )
@ -2292,9 +2044,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
if extra_boss_event is not None: if extra_boss_event is not None:
extra_boss_event_dict = newprofile.get_dict("extra_boss_event") extra_boss_event_dict = newprofile.get_dict("extra_boss_event")
for i in range(9): for i in range(9):
extra_boss_event_dict.replace_int( extra_boss_event_dict.replace_int(f"orb_{i}", int(extra_boss_event.attribute(f"orb_{i}")))
f"orb_{i}", int(extra_boss_event.attribute(f"orb_{i}"))
)
newprofile.replace_dict("extra_boss_event", extra_boss_event_dict) newprofile.replace_dict("extra_boss_event", extra_boss_event_dict)
# Step-up mode # Step-up mode
@ -2303,25 +2053,15 @@ class IIDXRootage(IIDXCourse, IIDXBase):
step_dict = newprofile.get_dict("step") step_dict = newprofile.get_dict("step")
step_dict.replace_int("enemy_damage", int(step.attribute("enemy_damage"))) step_dict.replace_int("enemy_damage", int(step.attribute("enemy_damage")))
step_dict.replace_int("progress", int(step.attribute("progress"))) step_dict.replace_int("progress", int(step.attribute("progress")))
step_dict.replace_bool( step_dict.replace_bool("is_track_ticket", bool(step.child_value("is_track_ticket")))
"is_track_ticket", bool(step.child_value("is_track_ticket"))
)
step_dict.replace_int("sp_level", int(step.attribute("sp_level"))) step_dict.replace_int("sp_level", int(step.attribute("sp_level")))
step_dict.replace_int("dp_level", int(step.attribute("dp_level"))) step_dict.replace_int("dp_level", int(step.attribute("dp_level")))
step_dict.replace_int("sp_mplay", int(step.attribute("sp_mplay"))) step_dict.replace_int("sp_mplay", int(step.attribute("sp_mplay")))
step_dict.replace_int("dp_mplay", int(step.attribute("dp_mplay"))) step_dict.replace_int("dp_mplay", int(step.attribute("dp_mplay")))
step_dict.replace_int( step_dict.replace_int("sp_mission_point", str(step_dict.get_int("sp_mission_point")))
"sp_mission_point", str(step_dict.get_int("sp_mission_point")) step_dict.replace_int("dp_mission_point", str(step_dict.get_int("dp_mission_point")))
) step_dict.replace_int("sp_dj_mission_level", str(step_dict.get_int("sp_dj_mission_level@")))
step_dict.replace_int( step_dict.replace_int("dp_dj_mission_level", str(step_dict.get_int("dp_dj_mission_level@")))
"dp_mission_point", str(step_dict.get_int("dp_mission_point"))
)
step_dict.replace_int(
"sp_dj_mission_level", str(step_dict.get_int("sp_dj_mission_level@"))
)
step_dict.replace_int(
"dp_dj_mission_level", str(step_dict.get_int("dp_dj_mission_level@"))
)
step_dict.replace_int( step_dict.replace_int(
"sp_clear_mission_level", "sp_clear_mission_level",
str(step_dict.get_int("sp_clear_mission_level")), str(step_dict.get_int("sp_clear_mission_level")),
@ -2330,12 +2070,8 @@ class IIDXRootage(IIDXCourse, IIDXBase):
"dp_clear_mission_level", "dp_clear_mission_level",
str(step_dict.get_int("dp_clear_mission_level")), str(step_dict.get_int("dp_clear_mission_level")),
) )
step_dict.replace_int( step_dict.replace_int("sp_dj_mission_clear", str(step_dict.get_int("sp_dj_mission_clear")))
"sp_dj_mission_clear", str(step_dict.get_int("sp_dj_mission_clear")) step_dict.replace_int("dp_dj_mission_clear", str(step_dict.get_int("dp_dj_mission_clear")))
)
step_dict.replace_int(
"dp_dj_mission_clear", str(step_dict.get_int("dp_dj_mission_clear"))
)
step_dict.replace_int( step_dict.replace_int(
"sp_clear_mission_clear", "sp_clear_mission_clear",
str(step_dict.get_int("sp_clear_mission_clear")), str(step_dict.get_int("sp_clear_mission_clear")),
@ -2344,9 +2080,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
"dp_clear_mission_clear", "dp_clear_mission_clear",
str(step_dict.get_int("dp_clear_mission_clear")), str(step_dict.get_int("dp_clear_mission_clear")),
) )
step_dict.replace_int( step_dict.replace_int("tips_read_list", str(step_dict.get_int("tips_read_list")))
"tips_read_list", str(step_dict.get_int("tips_read_list"))
)
newprofile.replace_dict("step", step_dict) newprofile.replace_dict("step", step_dict)
# QPro equip in step-up mode # QPro equip in step-up mode
@ -2364,21 +2098,11 @@ class IIDXRootage(IIDXCourse, IIDXBase):
qpro_secret = request.child("qpro_secret") qpro_secret = request.child("qpro_secret")
if qpro_secret is not None: if qpro_secret is not None:
qpro_secret_dict = newprofile.get_dict("qpro_secret") qpro_secret_dict = newprofile.get_dict("qpro_secret")
qpro_secret_dict.replace_int_array( qpro_secret_dict.replace_int_array("head", 5, qpro_secret.child_value("head"))
"head", 5, qpro_secret.child_value("head") qpro_secret_dict.replace_int_array("hair", 5, qpro_secret.child_value("hair"))
) qpro_secret_dict.replace_int_array("face", 5, qpro_secret.child_value("face"))
qpro_secret_dict.replace_int_array( qpro_secret_dict.replace_int_array("body", 5, qpro_secret.child_value("body"))
"hair", 5, qpro_secret.child_value("hair") qpro_secret_dict.replace_int_array("hand", 5, qpro_secret.child_value("hand"))
)
qpro_secret_dict.replace_int_array(
"face", 5, qpro_secret.child_value("face")
)
qpro_secret_dict.replace_int_array(
"body", 5, qpro_secret.child_value("body")
)
qpro_secret_dict.replace_int_array(
"hand", 5, qpro_secret.child_value("hand")
)
newprofile.replace_dict("qpro_secret", qpro_secret_dict) newprofile.replace_dict("qpro_secret", qpro_secret_dict)
# Orb data saving # Orb data saving
@ -2394,9 +2118,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
tonyutsu = request.child("tonyutsu") tonyutsu = request.child("tonyutsu")
if tonyutsu is not None: if tonyutsu is not None:
tonyutsu_dict = newprofile.get_dict("tonyutsu") tonyutsu_dict = newprofile.get_dict("tonyutsu")
tonyutsu_dict.replace_int( tonyutsu_dict.replace_int("platinum_pass", tonyutsu.attribute("platinum_pass"))
"platinum_pass", tonyutsu.attribute("platinum_pass")
)
tonyutsu_dict.replace_int("black_pass", tonyutsu.attribute("black_pass")) tonyutsu_dict.replace_int("black_pass", tonyutsu.attribute("black_pass"))
# Keep track of play statistics across all mixes # Keep track of play statistics across all mixes

View File

@ -105,28 +105,15 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
return IIDXCopula(self.data, self.config, self.model) return IIDXCopula(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert dailies into the DB. Insert dailies into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "daily_charts", "daily"):
cls.game, cls.version, "daily_charts", "daily"
):
# Generate a new list of three dailies. # Generate a new list of three dailies.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = list( all_songs = list(set([song.id for song in data.local.music.get_all_songs(cls.game, cls.version)]))
set(
[
song.id
for song in data.local.music.get_all_songs(
cls.game, cls.version
)
]
)
)
if len(all_songs) >= 3: if len(all_songs) >= 3:
daily_songs = random.sample(all_songs, 3) daily_songs = random.sample(all_songs, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -150,9 +137,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "daily_charts", "daily")
cls.game, cls.version, "daily_charts", "daily"
)
return events return events
@classmethod @classmethod
@ -387,9 +372,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
root = Node.void("IIDX24shop") root = Node.void("IIDX24shop")
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -412,9 +395,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
course.replace_int("music_2", request.child_value("music_2")) course.replace_int("music_2", request.child_value("music_2"))
course.replace_int("music_3", request.child_value("music_3")) course.replace_int("music_3", request.child_value("music_3"))
course.replace_bool("valid", request.child_value("valid")) course.replace_bool("valid", request.child_value("valid"))
self.data.local.machine.put_settings( self.data.local.machine.put_settings(machine.arcade, self.game, self.music_version, "shop_course", course)
machine.arcade, self.game, self.music_version, "shop_course", course
)
return Node.void("IIDX24shop") return Node.void("IIDX24shop")
@ -434,9 +415,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -574,16 +553,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
root = Node.void("IIDX24music") root = Node.void("IIDX24music")
attempts = self.get_clear_rates() attempts = self.get_clear_rates()
all_songs = list( all_songs = list(set([song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)]))
set(
[
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
]
)
)
for song in all_songs: for song in all_songs:
clears = [] clears = []
fcs = [] fcs = []
@ -627,16 +597,12 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
continue continue
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
# Grab score data for user/rival # Grab score data for user/rival
scoredata = self.make_score_struct( scoredata = self.make_score_struct(
scores, scores,
self.CLEAR_TYPE_SINGLE self.CLEAR_TYPE_SINGLE if cltype == self.GAME_CLTYPE_SINGLE else self.CLEAR_TYPE_DOUBLE,
if cltype == self.GAME_CLTYPE_SINGLE
else self.CLEAR_TYPE_DOUBLE,
rivalid, rivalid,
) )
for s in scoredata: for s in scoredata:
@ -644,10 +610,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
# Grab most played for user/rival # Grab most played for user/rival
most_played = [ most_played = [
play[0] play[0] for play in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)
for play in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
] ]
if len(most_played) < 20: if len(most_played) < 20:
most_played.extend([0] * (20 - len(most_played))) most_played.extend([0] * (20 - len(most_played)))
@ -674,9 +637,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
if userid is not None: if userid is not None:
# Try to look up previous ghost for user # Try to look up previous ghost for user
my_score = self.data.remote.music.get_score( my_score = self.data.remote.music.get_score(self.game, self.music_version, userid, musicid, chart)
self.game, self.music_version, userid, musicid, chart
)
if my_score is not None: if my_score is not None:
mydata = Node.binary("mydata", my_score.data.get_bytes("ghost")) mydata = Node.binary("mydata", my_score.data.get_bytes("ghost"))
mydata.set_attribute("score", str(my_score.points)) mydata.set_attribute("score", str(my_score.points))
@ -767,19 +728,13 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
key=lambda s: (s[1].points, s[1].timestamp), key=lambda s: (s[1].points, s[1].timestamp),
reverse=True, reverse=True,
) )
all_players = { all_players = {uid: prof for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])}
uid: prof
for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])
}
if not global_scores: if not global_scores:
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -831,9 +786,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
# Shop ranking # Shop ranking
shopdata = Node.void("shopdata") shopdata = Node.void("shopdata")
root.add_child(shopdata) root.add_child(shopdata)
shopdata.set_attribute( shopdata.set_attribute("rank", "-1" if oldindex is None else str(oldindex + 1))
"rank", "-1" if oldindex is None else str(oldindex + 1)
)
# Grab the rank of some other players on this song # Grab the rank of some other players on this song
ranklist = Node.void("ranklist") ranklist = Node.void("ranklist")
@ -857,10 +810,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -1324,9 +1274,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
used_secret_ids: List[int] = [] used_secret_ids: List[int] = []
for c in secret_courses: for c in secret_courses:
if c["id"] in used_secret_ids: if c["id"] in used_secret_ids:
raise Exception( raise Exception("Cannot have multiple secret courses with the same ID!")
"Cannot have multiple secret courses with the same ID!"
)
elif c["id"] < 0 or c["id"] >= 20: elif c["id"] < 0 or c["id"] >= 20:
raise Exception("Secret course ID is out of bounds!") raise Exception("Secret course ID is out of bounds!")
else: else:
@ -1503,9 +1451,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
best_clear_string = clear_map.get(best_clear, "NO PLAY") best_clear_string = clear_map.get(best_clear, "NO PLAY")
now_clear_string = clear_map.get(now_clear, "NO PLAY") now_clear_string = clear_map.get(now_clear, "NO PLAY")
# let's get the song info first # let's get the song info first
song = self.data.local.music.get_song( song = self.data.local.music.get_song(self.game, self.music_version, music_id, self.game_to_db_chart(class_id))
self.game, self.music_version, music_id, self.game_to_db_chart(class_id)
)
notecount = song.data.get("notecount", 0) notecount = song.data.get("notecount", 0)
# Construct the dictionary for the broadcast # Construct the dictionary for the broadcast
card_data = { card_data = {
@ -1622,15 +1568,9 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
secret.add_child(Node.s64_array("flg2", [-1, -1, -1])) secret.add_child(Node.s64_array("flg2", [-1, -1, -1]))
secret.add_child(Node.s64_array("flg3", [-1, -1, -1])) secret.add_child(Node.s64_array("flg3", [-1, -1, -1]))
else: else:
secret.add_child( secret.add_child(Node.s64_array("flg1", secret_dict.get_int_array("flg1", 3)))
Node.s64_array("flg1", secret_dict.get_int_array("flg1", 3)) secret.add_child(Node.s64_array("flg2", secret_dict.get_int_array("flg2", 3)))
) secret.add_child(Node.s64_array("flg3", secret_dict.get_int_array("flg3", 3)))
secret.add_child(
Node.s64_array("flg2", secret_dict.get_int_array("flg2", 3))
)
secret.add_child(
Node.s64_array("flg3", secret_dict.get_int_array("flg3", 3))
)
# Favorites # Favorites
for folder in ["favorite1", "favorite2", "favorite3"]: for folder in ["favorite1", "favorite2", "favorite3"]:
@ -1692,9 +1632,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
) )
), ),
) )
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for rank in achievements: for rank in achievements:
if rank.type == self.DAN_RANKING_SINGLE: if rank.type == self.DAN_RANKING_SINGLE:
grade.add_child( grade.add_child(
@ -1766,21 +1704,11 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
qpro_secrete_dict = profile.get_dict("qpro_secret") qpro_secrete_dict = profile.get_dict("qpro_secret")
qpro_secret = Node.void("qpro_secret") qpro_secret = Node.void("qpro_secret")
root.add_child(qpro_secret) root.add_child(qpro_secret)
qpro_secret.add_child( qpro_secret.add_child(Node.s64_array("head", qpro_secrete_dict.get_int_array("head", 5)))
Node.s64_array("head", qpro_secrete_dict.get_int_array("head", 5)) qpro_secret.add_child(Node.s64_array("hair", qpro_secrete_dict.get_int_array("hair", 5)))
) qpro_secret.add_child(Node.s64_array("face", qpro_secrete_dict.get_int_array("face", 5)))
qpro_secret.add_child( qpro_secret.add_child(Node.s64_array("body", qpro_secrete_dict.get_int_array("body", 5)))
Node.s64_array("hair", qpro_secrete_dict.get_int_array("hair", 5)) qpro_secret.add_child(Node.s64_array("hand", qpro_secrete_dict.get_int_array("hand", 5)))
)
qpro_secret.add_child(
Node.s64_array("face", qpro_secrete_dict.get_int_array("face", 5))
)
qpro_secret.add_child(
Node.s64_array("body", qpro_secrete_dict.get_int_array("body", 5))
)
qpro_secret.add_child(
Node.s64_array("hand", qpro_secrete_dict.get_int_array("hand", 5))
)
# Rivals # Rivals
rlist = Node.void("rlist") rlist = Node.void("rlist")
@ -1861,9 +1789,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
[ [
courseid, # course ID courseid, # course ID
coursechart, # course chart coursechart, # course chart
self.db_to_game_status( self.db_to_game_status(course.data.get_int("clear_status")), # course clear status
course.data.get_int("clear_status")
), # course clear status
course.data.get_int("pgnum"), # flashing great count course.data.get_int("pgnum"), # flashing great count
course.data.get_int("gnum"), # great count course.data.get_int("gnum"), # great count
], ],
@ -1881,9 +1807,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
[ [
courseid, # course ID courseid, # course ID
coursechart, # course chart coursechart, # course chart
self.db_to_game_status( self.db_to_game_status(course.data.get_int("clear_status")), # course clear status
course.data.get_int("clear_status")
), # course clear status
course.data.get_int("pgnum"), # flashing great count course.data.get_int("pgnum"), # flashing great count
course.data.get_int("gnum"), # great count course.data.get_int("gnum"), # great count
], ],
@ -1918,20 +1842,14 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
ninja_rank_node = Node.void("ninja_rank") ninja_rank_node = Node.void("ninja_rank")
root.add_child(ninja_rank_node) root.add_child(ninja_rank_node)
ninja_rank_node.set_attribute("style", str(ninja_rank.id)) ninja_rank_node.set_attribute("style", str(ninja_rank.id))
ninja_rank_node.add_child( ninja_rank_node.add_child(Node.s32_array("rank", ninja_rank.data.get_int_array("rank", 13)))
Node.s32_array("rank", ninja_rank.data.get_int_array("rank", 13)) ninja_rank_node.add_child(Node.s32_array("point", ninja_rank.data.get_int_array("point", 13)))
)
ninja_rank_node.add_child(
Node.s32_array("point", ninja_rank.data.get_int_array("point", 13))
)
# SINOBUZ Den event # SINOBUZ Den event
event1_dict = profile.get_dict("event1") event1_dict = profile.get_dict("event1")
event1 = Node.void("event1") event1 = Node.void("event1")
root.add_child(event1) root.add_child(event1)
event1.set_attribute( event1.set_attribute("last_select_map", str(event1_dict.get_int("last_select_map")))
"last_select_map", str(event1_dict.get_int("last_select_map"))
)
event1.set_attribute("hold_rice", str(event1_dict.get_int("hold_rice"))) event1.set_attribute("hold_rice", str(event1_dict.get_int("hold_rice")))
event1.set_attribute("tax_rice", str(event1_dict.get_int("tax_rice"))) event1.set_attribute("tax_rice", str(event1_dict.get_int("tax_rice")))
event1.set_attribute("tips_list", str(event1_dict.get_int("tips_list"))) event1.set_attribute("tips_list", str(event1_dict.get_int("tips_list")))
@ -1943,32 +1861,14 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
map_data_node = Node.void("map_data") map_data_node = Node.void("map_data")
event1.add_child(map_data_node) event1.add_child(map_data_node)
map_data_node.set_attribute("map_id", str(map_data.id)) map_data_node.set_attribute("map_id", str(map_data.id))
map_data_node.set_attribute( map_data_node.set_attribute("play_num", str(map_data.data.get_int("play_num")))
"play_num", str(map_data.data.get_int("play_num")) map_data_node.set_attribute("progress", str(map_data.data.get_int("progress")))
) map_data_node.set_attribute("battle_point", str(map_data.data.get_int("battle_point")))
map_data_node.set_attribute( map_data_node.set_attribute("rice_point", str(map_data.data.get_int("rice_point")))
"progress", str(map_data.data.get_int("progress")) map_data_node.set_attribute("is_clear", "1" if map_data.data.get_bool("is_clear") else "0")
) map_data_node.add_child(Node.binary("ninjyutsu", map_data.data.get_bytes("ninjyutsu")))
map_data_node.set_attribute( map_data_node.add_child(Node.binary("map_card_damage", map_data.data.get_bytes("map_card_damage")))
"battle_point", str(map_data.data.get_int("battle_point")) map_data_node.add_child(Node.binary("map_card_clear", map_data.data.get_bytes("map_card_clear")))
)
map_data_node.set_attribute(
"rice_point", str(map_data.data.get_int("rice_point"))
)
map_data_node.set_attribute(
"is_clear", "1" if map_data.data.get_bool("is_clear") else "0"
)
map_data_node.add_child(
Node.binary("ninjyutsu", map_data.data.get_bytes("ninjyutsu"))
)
map_data_node.add_child(
Node.binary(
"map_card_damage", map_data.data.get_bytes("map_card_damage")
)
)
map_data_node.add_child(
Node.binary("map_card_clear", map_data.data.get_bytes("map_card_clear"))
)
# Shichikenden event # Shichikenden event
event2_dict = profile.get_dict("event2") event2_dict = profile.get_dict("event2")
@ -1976,20 +1876,14 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
root.add_child(event2) root.add_child(event2)
event2.set_attribute("play_num", str(event2_dict.get_int("play_num"))) event2.set_attribute("play_num", str(event2_dict.get_int("play_num")))
event2.set_attribute("chakra_point", str(event2_dict.get_int("chakra_point"))) event2.set_attribute("chakra_point", str(event2_dict.get_int("chakra_point")))
event2.set_attribute( event2.set_attribute("last_select_ryuha", str(event2_dict.get_int("last_select_ryuha")))
"last_select_ryuha", str(event2_dict.get_int("last_select_ryuha"))
)
event2.add_child( event2.add_child(
Node.binary( Node.binary(
"last_select_dojo", "last_select_dojo",
event2_dict.get_bytes("last_select_dojo", b"\0" * 12), event2_dict.get_bytes("last_select_dojo", b"\0" * 12),
) )
) )
event2.add_child( event2.add_child(Node.binary("enemy_damage", event2_dict.get_bytes("enemy_damage", b"\0" * 532)))
Node.binary(
"enemy_damage", event2_dict.get_bytes("enemy_damage", b"\0" * 532)
)
)
# OMES Data # OMES Data
omes_dict = profile.get_dict("omes") omes_dict = profile.get_dict("omes")
@ -2002,15 +1896,9 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
onemore_data.set_attribute("defeat_4", str(omes_dict.get_int("defeat_4"))) onemore_data.set_attribute("defeat_4", str(omes_dict.get_int("defeat_4")))
onemore_data.set_attribute("defeat_5", str(omes_dict.get_int("defeat_5"))) onemore_data.set_attribute("defeat_5", str(omes_dict.get_int("defeat_5")))
onemore_data.set_attribute("defeat_6", str(omes_dict.get_int("defeat_6"))) onemore_data.set_attribute("defeat_6", str(omes_dict.get_int("defeat_6")))
onemore_data.set_attribute( onemore_data.set_attribute("challenge_num_n", str(omes_dict.get_int("challenge_num_n")))
"challenge_num_n", str(omes_dict.get_int("challenge_num_n")) onemore_data.set_attribute("challenge_num_h", str(omes_dict.get_int("challenge_num_h")))
) onemore_data.set_attribute("challenge_num_a", str(omes_dict.get_int("challenge_num_a")))
onemore_data.set_attribute(
"challenge_num_h", str(omes_dict.get_int("challenge_num_h"))
)
onemore_data.set_attribute(
"challenge_num_a", str(omes_dict.get_int("challenge_num_a"))
)
# If the user joined a particular shop, let the game know. # If the user joined a particular shop, let the game know.
if "shop_location" in profile: if "shop_location" in profile:
@ -2030,18 +1918,14 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
root.add_child(step) root.add_child(step)
step.set_attribute("enemy_damage", str(step_dict.get_int("enemy_damage"))) step.set_attribute("enemy_damage", str(step_dict.get_int("enemy_damage")))
step.set_attribute("progress", str(step_dict.get_int("progress"))) step.set_attribute("progress", str(step_dict.get_int("progress")))
step.set_attribute( step.set_attribute("enemy_defeat_flg", str(step_dict.get_int("enemy_defeat_flg")))
"enemy_defeat_flg", str(step_dict.get_int("enemy_defeat_flg"))
)
step.set_attribute("sp_level", str(step_dict.get_int("sp_level"))) step.set_attribute("sp_level", str(step_dict.get_int("sp_level")))
step.set_attribute("dp_level", str(step_dict.get_int("dp_level"))) step.set_attribute("dp_level", str(step_dict.get_int("dp_level")))
step.set_attribute("sp_mplay", str(step_dict.get_int("sp_mplay"))) step.set_attribute("sp_mplay", str(step_dict.get_int("sp_mplay")))
step.set_attribute("dp_mplay", str(step_dict.get_int("dp_mplay"))) step.set_attribute("dp_mplay", str(step_dict.get_int("dp_mplay")))
# Daily recommendations # Daily recommendations
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "dailies")
self.game, self.version, "dailies"
)
if entry is not None: if entry is not None:
packinfo = Node.void("packinfo") packinfo = Node.void("packinfo")
root.add_child(packinfo) root.add_child(packinfo)
@ -2064,36 +1948,24 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
achievement_node.set_attribute("pack", "0") achievement_node.set_attribute("pack", "0")
achievement_node.set_attribute("pack_comp", "0") achievement_node.set_attribute("pack_comp", "0")
else: else:
daily_played = self.data.local.user.get_achievement( daily_played = self.data.local.user.get_achievement(self.game, self.version, userid, pack_id, "daily")
self.game, self.version, userid, pack_id, "daily"
)
if daily_played is None: if daily_played is None:
daily_played = ValidatedDict() daily_played = ValidatedDict()
achievement_node.set_attribute( achievement_node.set_attribute("pack", str(daily_played.get_int("pack_flg")))
"pack", str(daily_played.get_int("pack_flg")) achievement_node.set_attribute("pack_comp", str(daily_played.get_int("pack_comp")))
)
achievement_node.set_attribute(
"pack_comp", str(daily_played.get_int("pack_comp"))
)
# Weeklies # Weeklies
achievement_node.set_attribute( achievement_node.set_attribute("last_weekly", str(profile.get_int("last_weekly")))
"last_weekly", str(profile.get_int("last_weekly"))
)
achievement_node.set_attribute("weekly_num", str(profile.get_int("weekly_num"))) achievement_node.set_attribute("weekly_num", str(profile.get_int("weekly_num")))
# Prefecture visit flag # Prefecture visit flag
achievement_node.set_attribute("visit_flg", str(profile.get_int("visit_flg"))) achievement_node.set_attribute("visit_flg", str(profile.get_int("visit_flg")))
# Number of rivals beaten # Number of rivals beaten
achievement_node.set_attribute( achievement_node.set_attribute("rival_crush", str(profile.get_int("rival_crush")))
"rival_crush", str(profile.get_int("rival_crush"))
)
# Tran medals # Tran medals
achievement_node.add_child( achievement_node.add_child(Node.s64_array("trophy", profile.get_int_array("trophy", 10)))
Node.s64_array("trophy", profile.get_int_array("trophy", 10))
)
# Track deller # Track deller
deller = Node.void("deller") deller = Node.void("deller")
@ -2116,9 +1988,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
detail.set_attribute("course_id", str(rank.id)) detail.set_attribute("course_id", str(rank.id))
detail.set_attribute("n_point", str(rank.data.get_int("normal_points"))) detail.set_attribute("n_point", str(rank.data.get_int("normal_points")))
detail.set_attribute("h_point", str(rank.data.get_int("hyper_points"))) detail.set_attribute("h_point", str(rank.data.get_int("hyper_points")))
detail.set_attribute( detail.set_attribute("a_point", str(rank.data.get_int("another_points")))
"a_point", str(rank.data.get_int("another_points"))
)
nostalgia = Node.void("nostalgia_open") nostalgia = Node.void("nostalgia_open")
root.add_child(nostalgia) root.add_child(nostalgia)
@ -2128,9 +1998,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
root.add_child(Node.void("bind_eaappli")) root.add_child(Node.void("bind_eaappli"))
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -2206,15 +2074,9 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
# Basic achievements # Basic achievements
achievements = request.child("achievements") achievements = request.child("achievements")
if achievements is not None: if achievements is not None:
newprofile.replace_int( newprofile.replace_int("visit_flg", int(achievements.attribute("visit_flg")))
"visit_flg", int(achievements.attribute("visit_flg")) newprofile.replace_int("last_weekly", int(achievements.attribute("last_weekly")))
) newprofile.replace_int("weekly_num", int(achievements.attribute("weekly_num")))
newprofile.replace_int(
"last_weekly", int(achievements.attribute("last_weekly"))
)
newprofile.replace_int(
"weekly_num", int(achievements.attribute("weekly_num"))
)
pack_id = int(achievements.attribute("pack_id")) pack_id = int(achievements.attribute("pack_id"))
if pack_id > 0: if pack_id > 0:
@ -2238,9 +2100,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
# Deller saving # Deller saving
deller = request.child("deller") deller = request.child("deller")
if deller is not None: if deller is not None:
newprofile.replace_int( newprofile.replace_int("deller", newprofile.get_int("deller") + int(deller.attribute("deller")))
"deller", newprofile.get_int("deller") + int(deller.attribute("deller"))
)
# Secret course expert point saving # Secret course expert point saving
expert_point = request.child("expert_point") expert_point = request.child("expert_point")
@ -2304,22 +2164,14 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
for i in range(self.FAVORITE_LIST_LENGTH): for i in range(self.FAVORITE_LIST_LENGTH):
singles.append( singles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", single_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", single_music_bin[(i * 4) : ((i + 1) * 4)] "chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[0],
)[0],
"chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[
0
],
} }
) )
doubles.append( doubles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", double_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", double_music_bin[(i * 4) : ((i + 1) * 4)] "chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[0],
)[0],
"chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[
0
],
} }
) )
@ -2412,18 +2264,10 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
if event2 is not None: if event2 is not None:
event2_dict = newprofile.get_dict("event2") event2_dict = newprofile.get_dict("event2")
event2_dict.replace_int("play_num", int(event2.attribute("play_num"))) event2_dict.replace_int("play_num", int(event2.attribute("play_num")))
event2_dict.replace_int( event2_dict.replace_int("last_select_ryuha", int(event2.attribute("last_select_ryuha")))
"last_select_ryuha", int(event2.attribute("last_select_ryuha")) event2_dict.replace_int("chakra_point", int(event2.attribute("chakra_point")))
) event2_dict.replace_bytes("last_select_dojo", event2.child_value("last_select_dojo"))
event2_dict.replace_int( event2_dict.replace_bytes("enemy_damage", event2.child_value("enemy_damage"))
"chakra_point", int(event2.attribute("chakra_point"))
)
event2_dict.replace_bytes(
"last_select_dojo", event2.child_value("last_select_dojo")
)
event2_dict.replace_bytes(
"enemy_damage", event2.child_value("enemy_damage")
)
newprofile.replace_dict("event2", event2_dict) newprofile.replace_dict("event2", event2_dict)
# Step-up mode # Step-up mode
@ -2432,9 +2276,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
step_dict = newprofile.get_dict("step") step_dict = newprofile.get_dict("step")
step_dict.replace_int("enemy_damage", int(step.attribute("enemy_damage"))) step_dict.replace_int("enemy_damage", int(step.attribute("enemy_damage")))
step_dict.replace_int("progress", int(step.attribute("progress"))) step_dict.replace_int("progress", int(step.attribute("progress")))
step_dict.replace_int( step_dict.replace_int("enemy_defeat_flg", int(step.attribute("enemy_defeat_flg")))
"enemy_defeat_flg", int(step.attribute("enemy_defeat_flg"))
)
step_dict.replace_int("sp_level", int(step.attribute("sp_level"))) step_dict.replace_int("sp_level", int(step.attribute("sp_level")))
step_dict.replace_int("dp_level", int(step.attribute("dp_level"))) step_dict.replace_int("dp_level", int(step.attribute("dp_level")))
step_dict.replace_int("sp_mplay", int(step.attribute("sp_mplay"))) step_dict.replace_int("sp_mplay", int(step.attribute("sp_mplay")))
@ -2456,21 +2298,11 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
qpro_secret = request.child("qpro_secret") qpro_secret = request.child("qpro_secret")
if qpro_secret is not None: if qpro_secret is not None:
qpro_secret_dict = newprofile.get_dict("qpro_secret") qpro_secret_dict = newprofile.get_dict("qpro_secret")
qpro_secret_dict.replace_int_array( qpro_secret_dict.replace_int_array("head", 5, qpro_secret.child_value("head"))
"head", 5, qpro_secret.child_value("head") qpro_secret_dict.replace_int_array("hair", 5, qpro_secret.child_value("hair"))
) qpro_secret_dict.replace_int_array("face", 5, qpro_secret.child_value("face"))
qpro_secret_dict.replace_int_array( qpro_secret_dict.replace_int_array("body", 5, qpro_secret.child_value("body"))
"hair", 5, qpro_secret.child_value("hair") qpro_secret_dict.replace_int_array("hand", 5, qpro_secret.child_value("hand"))
)
qpro_secret_dict.replace_int_array(
"face", 5, qpro_secret.child_value("face")
)
qpro_secret_dict.replace_int_array(
"body", 5, qpro_secret.child_value("body")
)
qpro_secret_dict.replace_int_array(
"hand", 5, qpro_secret.child_value("hand")
)
newprofile.replace_dict("qpro_secret", qpro_secret_dict) newprofile.replace_dict("qpro_secret", qpro_secret_dict)
# Orb data saving # Orb data saving
@ -2493,15 +2325,9 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
omes_dict.replace_int("defeat_4", int(onemore_data.attribute("defeat_4"))) omes_dict.replace_int("defeat_4", int(onemore_data.attribute("defeat_4")))
omes_dict.replace_int("defeat_5", int(onemore_data.attribute("defeat_5"))) omes_dict.replace_int("defeat_5", int(onemore_data.attribute("defeat_5")))
omes_dict.replace_int("defeat_6", int(onemore_data.attribute("defeat_6"))) omes_dict.replace_int("defeat_6", int(onemore_data.attribute("defeat_6")))
omes_dict.replace_int( omes_dict.replace_int("challenge_num_n", int(onemore_data.attribute("challenge_num_n")))
"challenge_num_n", int(onemore_data.attribute("challenge_num_n")) omes_dict.replace_int("challenge_num_h", int(onemore_data.attribute("challenge_num_h")))
) omes_dict.replace_int("challenge_num_a", int(onemore_data.attribute("challenge_num_a")))
omes_dict.replace_int(
"challenge_num_h", int(onemore_data.attribute("challenge_num_h"))
)
omes_dict.replace_int(
"challenge_num_a", int(onemore_data.attribute("challenge_num_a"))
)
newprofile.replace_dict("omes", omes_dict) newprofile.replace_dict("omes", omes_dict)
# Keep track of play statistics across all mixes # Keep track of play statistics across all mixes

View File

@ -100,28 +100,15 @@ class IIDXSpada(IIDXBase):
return IIDXTricoro(self.data, self.config, self.model) return IIDXTricoro(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert dailies into the DB. Insert dailies into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "daily_charts", "daily"):
cls.game, cls.version, "daily_charts", "daily"
):
# Generate a new list of three dailies. # Generate a new list of three dailies.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = list( all_songs = list(set([song.id for song in data.local.music.get_all_songs(cls.game, cls.version)]))
set(
[
song.id
for song in data.local.music.get_all_songs(
cls.game, cls.version
)
]
)
)
if len(all_songs) >= 3: if len(all_songs) >= 3:
daily_songs = random.sample(all_songs, 3) daily_songs = random.sample(all_songs, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -145,9 +132,7 @@ class IIDXSpada(IIDXBase):
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "daily_charts", "daily")
cls.game, cls.version, "daily_charts", "daily"
)
return events return events
@classmethod @classmethod
@ -345,9 +330,7 @@ class IIDXSpada(IIDXBase):
root = Node.void("IIDX21shop") root = Node.void("IIDX21shop")
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -371,9 +354,7 @@ class IIDXSpada(IIDXBase):
course.replace_int("music_2", request.child_value("music_2")) course.replace_int("music_2", request.child_value("music_2"))
course.replace_int("music_3", request.child_value("music_3")) course.replace_int("music_3", request.child_value("music_3"))
course.replace_bool("valid", request.child_value("valid")) course.replace_bool("valid", request.child_value("valid"))
self.data.local.machine.put_settings( self.data.local.machine.put_settings(machine.arcade, self.game, self.music_version, "shop_course", course)
machine.arcade, self.game, self.music_version, "shop_course", course
)
return root return root
@ -393,9 +374,7 @@ class IIDXSpada(IIDXBase):
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -474,16 +453,7 @@ class IIDXSpada(IIDXBase):
root = Node.void("IIDX21music") root = Node.void("IIDX21music")
attempts = self.get_clear_rates() attempts = self.get_clear_rates()
all_songs = list( all_songs = list(set([song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)]))
set(
[
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
]
)
)
for song in all_songs: for song in all_songs:
clears = [] clears = []
fcs = [] fcs = []
@ -527,16 +497,12 @@ class IIDXSpada(IIDXBase):
continue continue
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
# Grab score data for user/rival # Grab score data for user/rival
scoredata = self.make_score_struct( scoredata = self.make_score_struct(
scores, scores,
self.CLEAR_TYPE_SINGLE self.CLEAR_TYPE_SINGLE if cltype == self.GAME_CLTYPE_SINGLE else self.CLEAR_TYPE_DOUBLE,
if cltype == self.GAME_CLTYPE_SINGLE
else self.CLEAR_TYPE_DOUBLE,
rivalid, rivalid,
) )
for s in scoredata: for s in scoredata:
@ -544,10 +510,7 @@ class IIDXSpada(IIDXBase):
# Grab most played for user/rival # Grab most played for user/rival
most_played = [ most_played = [
play[0] play[0] for play in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)
for play in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
] ]
if len(most_played) < 20: if len(most_played) < 20:
most_played.extend([0] * (20 - len(most_played))) most_played.extend([0] * (20 - len(most_played)))
@ -590,19 +553,13 @@ class IIDXSpada(IIDXBase):
key=lambda s: (s[1].points, s[1].timestamp), key=lambda s: (s[1].points, s[1].timestamp),
reverse=True, reverse=True,
) )
all_players = { all_players = {uid: prof for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])}
uid: prof
for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])
}
if not global_scores: if not global_scores:
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -654,9 +611,7 @@ class IIDXSpada(IIDXBase):
# Shop ranking # Shop ranking
shopdata = Node.void("shopdata") shopdata = Node.void("shopdata")
root.add_child(shopdata) root.add_child(shopdata)
shopdata.set_attribute( shopdata.set_attribute("rank", "-1" if oldindex is None else str(oldindex + 1))
"rank", "-1" if oldindex is None else str(oldindex + 1)
)
# Grab the rank of some other players on this song # Grab the rank of some other players on this song
ranklist = Node.void("ranklist") ranklist = Node.void("ranklist")
@ -680,10 +635,7 @@ class IIDXSpada(IIDXBase):
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -831,9 +783,7 @@ class IIDXSpada(IIDXBase):
if userid is not None: if userid is not None:
# Try to look up previous ghost for user # Try to look up previous ghost for user
my_score = self.data.remote.music.get_score( my_score = self.data.remote.music.get_score(self.game, self.music_version, userid, musicid, chart)
self.game, self.music_version, userid, musicid, chart
)
if my_score is not None: if my_score is not None:
mydata = Node.binary("mydata", my_score.data.get_bytes("ghost")) mydata = Node.binary("mydata", my_score.data.get_bytes("ghost"))
mydata.set_attribute("score", str(my_score.points)) mydata.set_attribute("score", str(my_score.points))
@ -1128,9 +1078,7 @@ class IIDXSpada(IIDXBase):
best_clear_string = clear_map.get(best_clear, "NO PLAY") best_clear_string = clear_map.get(best_clear, "NO PLAY")
now_clear_string = clear_map.get(now_clear, "NO PLAY") now_clear_string = clear_map.get(now_clear, "NO PLAY")
# let's get the song info first # let's get the song info first
song = self.data.local.music.get_song( song = self.data.local.music.get_song(self.game, self.music_version, music_id, self.game_to_db_chart(class_id))
self.game, self.music_version, music_id, self.game_to_db_chart(class_id)
)
notecount = song.data.get("notecount", 0) notecount = song.data.get("notecount", 0)
# Construct the dictionary for the broadcast # Construct the dictionary for the broadcast
card_data = { card_data = {
@ -1235,9 +1183,7 @@ class IIDXSpada(IIDXBase):
join_shop.set_attribute("join_name", machine.name) join_shop.set_attribute("join_name", machine.name)
# Daily recommendations # Daily recommendations
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "dailies")
self.game, self.version, "dailies"
)
if entry is not None: if entry is not None:
packinfo = Node.void("packinfo") packinfo = Node.void("packinfo")
root.add_child(packinfo) root.add_child(packinfo)
@ -1268,15 +1214,9 @@ class IIDXSpada(IIDXBase):
secret.add_child(Node.s64_array("flg2", [-1, -1])) secret.add_child(Node.s64_array("flg2", [-1, -1]))
secret.add_child(Node.s64_array("flg3", [-1, -1])) secret.add_child(Node.s64_array("flg3", [-1, -1]))
else: else:
secret.add_child( secret.add_child(Node.s64_array("flg1", secret_dict.get_int_array("flg1", 2)))
Node.s64_array("flg1", secret_dict.get_int_array("flg1", 2)) secret.add_child(Node.s64_array("flg2", secret_dict.get_int_array("flg2", 2)))
) secret.add_child(Node.s64_array("flg3", secret_dict.get_int_array("flg3", 2)))
secret.add_child(
Node.s64_array("flg2", secret_dict.get_int_array("flg2", 2))
)
secret.add_child(
Node.s64_array("flg3", secret_dict.get_int_array("flg3", 2))
)
# Tran medals and shit # Tran medals and shit
achievements = Node.void("achievements") achievements = Node.void("achievements")
@ -1287,15 +1227,11 @@ class IIDXSpada(IIDXBase):
achievements.set_attribute("pack", "0") achievements.set_attribute("pack", "0")
achievements.set_attribute("pack_comp", "0") achievements.set_attribute("pack_comp", "0")
else: else:
daily_played = self.data.local.user.get_achievement( daily_played = self.data.local.user.get_achievement(self.game, self.version, userid, pack_id, "daily")
self.game, self.version, userid, pack_id, "daily"
)
if daily_played is None: if daily_played is None:
daily_played = ValidatedDict() daily_played = ValidatedDict()
achievements.set_attribute("pack", str(daily_played.get_int("pack_flg"))) achievements.set_attribute("pack", str(daily_played.get_int("pack_flg")))
achievements.set_attribute( achievements.set_attribute("pack_comp", str(daily_played.get_int("pack_comp")))
"pack_comp", str(daily_played.get_int("pack_comp"))
)
# Weeklies # Weeklies
achievements.set_attribute("last_weekly", str(profile.get_int("last_weekly"))) achievements.set_attribute("last_weekly", str(profile.get_int("last_weekly")))
@ -1308,9 +1244,7 @@ class IIDXSpada(IIDXBase):
achievements.set_attribute("rival_crush", str(profile.get_int("rival_crush"))) achievements.set_attribute("rival_crush", str(profile.get_int("rival_crush")))
# Tran medals # Tran medals
achievements.add_child( achievements.add_child(Node.s64_array("trophy", profile.get_int_array("trophy", 10)))
Node.s64_array("trophy", profile.get_int_array("trophy", 10))
)
# User settings # User settings
settings_dict = profile.get_dict("settings") settings_dict = profile.get_dict("settings")
@ -1356,9 +1290,7 @@ class IIDXSpada(IIDXBase):
) )
), ),
) )
rankings = self.data.local.user.get_achievements( rankings = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for rank in rankings: for rank in rankings:
if rank.type == self.DAN_RANKING_SINGLE: if rank.type == self.DAN_RANKING_SINGLE:
grade.add_child( grade.add_child(
@ -1483,9 +1415,7 @@ class IIDXSpada(IIDXBase):
step.add_child( step.add_child(
Node.binary( Node.binary(
"album", "album",
step_dict.get_bytes( step_dict.get_bytes("album", b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
"album", b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
),
) )
) )
@ -1614,13 +1544,9 @@ class IIDXSpada(IIDXBase):
"boss6_damage", "boss6_damage",
]: ]:
boss1.set_attribute(attr, str(boss1_dict.get_int(attr))) boss1.set_attribute(attr, str(boss1_dict.get_int(attr)))
boss1.add_child( boss1.add_child(Node.s32_array("level", boss1_dict.get_int_array("level", 7)))
Node.s32_array("level", boss1_dict.get_int_array("level", 7))
)
if "durability" in boss1_dict: if "durability" in boss1_dict:
boss1.add_child( boss1.add_child(Node.binary("durability", boss1_dict.get_bytes("durability")))
Node.binary("durability", boss1_dict.get_bytes("durability"))
)
# Events copied from Tricoro, but might still allow unlocks in this version? # Events copied from Tricoro, but might still allow unlocks in this version?
gakuen = Node.void("gakuen") gakuen = Node.void("gakuen")
@ -1646,9 +1572,7 @@ class IIDXSpada(IIDXBase):
root.add_child(Node.void("bind_eaappli")) root.add_child(Node.void("bind_eaappli"))
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -1720,15 +1644,9 @@ class IIDXSpada(IIDXBase):
# Basic achievements # Basic achievements
achievements = request.child("achievements") achievements = request.child("achievements")
if achievements is not None: if achievements is not None:
newprofile.replace_int( newprofile.replace_int("visit_flg", int(achievements.attribute("visit_flg")))
"visit_flg", int(achievements.attribute("visit_flg")) newprofile.replace_int("last_weekly", int(achievements.attribute("last_weekly")))
) newprofile.replace_int("weekly_num", int(achievements.attribute("weekly_num")))
newprofile.replace_int(
"last_weekly", int(achievements.attribute("last_weekly"))
)
newprofile.replace_int(
"weekly_num", int(achievements.attribute("weekly_num"))
)
pack_id = int(achievements.attribute("pack_id")) pack_id = int(achievements.attribute("pack_id"))
if pack_id > 0: if pack_id > 0:
@ -1752,9 +1670,7 @@ class IIDXSpada(IIDXBase):
# Deller saving # Deller saving
deller = request.child("deller") deller = request.child("deller")
if deller is not None: if deller is not None:
newprofile.replace_int( newprofile.replace_int("deller", newprofile.get_int("deller") + int(deller.attribute("deller")))
"deller", newprofile.get_int("deller") + int(deller.attribute("deller"))
)
# Favorites saving # Favorites saving
favorite = request.child("favorite") favorite = request.child("favorite")
@ -1769,17 +1685,13 @@ class IIDXSpada(IIDXBase):
for i in range(self.FAVORITE_LIST_LENGTH): for i in range(self.FAVORITE_LIST_LENGTH):
singles.append( singles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", single_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", single_music_bin[(i * 4) : ((i + 1) * 4)]
)[0],
"chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[0], "chart": struct.unpack("B", single_chart_bin[i : (i + 1)])[0],
} }
) )
doubles.append( doubles.append(
{ {
"id": struct.unpack( "id": struct.unpack("<L", double_music_bin[(i * 4) : ((i + 1) * 4)])[0],
"<L", double_music_bin[(i * 4) : ((i + 1) * 4)]
)[0],
"chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[0], "chart": struct.unpack("B", double_chart_bin[i : (i + 1)])[0],
} }
) )

View File

@ -92,28 +92,15 @@ class IIDXTricoro(IIDXBase):
return IIDXLincle(self.data, self.config, self.model) return IIDXLincle(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert dailies into the DB. Insert dailies into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "daily_charts", "daily"):
cls.game, cls.version, "daily_charts", "daily"
):
# Generate a new list of three dailies. # Generate a new list of three dailies.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = list( all_songs = list(set([song.id for song in data.local.music.get_all_songs(cls.game, cls.version)]))
set(
[
song.id
for song in data.local.music.get_all_songs(
cls.game, cls.version
)
]
)
)
if len(all_songs) >= 3: if len(all_songs) >= 3:
daily_songs = random.sample(all_songs, 3) daily_songs = random.sample(all_songs, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -137,9 +124,7 @@ class IIDXTricoro(IIDXBase):
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "daily_charts", "daily")
cls.game, cls.version, "daily_charts", "daily"
)
return events return events
@classmethod @classmethod
@ -324,9 +309,7 @@ class IIDXTricoro(IIDXBase):
root = Node.void("shop") root = Node.void("shop")
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -350,9 +333,7 @@ class IIDXTricoro(IIDXBase):
course.replace_int("music_2", request.child_value("music_2")) course.replace_int("music_2", request.child_value("music_2"))
course.replace_int("music_3", request.child_value("music_3")) course.replace_int("music_3", request.child_value("music_3"))
course.replace_bool("valid", request.child_value("valid")) course.replace_bool("valid", request.child_value("valid"))
self.data.local.machine.put_settings( self.data.local.machine.put_settings(machine.arcade, self.game, self.music_version, "shop_course", course)
machine.arcade, self.game, self.music_version, "shop_course", course
)
return root return root
@ -372,9 +353,7 @@ class IIDXTricoro(IIDXBase):
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
course = self.data.local.machine.get_settings( course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, "shop_course")
machine.arcade, self.game, self.music_version, "shop_course"
)
else: else:
course = None course = None
@ -453,16 +432,7 @@ class IIDXTricoro(IIDXBase):
root = Node.void("music") root = Node.void("music")
attempts = self.get_clear_rates() attempts = self.get_clear_rates()
all_songs = list( all_songs = list(set([song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)]))
set(
[
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
]
)
)
for song in all_songs: for song in all_songs:
clears = [] clears = []
fcs = [] fcs = []
@ -507,16 +477,12 @@ class IIDXTricoro(IIDXBase):
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
# Grab score data for user/rival # Grab score data for user/rival
scoredata = self.make_score_struct( scoredata = self.make_score_struct(
scores, scores,
self.CLEAR_TYPE_SINGLE self.CLEAR_TYPE_SINGLE if cltype == self.GAME_CLTYPE_SINGLE else self.CLEAR_TYPE_DOUBLE,
if cltype == self.GAME_CLTYPE_SINGLE
else self.CLEAR_TYPE_DOUBLE,
rivalid, rivalid,
) )
for s in scoredata: for s in scoredata:
@ -524,10 +490,7 @@ class IIDXTricoro(IIDXBase):
# Grab most played for user/rival # Grab most played for user/rival
most_played = [ most_played = [
play[0] play[0] for play in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)
for play in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
] ]
if len(most_played) < 20: if len(most_played) < 20:
most_played.extend([0] * (20 - len(most_played))) most_played.extend([0] * (20 - len(most_played)))
@ -570,19 +533,13 @@ class IIDXTricoro(IIDXBase):
key=lambda s: (s[1].points, s[1].timestamp), key=lambda s: (s[1].points, s[1].timestamp),
reverse=True, reverse=True,
) )
all_players = { all_players = {uid: prof for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])}
uid: prof
for (uid, prof) in self.get_any_profiles([s[0] for s in all_scores])
}
if not global_scores: if not global_scores:
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -633,9 +590,7 @@ class IIDXTricoro(IIDXBase):
# Shop ranking # Shop ranking
shopdata = Node.void("shopdata") shopdata = Node.void("shopdata")
root.add_child(shopdata) root.add_child(shopdata)
shopdata.set_attribute( shopdata.set_attribute("rank", "-1" if oldindex is None else str(oldindex + 1))
"rank", "-1" if oldindex is None else str(oldindex + 1)
)
# Grab the rank of some other players on this song # Grab the rank of some other players on this song
ranklist = Node.void("ranklist") ranklist = Node.void("ranklist")
@ -659,10 +614,7 @@ class IIDXTricoro(IIDXBase):
all_scores = [ all_scores = [
score score
for score in all_scores for score in all_scores
if ( if (score[0] == userid or self.user_joined_arcade(machine, all_players[score[0]]))
score[0] == userid
or self.user_joined_arcade(machine, all_players[score[0]])
)
] ]
# Find our actual index # Find our actual index
@ -809,9 +761,7 @@ class IIDXTricoro(IIDXBase):
if userid is not None: if userid is not None:
# Try to look up previous ghost for user # Try to look up previous ghost for user
my_score = self.data.remote.music.get_score( my_score = self.data.remote.music.get_score(self.game, self.music_version, userid, musicid, chart)
self.game, self.music_version, userid, musicid, chart
)
if my_score is not None: if my_score is not None:
mydata = Node.binary("mydata", my_score.data.get_bytes("ghost")) mydata = Node.binary("mydata", my_score.data.get_bytes("ghost"))
mydata.set_attribute("score", str(my_score.points)) mydata.set_attribute("score", str(my_score.points))
@ -1114,9 +1064,7 @@ class IIDXTricoro(IIDXBase):
) )
), ),
) )
rankings = self.data.local.user.get_achievements( rankings = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for rank in rankings: for rank in rankings:
if rank.type == self.DAN_RANKING_SINGLE: if rank.type == self.DAN_RANKING_SINGLE:
grade.add_child( grade.add_child(
@ -1274,18 +1222,12 @@ class IIDXTricoro(IIDXBase):
step.set_attribute("dp_mplay", str(step_dict.get_int("dp_mplay"))) step.set_attribute("dp_mplay", str(step_dict.get_int("dp_mplay")))
step.set_attribute("review", str(step_dict.get_int("review"))) step.set_attribute("review", str(step_dict.get_int("review")))
if "stamp" in step_dict: if "stamp" in step_dict:
step.add_child( step.add_child(Node.binary("stamp", step_dict.get_bytes("stamp", bytes([0] * 36))))
Node.binary("stamp", step_dict.get_bytes("stamp", bytes([0] * 36)))
)
if "help" in step_dict: if "help" in step_dict:
step.add_child( step.add_child(Node.binary("help", step_dict.get_bytes("help", bytes([0] * 6))))
Node.binary("help", step_dict.get_bytes("help", bytes([0] * 6)))
)
# Daily recommendations # Daily recommendations
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "dailies")
self.game, self.version, "dailies"
)
if entry is not None: if entry is not None:
packinfo = Node.void("packinfo") packinfo = Node.void("packinfo")
root.add_child(packinfo) root.add_child(packinfo)
@ -1328,15 +1270,11 @@ class IIDXTricoro(IIDXBase):
achievements.set_attribute("pack", "0") achievements.set_attribute("pack", "0")
achievements.set_attribute("pack_comp", "0") achievements.set_attribute("pack_comp", "0")
else: else:
daily_played = self.data.local.user.get_achievement( daily_played = self.data.local.user.get_achievement(self.game, self.version, userid, pack_id, "daily")
self.game, self.version, userid, pack_id, "daily"
)
if daily_played is None: if daily_played is None:
daily_played = ValidatedDict() daily_played = ValidatedDict()
achievements.set_attribute("pack", str(daily_played.get_int("pack_flg"))) achievements.set_attribute("pack", str(daily_played.get_int("pack_flg")))
achievements.set_attribute( achievements.set_attribute("pack_comp", str(daily_played.get_int("pack_comp")))
"pack_comp", str(daily_played.get_int("pack_comp"))
)
# Weeklies # Weeklies
achievements.set_attribute("last_weekly", str(profile.get_int("last_weekly"))) achievements.set_attribute("last_weekly", str(profile.get_int("last_weekly")))
@ -1349,9 +1287,7 @@ class IIDXTricoro(IIDXBase):
achievements.set_attribute("rival_crush", str(profile.get_int("rival_crush"))) achievements.set_attribute("rival_crush", str(profile.get_int("rival_crush")))
# Tran medals # Tran medals
achievements.add_child( achievements.add_child(Node.s64_array("trophy", profile.get_int_array("trophy", 10)))
Node.s64_array("trophy", profile.get_int_array("trophy", 10))
)
# Link5 data # Link5 data
if "link5" in profile: if "link5" in profile:
@ -1403,9 +1339,7 @@ class IIDXTricoro(IIDXBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid) play_stats = self.get_play_statistics(userid)
@ -1459,15 +1393,9 @@ class IIDXTricoro(IIDXBase):
# Basic achievements # Basic achievements
achievements = request.child("achievements") achievements = request.child("achievements")
if achievements is not None: if achievements is not None:
newprofile.replace_int( newprofile.replace_int("visit_flg", int(achievements.attribute("visit_flg")))
"visit_flg", int(achievements.attribute("visit_flg")) newprofile.replace_int("last_weekly", int(achievements.attribute("last_weekly")))
) newprofile.replace_int("weekly_num", int(achievements.attribute("weekly_num")))
newprofile.replace_int(
"last_weekly", int(achievements.attribute("last_weekly"))
)
newprofile.replace_int(
"weekly_num", int(achievements.attribute("weekly_num"))
)
pack_id = int(achievements.attribute("pack_id")) pack_id = int(achievements.attribute("pack_id"))
if pack_id > 0: if pack_id > 0:

View File

@ -30,13 +30,9 @@ class JubeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
PLAY_MEDAL_FAILED: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_FAILED PLAY_MEDAL_FAILED: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_FAILED
PLAY_MEDAL_CLEARED: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_CLEARED PLAY_MEDAL_CLEARED: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_CLEARED
PLAY_MEDAL_NEARLY_FULL_COMBO: Final[ PLAY_MEDAL_NEARLY_FULL_COMBO: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_FULL_COMBO
int
] = DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_FULL_COMBO
PLAY_MEDAL_FULL_COMBO: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_FULL_COMBO PLAY_MEDAL_FULL_COMBO: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_FULL_COMBO
PLAY_MEDAL_NEARLY_EXCELLENT: Final[ PLAY_MEDAL_NEARLY_EXCELLENT: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_EXCELLENT
int
] = DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_EXCELLENT
PLAY_MEDAL_EXCELLENT: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT PLAY_MEDAL_EXCELLENT: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT
CHART_TYPE_BASIC: Final[int] = 0 CHART_TYPE_BASIC: Final[int] = 0
@ -86,18 +82,14 @@ class JubeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
return Node.void("gametop") return Node.void("gametop")
def format_scores( def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
self, userid: UserID, profile: Profile, scores: List[Score]
) -> Node:
""" """
Base handler for a score list. Given a userid, profile and a score list, Base handler for a score list. Given a userid, profile and a score list,
return a Node representing a score list. Should be overridden. return a Node representing a score list. Should be overridden.
""" """
return Node.void("gametop") return Node.void("gametop")
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
""" """
Base handler for profile parsing. Given a request and an old profile, Base handler for profile parsing. Given a request and an old profile,
return a new profile that's been updated with the contents of the request. return a new profile that's been updated with the contents of the request.
@ -159,9 +151,7 @@ class JubeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
return self.format_profile(userid, profile) return self.format_profile(userid, profile)
def get_scores_by_extid( def get_scores_by_extid(self, extid: Optional[int], partition: int, total_partitions: int) -> Optional[Node]:
self, extid: Optional[int], partition: int, total_partitions: int
) -> Optional[Node]:
""" """
Given an ExtID, return a formatted score node. Similar rationale to Given an ExtID, return a formatted score node. Similar rationale to
get_profile_by_refid. Note that this takes into account the game's get_profile_by_refid. Note that this takes into account the game's
@ -183,9 +173,7 @@ class JubeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# We fetch all scores on the first partition and then divy up # We fetch all scores on the first partition and then divy up
# the scores across total_partitions fetches. If it is small # the scores across total_partitions fetches. If it is small
# enough, we don't bother. # enough, we don't bother.
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
else: else:
# We will want to fetch the remaining scores that were in our # We will want to fetch the remaining scores that were in our
# cache. # cache.
@ -205,9 +193,7 @@ class JubeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# last iteration. # last iteration.
if partition == total_partitions: if partition == total_partitions:
if rest: if rest:
raise Exception( raise Exception("Logic error, should not have gotten additional scores to cache on last iteration!")
"Logic error, should not have gotten additional scores to cache on last iteration!"
)
self.cache.delete(cache_key) self.cache.delete(cache_key)
else: else:
self.cache.set(cache_key, rest, timeout=60) self.cache.set(cache_key, rest, timeout=60)
@ -339,10 +325,7 @@ class JubeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
for gameitem in gameitems: for gameitem in gameitems:
if gameitem.type == "emblem": if gameitem.type == "emblem":
if ( if gameitem.data.get_int("layer") == 2 and gameitem.data.get_int("rarity") == 1:
gameitem.data.get_int("layer") == 2
and gameitem.data.get_int("rarity") == 1
):
default_main.add(gameitem.id) default_main.add(gameitem.id)
return default_main return default_main

View File

@ -83,16 +83,12 @@ class JubeatClan(
return JubeatQubell(self.data, self.config, self.model) return JubeatQubell(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert daily FC challenges into the DB. Insert daily FC challenges into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "fc_challenge", "daily"):
cls.game, cls.version, "fc_challenge", "daily"
):
# Generate a new list of two FC challenge songs. Skip a particular song range since these are all a single song ID. # Generate a new list of two FC challenge songs. Skip a particular song range since these are all a single song ID.
# Jubeat Clan has an unlock event where you have to play different charts for the same song, and the charts are # Jubeat Clan has an unlock event where you have to play different charts for the same song, and the charts are
# loaded in based on the cabinet's prefecture. So, no matter where you are, you will only see one song within this # loaded in based on the cabinet's prefecture. So, no matter where you are, you will only see one song within this
@ -129,9 +125,7 @@ class JubeatClan(
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "fc_challenge", "daily")
cls.game, cls.version, "fc_challenge", "daily"
)
return events return events
@classmethod @classmethod
@ -1098,36 +1092,21 @@ class JubeatClan(
valid_courses: Set[int] = set() valid_courses: Set[int] = set()
for course in self.__get_course_list(): for course in self.__get_course_list():
if course["id"] < 1: if course["id"] < 1:
raise Exception( raise Exception(f"Invalid course ID {course['id']} found in course list!")
f"Invalid course ID {course['id']} found in course list!"
)
if course["id"] in valid_courses: if course["id"] in valid_courses:
raise Exception(f"Duplicate ID {course['id']} found in course list!") raise Exception(f"Duplicate ID {course['id']} found in course list!")
if ( if course["clear_type"] == self.COURSE_CLEAR_HAZARD and "hazard_type" not in course:
course["clear_type"] == self.COURSE_CLEAR_HAZARD
and "hazard_type" not in course
):
raise Exception(f"Need 'hazard_type' set in course {course['id']}!") raise Exception(f"Need 'hazard_type' set in course {course['id']}!")
if ( if course["course_type"] == self.COURSE_TYPE_TIME_BASED and "end_time" not in course:
course["course_type"] == self.COURSE_TYPE_TIME_BASED
and "end_time" not in course
):
raise Exception(f"Need 'end_time' set in course {course['id']}!") raise Exception(f"Need 'end_time' set in course {course['id']}!")
if ( if (
course["clear_type"] course["clear_type"] in [self.COURSE_CLEAR_SCORE, self.COURSE_CLEAR_COMBINED_SCORE]
in [self.COURSE_CLEAR_SCORE, self.COURSE_CLEAR_COMBINED_SCORE]
and "score" not in course and "score" not in course
): ):
raise Exception(f"Need 'score' set in course {course['id']}!") raise Exception(f"Need 'score' set in course {course['id']}!")
if ( if course["clear_type"] == self.COURSE_CLEAR_SCORE and course["score"] > 1000000:
course["clear_type"] == self.COURSE_CLEAR_SCORE
and course["score"] > 1000000
):
raise Exception(f"Invalid per-coure score in course {course['id']}!") raise Exception(f"Invalid per-coure score in course {course['id']}!")
if ( if course["clear_type"] == self.COURSE_CLEAR_COMBINED_SCORE and course["score"] <= 1000000:
course["clear_type"] == self.COURSE_CLEAR_COMBINED_SCORE
and course["score"] <= 1000000
):
raise Exception(f"Invalid combined score in course {course['id']}!") raise Exception(f"Invalid combined score in course {course['id']}!")
valid_courses.add(course["id"]) valid_courses.add(course["id"])
@ -1139,11 +1118,7 @@ class JubeatClan(
clan_course.set_attribute("id", str(course["id"])) clan_course.set_attribute("id", str(course["id"]))
clan_course.set_attribute("course_type", str(course["course_type"])) clan_course.set_attribute("course_type", str(course["course_type"]))
clan_course.add_child(Node.s32("difficulty", course["difficulty"])) clan_course.add_child(Node.s32("difficulty", course["difficulty"]))
clan_course.add_child( clan_course.add_child(Node.u64("etime", (course["end_time"] if "end_time" in course else 0) * 1000))
Node.u64(
"etime", (course["end_time"] if "end_time" in course else 0) * 1000
)
)
clan_course.add_child(Node.string("name", course["name"])) clan_course.add_child(Node.string("name", course["name"]))
# List of included songs # List of included songs
@ -1169,9 +1144,7 @@ class JubeatClan(
clan_course.add_child(clear) clan_course.add_child(clear)
ex_option = Node.void("ex_option") ex_option = Node.void("ex_option")
clear.add_child(ex_option) clear.add_child(ex_option)
ex_option.add_child( ex_option.add_child(Node.bool("is_hard", course["hard"] if "hard" in course else False))
Node.bool("is_hard", course["hard"] if "hard" in course else False)
)
ex_option.add_child( ex_option.add_child(
Node.s32( Node.s32(
"hazard_type", "hazard_type",
@ -1179,9 +1152,7 @@ class JubeatClan(
) )
) )
clear.set_attribute("type", str(course["clear_type"])) clear.set_attribute("type", str(course["clear_type"]))
clear.add_child( clear.add_child(Node.s32("score", course["score"] if "score" in course else 0))
Node.s32("score", course["score"] if "score" in course else 0)
)
reward_list = Node.void("reward_list") reward_list = Node.void("reward_list")
clear.add_child(reward_list) clear.add_child(reward_list)
@ -1404,9 +1375,7 @@ class JubeatClan(
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
owned_emblems = self.calculate_owned_items( owned_emblems = self.calculate_owned_items(item.child_value("emblem_list"))
item.child_value("emblem_list")
)
for index in owned_emblems: for index in owned_emblems:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -1443,9 +1412,7 @@ class JubeatClan(
return Node.void("gameend") return Node.void("gameend")
def format_scores( def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
self, userid: UserID, profile: Profile, scores: List[Score]
) -> Node:
root = Node.void("gametop") root = Node.void("gametop")
datanode = Node.void("data") datanode = Node.void("data")
root.add_child(datanode) root.add_child(datanode)
@ -1518,24 +1485,12 @@ class JubeatClan(
playdata.add_child(musicdata) playdata.add_child(musicdata)
musicdata.set_attribute("music_id", scoreid) musicdata.set_attribute("music_id", scoreid)
musicdata.add_child( musicdata.add_child(Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)))
Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)) musicdata.add_child(Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)))
) musicdata.add_child(Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3)))
musicdata.add_child( musicdata.add_child(Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3)))
Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)) musicdata.add_child(Node.s32_array("score", scoredata.get_int_array("points", 3)))
) musicdata.add_child(Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3)))
musicdata.add_child(
Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3))
)
musicdata.add_child(
Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3))
)
musicdata.add_child(
Node.s32_array("score", scoredata.get_int_array("points", 3))
)
musicdata.add_child(
Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3))
)
for i, ghost in enumerate(scoredata.get("ghost", [None, None, None])): for i, ghost in enumerate(scoredata.get("ghost", [None, None, None])):
if ghost is None: if ghost is None:
@ -1557,9 +1512,7 @@ class JubeatClan(
force_unlock = game_config.get_bool("force_song_unlock") force_unlock = game_config.get_bool("force_song_unlock")
# Calculate all of our achievement-backed entities. # Calculate all of our achievement-backed entities.
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
owned_songs: Set[int] = set() owned_songs: Set[int] = set()
owned_secrets: Set[int] = set() owned_secrets: Set[int] = set()
event_completion: Dict[int, bool] = {} event_completion: Dict[int, bool] = {}
@ -1567,9 +1520,7 @@ class JubeatClan(
owned_emblems: Set[int] = set() owned_emblems: Set[int] = set()
for achievement in achievements: for achievement in achievements:
if achievement.type == "event": if achievement.type == "event":
event_completion[achievement.id] = achievement.data.get_bool( event_completion[achievement.id] = achievement.data.get_bool("is_completed")
"is_completed"
)
elif achievement.type == "course": elif achievement.type == "course":
course_completion[achievement.id] = achievement.data course_completion[achievement.id] = achievement.data
elif achievement.type == "emblem": elif achievement.type == "emblem":
@ -1610,12 +1561,8 @@ class JubeatClan(
info.add_child(Node.s32("match_cnt", profile.get_int("match_cnt"))) info.add_child(Node.s32("match_cnt", profile.get_int("match_cnt")))
info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt"))) info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt")))
info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt"))) info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt")))
info.add_child( info.add_child(Node.s32("bonus_tune_points", profile.get_int("bonus_tune_points")))
Node.s32("bonus_tune_points", profile.get_int("bonus_tune_points")) info.add_child(Node.bool("is_bonus_tune_played", profile.get_bool("is_bonus_tune_played")))
)
info.add_child(
Node.bool("is_bonus_tune_played", profile.get_bool("is_bonus_tune_played"))
)
# Looks to be set to true when there's an old profile, stops tutorial from # Looks to be set to true when there's an old profile, stops tutorial from
# happening on first load. # happening on first load.
@ -1665,68 +1612,30 @@ class JubeatClan(
# Secret unlocks # Secret unlocks
item = Node.void("item") item = Node.void("item")
player.add_child(item) player.add_child(item)
item.add_child( item.add_child(Node.s32_array("music_list", profile.get_int_array("music_list", 64, [-1] * 64)))
Node.s32_array(
"music_list", profile.get_int_array("music_list", 64, [-1] * 64)
)
)
item.add_child( item.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 64) ([-1] * 64) if force_unlock else self.create_owned_items(owned_songs, 64),
if force_unlock
else self.create_owned_items(owned_songs, 64),
)
)
item.add_child(
Node.s32_array(
"theme_list", profile.get_int_array("theme_list", 16, [-1] * 16)
)
)
item.add_child(
Node.s32_array(
"marker_list", profile.get_int_array("marker_list", 16, [-1] * 16)
)
)
item.add_child(
Node.s32_array(
"title_list", profile.get_int_array("title_list", 160, [-1] * 160)
)
)
item.add_child(
Node.s32_array(
"parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)
)
)
item.add_child(
Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96))
)
item.add_child(
Node.s32_array(
"commu_list", profile.get_int_array("commu_list", 16, [-1] * 16)
) )
) )
item.add_child(Node.s32_array("theme_list", profile.get_int_array("theme_list", 16, [-1] * 16)))
item.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list", 16, [-1] * 16)))
item.add_child(Node.s32_array("title_list", profile.get_int_array("title_list", 160, [-1] * 160)))
item.add_child(Node.s32_array("parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)))
item.add_child(Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96)))
item.add_child(Node.s32_array("commu_list", profile.get_int_array("commu_list", 16, [-1] * 16)))
new = Node.void("new") new = Node.void("new")
item.add_child(new) item.add_child(new)
new.add_child( new.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 64) ([-1] * 64) if force_unlock else self.create_owned_items(owned_secrets, 64),
if force_unlock
else self.create_owned_items(owned_secrets, 64),
)
)
new.add_child(
Node.s32_array(
"theme_list", profile.get_int_array("theme_list_new", 16, [-1] * 16)
)
)
new.add_child(
Node.s32_array(
"marker_list", profile.get_int_array("marker_list_new", 16, [-1] * 16)
) )
) )
new.add_child(Node.s32_array("theme_list", profile.get_int_array("theme_list_new", 16, [-1] * 16)))
new.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list_new", 16, [-1] * 16)))
# Add rivals to profile. # Add rivals to profile.
rivallist = Node.void("rivallist") rivallist = Node.void("rivallist")
@ -1765,9 +1674,7 @@ class JubeatClan(
lab_edit_seq.set_attribute("count", "0") lab_edit_seq.set_attribute("count", "0")
# Full combo challenge # Full combo challenge
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "fc_challenge")
self.game, self.version, "fc_challenge"
)
if entry is None: if entry is None:
entry = ValidatedDict() entry = ValidatedDict()
@ -1826,11 +1733,7 @@ class JubeatClan(
state = 0x0 state = 0x0
state |= self.EVENT_STATUS_OPEN if eventdata["enabled"] else 0 state |= self.EVENT_STATUS_OPEN if eventdata["enabled"] else 0
state |= ( state |= self.EVENT_STATUS_COMPLETE if event_completion.get(eventid, False) else 0
self.EVENT_STATUS_COMPLETE
if event_completion.get(eventid, False)
else 0
)
event.add_child(Node.u8("state", state)) event.add_child(Node.u8("state", state))
# JBox stuff # JBox stuff
@ -1900,9 +1803,7 @@ class JubeatClan(
bestentry.replace_int("songid", achievement.id) bestentry.replace_int("songid", achievement.id)
bestentry.replace_int("chart", chart) bestentry.replace_int("chart", chart)
jubeat_entries.append(bestentry) jubeat_entries.append(bestentry)
jubeat_entries = sorted( jubeat_entries = sorted(jubeat_entries, key=lambda entry: entry.get_int("value"), reverse=True)
jubeat_entries, key=lambda entry: entry.get_int("value"), reverse=True
)
# Now, give the game the list. # Now, give the game the list.
for i, entry in enumerate(jubeat_entries): for i, entry in enumerate(jubeat_entries):
@ -1916,9 +1817,7 @@ class JubeatClan(
target_music.add_child(Node.s8("seq", entry.get_int("chart"))) target_music.add_child(Node.s8("seq", entry.get_int("chart")))
target_music.add_child(Node.s32("score", entry.get_int("score"))) target_music.add_child(Node.s32("score", entry.get_int("score")))
target_music.add_child(Node.s32("value", entry.get_int("value"))) target_music.add_child(Node.s32("value", entry.get_int("value")))
target_music.add_child( target_music.add_child(Node.bool("is_hard_mode", entry.get_bool("hard_mode")))
Node.bool("is_hard_mode", entry.get_bool("hard_mode"))
)
# Team stuff # Team stuff
team = Node.void("team") team = Node.void("team")
@ -1964,9 +1863,7 @@ class JubeatClan(
status = 0 status = 0
status |= self.COURSE_STATUS_SEEN if status_dict.get_bool("seen") else 0 status |= self.COURSE_STATUS_SEEN if status_dict.get_bool("seen") else 0
status |= self.COURSE_STATUS_PLAYED if status_dict.get_bool("played") else 0 status |= self.COURSE_STATUS_PLAYED if status_dict.get_bool("played") else 0
status |= ( status |= self.COURSE_STATUS_CLEARED if status_dict.get_bool("cleared") else 0
self.COURSE_STATUS_CLEARED if status_dict.get_bool("cleared") else 0
)
clan_course = Node.void("clan_course") clan_course = Node.void("clan_course")
clan_course_list.add_child(clan_course) clan_course_list.add_child(clan_course)
@ -2051,9 +1948,7 @@ class JubeatClan(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
newprofile.replace_bool("saved", True) newprofile.replace_bool("saved", True)
data = request.child("data") data = request.child("data")
@ -2092,12 +1987,8 @@ class JubeatClan(
newprofile.replace_int("beat_cnt", info.child_value("beat_cnt")) newprofile.replace_int("beat_cnt", info.child_value("beat_cnt"))
newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt")) newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt"))
newprofile.replace_int( newprofile.replace_int("bonus_tune_points", info.child_value("bonus_tune_points"))
"bonus_tune_points", info.child_value("bonus_tune_points") newprofile.replace_bool("is_bonus_tune_played", info.child_value("is_bonus_tune_played"))
)
newprofile.replace_bool(
"is_bonus_tune_played", info.child_value("is_bonus_tune_played")
)
# Grab last settings # Grab last settings
lastnode = player.child("last") lastnode = player.child("last")
@ -2122,30 +2013,16 @@ class JubeatClan(
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
newprofile.replace_int_array( newprofile.replace_int_array("music_list", 64, item.child_value("music_list"))
"music_list", 64, item.child_value("music_list") newprofile.replace_int_array("theme_list", 16, item.child_value("theme_list"))
) newprofile.replace_int_array("marker_list", 16, item.child_value("marker_list"))
newprofile.replace_int_array( newprofile.replace_int_array("title_list", 160, item.child_value("title_list"))
"theme_list", 16, item.child_value("theme_list") newprofile.replace_int_array("parts_list", 160, item.child_value("parts_list"))
) newprofile.replace_int_array("commu_list", 16, item.child_value("commu_list"))
newprofile.replace_int_array(
"marker_list", 16, item.child_value("marker_list")
)
newprofile.replace_int_array(
"title_list", 160, item.child_value("title_list")
)
newprofile.replace_int_array(
"parts_list", 160, item.child_value("parts_list")
)
newprofile.replace_int_array(
"commu_list", 16, item.child_value("commu_list")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_songs = self.calculate_owned_items( owned_songs = self.calculate_owned_items(item.child_value("secret_list"))
item.child_value("secret_list")
)
for index in owned_songs: for index in owned_songs:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -2169,18 +2046,12 @@ class JubeatClan(
newitem = item.child("new") newitem = item.child("new")
if newitem is not None: if newitem is not None:
newprofile.replace_int_array( newprofile.replace_int_array("theme_list_new", 16, newitem.child_value("theme_list"))
"theme_list_new", 16, newitem.child_value("theme_list") newprofile.replace_int_array("marker_list_new", 16, newitem.child_value("marker_list"))
)
newprofile.replace_int_array(
"marker_list_new", 16, newitem.child_value("marker_list")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_secrets = self.calculate_owned_items( owned_secrets = self.calculate_owned_items(newitem.child_value("secret_list"))
newitem.child_value("secret_list")
)
for index in owned_secrets: for index in owned_secrets:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -2375,9 +2246,7 @@ class JubeatClan(
if flags & bit > 0: if flags & bit > 0:
medal = max(medal, mapping[bit]) medal = max(medal, mapping[bit])
self.update_score( self.update_score(userid, timestamp, songid, chart, points, medal, combo, ghost, stats)
userid, timestamp, songid, chart, points, medal, combo, ghost, stats
)
# Born stuff # Born stuff
born = player.child("born") born = player.child("born")
@ -2458,9 +2327,7 @@ class JubeatClan(
oldcourse = ValidatedDict() oldcourse = ValidatedDict()
oldcourse.replace_bool("seen", oldcourse.get_bool("seen") or is_seen) oldcourse.replace_bool("seen", oldcourse.get_bool("seen") or is_seen)
oldcourse.replace_bool( oldcourse.replace_bool("played", oldcourse.get_bool("played") or is_played)
"played", oldcourse.get_bool("played") or is_played
)
# Save it as an achievement # Save it as an achievement
self.data.local.user.put_achievement( self.data.local.user.put_achievement(

View File

@ -143,22 +143,15 @@ class JubeatFesto(
}[db_chart] }[db_chart]
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert daily FC challenges into the DB. Insert daily FC challenges into the DB.
""" """
events: List[Tuple[str, Dict[str, Any]]] = [] events: List[Tuple[str, Dict[str, Any]]] = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "fc_challenge", "daily"):
cls.game, cls.version, "fc_challenge", "daily"
):
# Generate a new list of two FC challenge songs. # Generate a new list of two FC challenge songs.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = set( all_songs = set(song.id for song in data.local.music.get_all_songs(cls.game, cls.version))
song.id
for song in data.local.music.get_all_songs(cls.game, cls.version)
)
if len(all_songs) >= 2: if len(all_songs) >= 2:
daily_songs = random.sample(all_songs, 2) daily_songs = random.sample(all_songs, 2)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -184,12 +177,8 @@ class JubeatFesto(
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "fc_challenge", "daily")
cls.game, cls.version, "fc_challenge", "daily" if data.local.network.should_schedule(cls.game, cls.version, "random_course", "daily"):
)
if data.local.network.should_schedule(
cls.game, cls.version, "random_course", "daily"
):
# Generate a new list of three random songs for random course mode. # Generate a new list of three random songs for random course mode.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
@ -216,11 +205,7 @@ class JubeatFesto(
cls.CHART_TYPE_HARD_EXTREME: cls.CHART_TYPE_EXTREME, cls.CHART_TYPE_HARD_EXTREME: cls.CHART_TYPE_EXTREME,
}[chart] }[chart]
all_tens = [ all_tens = [song for song in data.local.music.get_all_songs(cls.game, cls.version) if is_ten(song)]
song
for song in data.local.music.get_all_songs(cls.game, cls.version)
if is_ten(song)
]
if len(all_tens) >= 3: if len(all_tens) >= 3:
course_songs = random.sample(all_tens, 3) course_songs = random.sample(all_tens, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -266,9 +251,7 @@ class JubeatFesto(
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "random_course", "daily")
cls.game, cls.version, "random_course", "daily"
)
return events return events
@classmethod @classmethod
@ -324,9 +307,7 @@ class JubeatFesto(
# If it is available, then grab the random course. If we haven't generated that course, then # If it is available, then grab the random course. If we haven't generated that course, then
# just don't bother trying to create it. # just don't bother trying to create it.
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "random_course")
self.game, self.version, "random_course"
)
random_course: List[Dict[str, Any]] = [] random_course: List[Dict[str, Any]] = []
if entry is not None: if entry is not None:
@ -521,9 +502,7 @@ class JubeatFesto(
"music": [ "music": [
[ [
( (
70000057 70000057 if dataver < 2019062100 else (90000079 if dataver < 2022021600 else 20000031),
if dataver < 2019062100
else (90000079 if dataver < 2022021600 else 20000031),
0, 0,
), ),
(60000100, 0), (60000100, 0),
@ -543,9 +522,7 @@ class JubeatFesto(
"music": [ "music": [
[ [
( (
80000020 80000020 if dataver < 2019062100 else (90000082 if dataver < 2022021600 else 60000092),
if dataver < 2019062100
else (90000082 if dataver < 2022021600 else 60000092),
0, 0,
), ),
(90000031, 0), (90000031, 0),
@ -556,9 +533,7 @@ class JubeatFesto(
80000034 80000034
if dataver < 2020062900 if dataver < 2020062900
else ( else (
30000108 30000108 if dataver < 2020091300 else (40000107 if dataver < 2021020100 else 30000004)
if dataver < 2020091300
else (40000107 if dataver < 2021020100 else 30000004)
), ),
0, 0,
), ),
@ -579,9 +554,7 @@ class JubeatFesto(
"music": [ "music": [
[ [
( (
70000148 70000148 if dataver < 2020021900 else (90000040 if dataver < 2021081600 else 80000097),
if dataver < 2020021900
else (90000040 if dataver < 2021081600 else 80000097),
0, 0,
), ),
(50000296 if dataver < 2021081600 else 90000029, 0), (50000296 if dataver < 2021081600 else 90000029, 0),
@ -665,9 +638,7 @@ class JubeatFesto(
[ [
(50000242, 0), (50000242, 0),
( (
80000034 80000034 if dataver < 2020063000 else (90000079 if dataver < 2022021600 else 50000277),
if dataver < 2020063000
else (90000079 if dataver < 2022021600 else 50000277),
1, 1,
), ),
(90000037 if dataver < 2021081600 else 50000294, 1), (90000037 if dataver < 2021081600 else 50000294, 1),
@ -675,9 +646,7 @@ class JubeatFesto(
[(50000260, 1), (50000261, 1)], [(50000260, 1), (50000261, 1)],
[ [
( (
70000085 70000085 if dataver < 2019062100 else (90000081 if dataver < 2022021600 else 90000143),
if dataver < 2019062100
else (90000081 if dataver < 2022021600 else 90000143),
1, 1,
), ),
], ],
@ -695,9 +664,7 @@ class JubeatFesto(
(20000111 if dataver < 2019062100 else 90000034, 1), (20000111 if dataver < 2019062100 else 90000034, 1),
(90000037 if dataver < 2021081600 else 90000107, 1), (90000037 if dataver < 2021081600 else 90000107, 1),
( (
70000131 70000131 if dataver < 2019111800 else (90000042 if dataver < 2021081600 else 90000140),
if dataver < 2019111800
else (90000042 if dataver < 2021081600 else 90000140),
1, 1,
), ),
], ],
@ -1753,9 +1720,7 @@ class JubeatFesto(
game_config = self.get_game_config() game_config = self.get_game_config()
konami_logo_50th = Node.void("konami_logo_50th") konami_logo_50th = Node.void("konami_logo_50th")
info.add_child(konami_logo_50th) info.add_child(konami_logo_50th)
konami_logo_50th.add_child( konami_logo_50th.add_child(Node.bool("is_available", game_config.get_bool("50th_anniversary")))
Node.bool("is_available", game_config.get_bool("50th_anniversary"))
)
expert_option = Node.void("expert_option") expert_option = Node.void("expert_option")
info.add_child(expert_option) info.add_child(expert_option)
@ -1780,36 +1745,21 @@ class JubeatFesto(
dataver = self.model.version or 2022052400 dataver = self.model.version or 2022052400
for course in self.__get_course_list(): for course in self.__get_course_list():
if course["id"] < 1: if course["id"] < 1:
raise Exception( raise Exception(f"Invalid course ID {course['id']} found in course list!")
f"Invalid course ID {course['id']} found in course list!"
)
if course["id"] in valid_courses: if course["id"] in valid_courses:
raise Exception(f"Duplicate ID {course['id']} found in course list!") raise Exception(f"Duplicate ID {course['id']} found in course list!")
if ( if course["clear_type"] == self.COURSE_CLEAR_HAZARD and "hazard_type" not in course:
course["clear_type"] == self.COURSE_CLEAR_HAZARD
and "hazard_type" not in course
):
raise Exception(f"Need 'hazard_type' set in course {course['id']}!") raise Exception(f"Need 'hazard_type' set in course {course['id']}!")
if ( if course["course_type"] == self.COURSE_TYPE_TIME_BASED and "end_time" not in course:
course["course_type"] == self.COURSE_TYPE_TIME_BASED
and "end_time" not in course
):
raise Exception(f"Need 'end_time' set in course {course['id']}!") raise Exception(f"Need 'end_time' set in course {course['id']}!")
if ( if (
course["clear_type"] course["clear_type"] in [self.COURSE_CLEAR_SCORE, self.COURSE_CLEAR_COMBINED_SCORE]
in [self.COURSE_CLEAR_SCORE, self.COURSE_CLEAR_COMBINED_SCORE]
and "score" not in course and "score" not in course
): ):
raise Exception(f"Need 'score' set in course {course['id']}!") raise Exception(f"Need 'score' set in course {course['id']}!")
if ( if course["clear_type"] == self.COURSE_CLEAR_SCORE and course["score"] > 1000000:
course["clear_type"] == self.COURSE_CLEAR_SCORE
and course["score"] > 1000000
):
raise Exception(f"Invalid per-coure score in course {course['id']}!") raise Exception(f"Invalid per-coure score in course {course['id']}!")
if ( if course["clear_type"] == self.COURSE_CLEAR_COMBINED_SCORE and course["score"] <= 1000000:
course["clear_type"] == self.COURSE_CLEAR_COMBINED_SCORE
and course["score"] <= 1000000
):
raise Exception(f"Invalid combined score in course {course['id']}!") raise Exception(f"Invalid combined score in course {course['id']}!")
valid_courses.add(course["id"]) valid_courses.add(course["id"])
@ -1821,11 +1771,7 @@ class JubeatFesto(
clan_course.set_attribute("id", str(course["id"])) clan_course.set_attribute("id", str(course["id"]))
clan_course.set_attribute("course_type", str(course["course_type"])) clan_course.set_attribute("course_type", str(course["course_type"]))
clan_course.add_child(Node.s32("difficulty", course["difficulty"])) clan_course.add_child(Node.s32("difficulty", course["difficulty"]))
clan_course.add_child( clan_course.add_child(Node.u64("etime", (course["end_time"] if "end_time" in course else 0) * 1000))
Node.u64(
"etime", (course["end_time"] if "end_time" in course else 0) * 1000
)
)
clan_course.add_child(Node.string("name", course["name"])) clan_course.add_child(Node.string("name", course["name"]))
# List of included songs # List of included songs
@ -1851,9 +1797,7 @@ class JubeatFesto(
clan_course.add_child(clear) clan_course.add_child(clear)
ex_option = Node.void("ex_option") ex_option = Node.void("ex_option")
clear.add_child(ex_option) clear.add_child(ex_option)
ex_option.add_child( ex_option.add_child(Node.bool("is_hard", course["hard"] if "hard" in course else False))
Node.bool("is_hard", course["hard"] if "hard" in course else False)
)
ex_option.add_child( ex_option.add_child(
Node.s32( Node.s32(
"hazard_type", "hazard_type",
@ -1861,9 +1805,7 @@ class JubeatFesto(
) )
) )
clear.set_attribute("type", str(course["clear_type"])) clear.set_attribute("type", str(course["clear_type"]))
clear.add_child( clear.add_child(Node.s32("score", course["score"] if "score" in course else 0))
Node.s32("score", course["score"] if "score" in course else 0)
)
reward_list = Node.void("reward_list") reward_list = Node.void("reward_list")
clear.add_child(reward_list) clear.add_child(reward_list)
@ -1965,9 +1907,7 @@ class JubeatFesto(
if game_config.get_bool("festo_dungeon"): if game_config.get_bool("festo_dungeon"):
festo_dungeon = Node.void("festo_dungeon") festo_dungeon = Node.void("festo_dungeon")
info.add_child(festo_dungeon) info.add_child(festo_dungeon)
festo_dungeon.add_child( festo_dungeon.add_child(Node.u64("etime", (Time.now() + Time.SECONDS_IN_WEEK) * 1000))
Node.u64("etime", (Time.now() + Time.SECONDS_IN_WEEK) * 1000)
)
# Unsupported team_battle nodes. # Unsupported team_battle nodes.
info.add_child(Node.void("team_battle")) info.add_child(Node.void("team_battle"))
@ -2205,9 +2145,7 @@ class JubeatFesto(
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
owned_emblems = self.calculate_owned_items( owned_emblems = self.calculate_owned_items(item.child_value("emblem_list"))
item.child_value("emblem_list")
)
for index in owned_emblems: for index in owned_emblems:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -2244,9 +2182,7 @@ class JubeatFesto(
return Node.void("gameend") return Node.void("gameend")
def format_scores( def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
self, userid: UserID, profile: Profile, scores: List[Score]
) -> Node:
root = Node.void("gametop") root = Node.void("gametop")
datanode = Node.void("data") datanode = Node.void("data")
root.add_child(datanode) root.add_child(datanode)
@ -2324,43 +2260,15 @@ class JubeatFesto(
normalnode = Node.void("normal") normalnode = Node.void("normal")
musicdata.add_child(normalnode) musicdata.add_child(normalnode)
normalnode.add_child( normalnode.add_child(Node.s32_array("play_cnt", scoredata.get_int_array("normal_play_cnt", 3)))
Node.s32_array( normalnode.add_child(Node.s32_array("clear_cnt", scoredata.get_int_array("normal_clear_cnt", 3)))
"play_cnt", scoredata.get_int_array("normal_play_cnt", 3) normalnode.add_child(Node.s32_array("fc_cnt", scoredata.get_int_array("normal_fc_cnt", 3)))
) normalnode.add_child(Node.s32_array("ex_cnt", scoredata.get_int_array("normal_ex_cnt", 3)))
) normalnode.add_child(Node.s32_array("score", scoredata.get_int_array("normal_points", 3)))
normalnode.add_child( normalnode.add_child(Node.s8_array("clear", scoredata.get_int_array("normal_clear_flags", 3)))
Node.s32_array( normalnode.add_child(Node.s32_array("music_rate", scoredata.get_int_array("normal_music_rate", 3)))
"clear_cnt", scoredata.get_int_array("normal_clear_cnt", 3)
)
)
normalnode.add_child(
Node.s32_array(
"fc_cnt", scoredata.get_int_array("normal_fc_cnt", 3)
)
)
normalnode.add_child(
Node.s32_array(
"ex_cnt", scoredata.get_int_array("normal_ex_cnt", 3)
)
)
normalnode.add_child(
Node.s32_array("score", scoredata.get_int_array("normal_points", 3))
)
normalnode.add_child(
Node.s8_array(
"clear", scoredata.get_int_array("normal_clear_flags", 3)
)
)
normalnode.add_child(
Node.s32_array(
"music_rate", scoredata.get_int_array("normal_music_rate", 3)
)
)
for i, ghost in enumerate( for i, ghost in enumerate(scoredata.get("normal_ghost", [None, None, None])):
scoredata.get("normal_ghost", [None, None, None])
):
if ghost is None: if ghost is None:
continue continue
@ -2372,39 +2280,15 @@ class JubeatFesto(
hardnode = Node.void("hard") hardnode = Node.void("hard")
musicdata.add_child(hardnode) musicdata.add_child(hardnode)
hardnode.add_child( hardnode.add_child(Node.s32_array("play_cnt", scoredata.get_int_array("hard_play_cnt", 3)))
Node.s32_array( hardnode.add_child(Node.s32_array("clear_cnt", scoredata.get_int_array("hard_clear_cnt", 3)))
"play_cnt", scoredata.get_int_array("hard_play_cnt", 3) hardnode.add_child(Node.s32_array("fc_cnt", scoredata.get_int_array("hard_fc_cnt", 3)))
) hardnode.add_child(Node.s32_array("ex_cnt", scoredata.get_int_array("hard_ex_cnt", 3)))
) hardnode.add_child(Node.s32_array("score", scoredata.get_int_array("hard_points", 3)))
hardnode.add_child( hardnode.add_child(Node.s8_array("clear", scoredata.get_int_array("hard_clear_flags", 3)))
Node.s32_array( hardnode.add_child(Node.s32_array("music_rate", scoredata.get_int_array("hard_music_rate", 3)))
"clear_cnt", scoredata.get_int_array("hard_clear_cnt", 3)
)
)
hardnode.add_child(
Node.s32_array("fc_cnt", scoredata.get_int_array("hard_fc_cnt", 3))
)
hardnode.add_child(
Node.s32_array("ex_cnt", scoredata.get_int_array("hard_ex_cnt", 3))
)
hardnode.add_child(
Node.s32_array("score", scoredata.get_int_array("hard_points", 3))
)
hardnode.add_child(
Node.s8_array(
"clear", scoredata.get_int_array("hard_clear_flags", 3)
)
)
hardnode.add_child(
Node.s32_array(
"music_rate", scoredata.get_int_array("hard_music_rate", 3)
)
)
for i, ghost in enumerate( for i, ghost in enumerate(scoredata.get("hard_ghost", [None, None, None])):
scoredata.get("hard_ghost", [None, None, None])
):
if ghost is None: if ghost is None:
continue continue
@ -2424,9 +2308,7 @@ class JubeatFesto(
force_unlock = game_config.get_bool("force_song_unlock") force_unlock = game_config.get_bool("force_song_unlock")
# Calculate all of our achievement-backed entities. # Calculate all of our achievement-backed entities.
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
owned_songs: Set[int] = set() owned_songs: Set[int] = set()
owned_secrets: Set[int] = set() owned_secrets: Set[int] = set()
owned_emblems: Set[int] = set() owned_emblems: Set[int] = set()
@ -2434,9 +2316,7 @@ class JubeatFesto(
course_completion: Dict[int, ValidatedDict] = {} course_completion: Dict[int, ValidatedDict] = {}
for achievement in achievements: for achievement in achievements:
if achievement.type == "event": if achievement.type == "event":
event_completion[achievement.id] = achievement.data.get_bool( event_completion[achievement.id] = achievement.data.get_bool("is_completed")
"is_completed"
)
elif achievement.type == "course": elif achievement.type == "course":
course_completion[achievement.id] = achievement.data course_completion[achievement.id] = achievement.data
elif achievement.type == "emblem": elif achievement.type == "emblem":
@ -2480,12 +2360,8 @@ class JubeatFesto(
info.add_child(Node.s32("mtg_entry_cnt", profile.get_int("mtg_entry_cnt"))) info.add_child(Node.s32("mtg_entry_cnt", profile.get_int("mtg_entry_cnt")))
info.add_child(Node.s32("mtg_hold_cnt", profile.get_int("mtg_hold_cnt"))) info.add_child(Node.s32("mtg_hold_cnt", profile.get_int("mtg_hold_cnt")))
info.add_child(Node.u8("mtg_result", profile.get_int("mtg_result"))) info.add_child(Node.u8("mtg_result", profile.get_int("mtg_result")))
info.add_child( info.add_child(Node.s32("bonus_tune_points", profile.get_int("bonus_tune_points")))
Node.s32("bonus_tune_points", profile.get_int("bonus_tune_points")) info.add_child(Node.bool("is_bonus_tune_played", profile.get_bool("is_bonus_tune_played")))
)
info.add_child(
Node.bool("is_bonus_tune_played", profile.get_bool("is_bonus_tune_played"))
)
# Looks to be set to true when there's an old profile, stops tutorial from # Looks to be set to true when there's an old profile, stops tutorial from
# happening on first load. # happening on first load.
@ -2532,55 +2408,27 @@ class JubeatFesto(
# Default music availability, I think? The game doesn't seem to make much use of this, so I think # Default music availability, I think? The game doesn't seem to make much use of this, so I think
# we can safely set it to all 1's much like we do the open_music_list bitfield in global settings. # we can safely set it to all 1's much like we do the open_music_list bitfield in global settings.
item.add_child( item.add_child(Node.s32_array("music_list", profile.get_int_array("music_list", 64, [-1] * 64)))
Node.s32_array(
"music_list", profile.get_int_array("music_list", 64, [-1] * 64)
)
)
# Song unlocks, force everything on if force unlocked, otherwise default to what the game granted. # Song unlocks, force everything on if force unlocked, otherwise default to what the game granted.
item.add_child( item.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 64) ([-1] * 64) if force_unlock else self.create_owned_items(owned_songs, 64),
if force_unlock
else self.create_owned_items(owned_songs, 64),
) )
) )
# We force unlock all themes, markers, titles, and parts, regardless of what the client ended up earning. # We force unlock all themes, markers, titles, and parts, regardless of what the client ended up earning.
item.add_child( item.add_child(Node.s32_array("theme_list", profile.get_int_array("theme_list", 16, [-1] * 16)))
Node.s32_array( item.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list", 16, [-1] * 16)))
"theme_list", profile.get_int_array("theme_list", 16, [-1] * 16) item.add_child(Node.s32_array("title_list", profile.get_int_array("title_list", 160, [-1] * 160)))
) item.add_child(Node.s32_array("parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)))
)
item.add_child(
Node.s32_array(
"marker_list", profile.get_int_array("marker_list", 16, [-1] * 16)
)
)
item.add_child(
Node.s32_array(
"title_list", profile.get_int_array("title_list", 160, [-1] * 160)
)
)
item.add_child(
Node.s32_array(
"parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)
)
)
# These get earned by unlocking them through JBOX. # These get earned by unlocking them through JBOX.
item.add_child( item.add_child(Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96)))
Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96))
)
# I got no idea wtf this is, so I'm defaulting it to all on like the above ones. # I got no idea wtf this is, so I'm defaulting it to all on like the above ones.
item.add_child( item.add_child(Node.s32_array("commu_list", profile.get_int_array("commu_list", 16, [-1] * 16)))
Node.s32_array(
"commu_list", profile.get_int_array("commu_list", 16, [-1] * 16)
)
)
# I have no idea what these are for. I figured it was for the server to grant songs/themes/markers # I have no idea what these are for. I figured it was for the server to grant songs/themes/markers
# outside of gameplay, but the game doesn't seem to react to setting values here. So, lets set them # outside of gameplay, but the game doesn't seem to react to setting values here. So, lets set them
@ -2592,21 +2440,11 @@ class JubeatFesto(
new.add_child( new.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 64) ([-1] * 64) if force_unlock else self.create_owned_items(owned_secrets, 64),
if force_unlock
else self.create_owned_items(owned_secrets, 64),
)
)
new.add_child(
Node.s32_array(
"theme_list", profile.get_int_array("theme_list_new", 16, [-1] * 16)
)
)
new.add_child(
Node.s32_array(
"marker_list", profile.get_int_array("marker_list_new", 16, [-1] * 16)
) )
) )
new.add_child(Node.s32_array("theme_list", profile.get_int_array("theme_list_new", 16, [-1] * 16)))
new.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list_new", 16, [-1] * 16)))
# Add rivals to profile. # Add rivals to profile.
rivallist = Node.void("rivallist") rivallist = Node.void("rivallist")
@ -2643,9 +2481,7 @@ class JubeatFesto(
lab_edit_seq.set_attribute("count", "0") lab_edit_seq.set_attribute("count", "0")
# Full combo challenge # Full combo challenge
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "fc_challenge")
self.game, self.version, "fc_challenge"
)
if entry is None: if entry is None:
entry = ValidatedDict() entry = ValidatedDict()
@ -2705,11 +2541,7 @@ class JubeatFesto(
state = 0x0 state = 0x0
state |= self.EVENT_STATUS_OPEN if eventdata["enabled"] else 0 state |= self.EVENT_STATUS_OPEN if eventdata["enabled"] else 0
state |= ( state |= self.EVENT_STATUS_COMPLETE if event_completion.get(eventid, False) else 0
self.EVENT_STATUS_COMPLETE
if event_completion.get(eventid, False)
else 0
)
event.add_child(Node.u8("state", state)) event.add_child(Node.u8("state", state))
# JBox stuff # JBox stuff
@ -2776,9 +2608,7 @@ class JubeatFesto(
status = 0 status = 0
status |= self.COURSE_STATUS_SEEN if status_dict.get_bool("seen") else 0 status |= self.COURSE_STATUS_SEEN if status_dict.get_bool("seen") else 0
status |= self.COURSE_STATUS_PLAYED if status_dict.get_bool("played") else 0 status |= self.COURSE_STATUS_PLAYED if status_dict.get_bool("played") else 0
status |= ( status |= self.COURSE_STATUS_CLEARED if status_dict.get_bool("cleared") else 0
self.COURSE_STATUS_CLEARED if status_dict.get_bool("cleared") else 0
)
coursenode = Node.void("course") coursenode = Node.void("course")
course_list.add_child(coursenode) course_list.add_child(coursenode)
@ -2871,20 +2701,14 @@ class JubeatFesto(
# Festo dungeon # Festo dungeon
festo_dungeon = Node.void("festo_dungeon") festo_dungeon = Node.void("festo_dungeon")
player.add_child(festo_dungeon) player.add_child(festo_dungeon)
festo_dungeon.add_child( festo_dungeon.add_child(Node.s32("phase", profile.get_int("festo_dungeon_phase")))
Node.s32("phase", profile.get_int("festo_dungeon_phase")) festo_dungeon.add_child(Node.s32("clear_flag", profile.get_int("festo_dungeon_clear_flag")))
)
festo_dungeon.add_child(
Node.s32("clear_flag", profile.get_int("festo_dungeon_clear_flag"))
)
# Missing travel event, which I do not want to implement. # Missing travel event, which I do not want to implement.
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
newprofile.replace_bool("saved", True) newprofile.replace_bool("saved", True)
data = request.child("data") data = request.child("data")
@ -2923,12 +2747,8 @@ class JubeatFesto(
newprofile.replace_int("beat_cnt", info.child_value("beat_cnt")) newprofile.replace_int("beat_cnt", info.child_value("beat_cnt"))
newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt")) newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt"))
newprofile.replace_int( newprofile.replace_int("bonus_tune_points", info.child_value("bonus_tune_points"))
"bonus_tune_points", info.child_value("bonus_tune_points") newprofile.replace_bool("is_bonus_tune_played", info.child_value("is_bonus_tune_played"))
)
newprofile.replace_bool(
"is_bonus_tune_played", info.child_value("is_bonus_tune_played")
)
# Grab last settings # Grab last settings
lastnode = player.child("last") lastnode = player.child("last")
@ -2953,30 +2773,16 @@ class JubeatFesto(
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
newprofile.replace_int_array( newprofile.replace_int_array("music_list", 64, item.child_value("music_list"))
"music_list", 64, item.child_value("music_list") newprofile.replace_int_array("theme_list", 16, item.child_value("theme_list"))
) newprofile.replace_int_array("marker_list", 16, item.child_value("marker_list"))
newprofile.replace_int_array( newprofile.replace_int_array("title_list", 160, item.child_value("title_list"))
"theme_list", 16, item.child_value("theme_list") newprofile.replace_int_array("parts_list", 160, item.child_value("parts_list"))
) newprofile.replace_int_array("commu_list", 16, item.child_value("commu_list"))
newprofile.replace_int_array(
"marker_list", 16, item.child_value("marker_list")
)
newprofile.replace_int_array(
"title_list", 160, item.child_value("title_list")
)
newprofile.replace_int_array(
"parts_list", 160, item.child_value("parts_list")
)
newprofile.replace_int_array(
"commu_list", 16, item.child_value("commu_list")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_songs = self.calculate_owned_items( owned_songs = self.calculate_owned_items(item.child_value("secret_list"))
item.child_value("secret_list")
)
for index in owned_songs: for index in owned_songs:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -3000,18 +2806,12 @@ class JubeatFesto(
newitem = item.child("new") newitem = item.child("new")
if newitem is not None: if newitem is not None:
newprofile.replace_int_array( newprofile.replace_int_array("theme_list_new", 16, newitem.child_value("theme_list"))
"theme_list_new", 16, newitem.child_value("theme_list") newprofile.replace_int_array("marker_list_new", 16, newitem.child_value("marker_list"))
)
newprofile.replace_int_array(
"marker_list_new", 16, newitem.child_value("marker_list")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_secrets = self.calculate_owned_items( owned_secrets = self.calculate_owned_items(newitem.child_value("secret_list"))
newitem.child_value("secret_list")
)
for index in owned_secrets: for index in owned_secrets:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -3226,9 +3026,7 @@ class JubeatFesto(
# Save it back # Save it back
newprofile.replace_dict("pick_up_chart", pick_up_chart) newprofile.replace_dict("pick_up_chart", pick_up_chart)
newprofile.replace_float( newprofile.replace_float("pick_up_jubility", float(hot_music_list.attribute("param")) / 10)
"pick_up_jubility", float(hot_music_list.attribute("param")) / 10
)
# Common jubility stuff # Common jubility stuff
other_music_list = target_music.child("other_music_list") other_music_list = target_music.child("other_music_list")
@ -3251,9 +3049,7 @@ class JubeatFesto(
# Save it back # Save it back
newprofile.replace_dict("common_chart", common_chart) newprofile.replace_dict("common_chart", common_chart)
newprofile.replace_float( newprofile.replace_float("common_jubility", float(other_music_list.attribute("param")) / 10)
"common_jubility", float(other_music_list.attribute("param")) / 10
)
# Clan course saving # Clan course saving
clan_course_list = player.child("course_list") clan_course_list = player.child("course_list")
@ -3281,9 +3077,7 @@ class JubeatFesto(
oldcourse = ValidatedDict() oldcourse = ValidatedDict()
oldcourse.replace_bool("seen", oldcourse.get_bool("seen") or is_seen) oldcourse.replace_bool("seen", oldcourse.get_bool("seen") or is_seen)
oldcourse.replace_bool( oldcourse.replace_bool("played", oldcourse.get_bool("played") or is_played)
"played", oldcourse.get_bool("played") or is_played
)
# Save it as an achievement # Save it as an achievement
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
@ -3335,12 +3129,8 @@ class JubeatFesto(
festo_dungeon = player.child("festo_dungeon") festo_dungeon = player.child("festo_dungeon")
if festo_dungeon is not None: if festo_dungeon is not None:
newprofile.replace_int( newprofile.replace_int("festo_dungeon_phase", festo_dungeon.child_value("phase"))
"festo_dungeon_phase", festo_dungeon.child_value("phase") newprofile.replace_int("festo_dungeon_clear_flag", festo_dungeon.child_value("clear_flag"))
)
newprofile.replace_int(
"festo_dungeon_clear_flag", festo_dungeon.child_value("clear_flag")
)
# Keep track of play statistics # Keep track of play statistics
self.update_play_statistics(userid) self.update_play_statistics(userid)

View File

@ -199,9 +199,7 @@ class JubeatProp(
return cls.__rank_to_class(cls.__class_to_rank(cur_class, cur_subclass) - 1) return cls.__rank_to_class(cls.__class_to_rank(cur_class, cur_subclass) - 1)
@classmethod @classmethod
def _get_league_buckets( def _get_league_buckets(cls, scores: List[Tuple[UserID, int]]) -> Tuple[List[UserID], List[UserID], List[UserID]]:
cls, scores: List[Tuple[UserID, int]]
) -> Tuple[List[UserID], List[UserID], List[UserID]]:
""" """
Given a list of userid, score tuples, return a tuple containing three lists. Given a list of userid, score tuples, return a tuple containing three lists.
The first list is the top 30% scorer IDs, the next list is the middle 40% The first list is the top 30% scorer IDs, the next list is the middle 40%
@ -253,9 +251,7 @@ class JubeatProp(
scores.append( scores.append(
( (
userid, userid,
league_score["score"][0] league_score["score"][0] + league_score["score"][1] + league_score["score"][2],
+ league_score["score"][1]
+ league_score["score"][2],
) )
) )
else: else:
@ -264,9 +260,7 @@ class JubeatProp(
return scores, absentees return scores, absentees
@classmethod @classmethod
def _get_league_absentees( def _get_league_absentees(cls, data: Data, current_id: int, absentees: List[UserID]) -> List[UserID]:
cls, data: Data, current_id: int, absentees: List[UserID]
) -> List[UserID]:
""" """
Given a list of user IDs that didn't play for some number of weeks, return Given a list of user IDs that didn't play for some number of weeks, return
a subset of those IDs that have been absent enough weeks to get a demotion. a subset of those IDs that have been absent enough weeks to get a demotion.
@ -333,22 +327,15 @@ class JubeatProp(
data.local.user.put_profile(cls.game, cls.version, userid, profile) data.local.user.put_profile(cls.game, cls.version, userid, profile)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Once a week, insert a new league course. Every day, insert new FC challenge courses. Once a week, insert a new league course. Every day, insert new FC challenge courses.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "league_course", "weekly"):
cls.game, cls.version, "league_course", "weekly"
):
# Generate a new league course list, save it to the DB. # Generate a new league course list, save it to the DB.
start_time, end_time = data.local.network.get_schedule_duration("weekly") start_time, end_time = data.local.network.get_schedule_duration("weekly")
all_songs = set( all_songs = set(song.id for song in data.local.music.get_all_songs(cls.game, cls.version))
song.id
for song in data.local.music.get_all_songs(cls.game, cls.version)
)
if len(all_songs) >= 3: if len(all_songs) >= 3:
league_songs = random.sample(all_songs, 3) league_songs = random.sample(all_songs, 3)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -390,19 +377,12 @@ class JubeatProp(
cls._modify_profile(data, userid, "demote") cls._modify_profile(data, userid, "demote")
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "league_course", "weekly")
cls.game, cls.version, "league_course", "weekly"
)
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "fc_challenge", "daily"):
cls.game, cls.version, "fc_challenge", "daily"
):
# Generate a new list of two FC challenge songs. # Generate a new list of two FC challenge songs.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = set( all_songs = set(song.id for song in data.local.music.get_all_songs(cls.game, cls.version))
song.id
for song in data.local.music.get_all_songs(cls.game, cls.version)
)
if len(all_songs) >= 2: if len(all_songs) >= 2:
daily_songs = random.sample(all_songs, 2) daily_songs = random.sample(all_songs, 2)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -428,9 +408,7 @@ class JubeatProp(
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "fc_challenge", "daily")
cls.game, cls.version, "fc_challenge", "daily"
)
return events return events
@ -466,9 +444,7 @@ class JubeatProp(
info.add_child(only_now_music) info.add_child(only_now_music)
# Full combo challenge? # Full combo challenge?
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "fc_challenge")
self.game, self.version, "fc_challenge"
)
if entry is None: if entry is None:
entry = ValidatedDict() entry = ValidatedDict()
@ -803,11 +779,7 @@ class JubeatProp(
result.add_child(Node.s32_array("score", scores)) result.add_child(Node.s32_array("score", scores))
# Last course ID # Last course ID
data.add_child( data.add_child(Node.s32("last_course_id", profile.get_dict("last").get_int("last_course_id", -1)))
Node.s32(
"last_course_id", profile.get_dict("last").get_int("last_course_id", -1)
)
)
return gametop return gametop
@ -830,9 +802,7 @@ class JubeatProp(
data.add_child(league_list) data.add_child(league_list)
# Look up the current league charts in the DB # Look up the current league charts in the DB
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "league")
self.game, self.version, "league"
)
if entry is not None: if entry is not None:
# Just get the week number, use that as the ID # Just get the week number, use that as the ID
leagueid = int(entry["start_time"] / 604800) leagueid = int(entry["start_time"] / 604800)
@ -870,27 +840,15 @@ class JubeatProp(
result = Node.void("result") result = Node.void("result")
player.add_child(result) player.add_child(result)
league_score = self.data.local.user.get_achievement( league_score = self.data.local.user.get_achievement(self.game, self.version, userid, leagueid, "league")
self.game, self.version, userid, leagueid, "league"
)
if league_score is None: if league_score is None:
league_score = ValidatedDict() league_score = ValidatedDict()
result.add_child( result.add_child(Node.s32_array("score", league_score.get_int_array("score", 3, [0] * 3)))
Node.s32_array("score", league_score.get_int_array("score", 3, [0] * 3)) result.add_child(Node.s8_array("clear", league_score.get_int_array("clear", 3, [0] * 3)))
)
result.add_child(
Node.s8_array("clear", league_score.get_int_array("clear", 3, [0] * 3))
)
data.add_child( data.add_child(Node.s32("last_class", profile.get_dict("last").get_int("league_class", 1)))
Node.s32("last_class", profile.get_dict("last").get_int("league_class", 1)) data.add_child(Node.s32("last_subclass", profile.get_dict("last").get_int("league_subclass", 5)))
)
data.add_child(
Node.s32(
"last_subclass", profile.get_dict("last").get_int("league_subclass", 5)
)
)
data.add_child(Node.bool("is_checked", profile.get_bool("league_is_checked"))) data.add_child(Node.bool("is_checked", profile.get_bool("league_is_checked")))
return gametop return gametop
@ -905,9 +863,7 @@ class JubeatProp(
force_unlock = game_config.get_bool("force_song_unlock") force_unlock = game_config.get_bool("force_song_unlock")
# Allow figuring out owned emblems. # Allow figuring out owned emblems.
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
owned_songs: Set[int] = set() owned_songs: Set[int] = set()
owned_secrets: Set[int] = set() owned_secrets: Set[int] = set()
owned_emblems: Set[int] = set() owned_emblems: Set[int] = set()
@ -953,12 +909,8 @@ class JubeatProp(
info.add_child(Node.s32("match_cnt", profile.get_int("match_cnt"))) info.add_child(Node.s32("match_cnt", profile.get_int("match_cnt")))
info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt"))) info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt")))
info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt"))) info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt")))
info.add_child( info.add_child(Node.s32("bonus_tune_points", profile.get_int("bonus_tune_points")))
Node.s32("bonus_tune_points", profile.get_int("bonus_tune_points")) info.add_child(Node.bool("is_bonus_tune_played", profile.get_bool("is_bonus_tune_played")))
)
info.add_child(
Node.bool("is_bonus_tune_played", profile.get_bool("is_bonus_tune_played"))
)
# Looks to be set to true when there's an old profile, stops tutorial from # Looks to be set to true when there's an old profile, stops tutorial from
# happening on first load. # happening on first load.
@ -1008,55 +960,29 @@ class JubeatProp(
# Secret unlocks # Secret unlocks
item = Node.void("item") item = Node.void("item")
player.add_child(item) player.add_child(item)
item.add_child( item.add_child(Node.s32_array("music_list", profile.get_int_array("music_list", 32, [-1] * 32)))
Node.s32_array(
"music_list", profile.get_int_array("music_list", 32, [-1] * 32)
)
)
item.add_child( item.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 32) ([-1] * 32) if force_unlock else self.create_owned_items(owned_songs, 32),
if force_unlock
else self.create_owned_items(owned_songs, 32),
) )
) )
item.add_child(Node.s16("theme_list", profile.get_int("theme_list", -1))) item.add_child(Node.s16("theme_list", profile.get_int("theme_list", -1)))
item.add_child( item.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list", 2, [-1] * 2)))
Node.s32_array( item.add_child(Node.s32_array("title_list", profile.get_int_array("title_list", 160, [-1] * 160)))
"marker_list", profile.get_int_array("marker_list", 2, [-1] * 2) item.add_child(Node.s32_array("parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)))
) item.add_child(Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96)))
)
item.add_child(
Node.s32_array(
"title_list", profile.get_int_array("title_list", 160, [-1] * 160)
)
)
item.add_child(
Node.s32_array(
"parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)
)
)
item.add_child(
Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96))
)
new = Node.void("new") new = Node.void("new")
item.add_child(new) item.add_child(new)
new.add_child( new.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 32) ([-1] * 32) if force_unlock else self.create_owned_items(owned_secrets, 32),
if force_unlock
else self.create_owned_items(owned_secrets, 32),
) )
) )
new.add_child(Node.s16("theme_list", profile.get_int("theme_list_new", -1))) new.add_child(Node.s16("theme_list", profile.get_int("theme_list_new", -1)))
new.add_child( new.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list_new", 2, [-1] * 2)))
Node.s32_array(
"marker_list", profile.get_int_array("marker_list_new", 2, [-1] * 2)
)
)
# Sane defaults for unknown/who cares nodes # Sane defaults for unknown/who cares nodes
history = Node.void("history") history = Node.void("history")
@ -1070,9 +996,7 @@ class JubeatProp(
cabinet_survey.add_child(Node.u32("read_flag", 0)) cabinet_survey.add_child(Node.u32("read_flag", 0))
kaitou_bisco = Node.void("kaitou_bisco") kaitou_bisco = Node.void("kaitou_bisco")
player.add_child(kaitou_bisco) player.add_child(kaitou_bisco)
kaitou_bisco.add_child( kaitou_bisco.add_child(Node.u32("read_flag", profile.get_int("kaitou_bisco_read_flag")))
Node.u32("read_flag", profile.get_int("kaitou_bisco_read_flag"))
)
navi = Node.void("navi") navi = Node.void("navi")
player.add_child(navi) player.add_child(navi)
navi.add_child(Node.u32("flag", profile.get_int("navi_flag"))) navi.add_child(Node.u32("flag", profile.get_int("navi_flag")))
@ -1089,15 +1013,11 @@ class JubeatProp(
event.set_attribute("type", str(achievement.id)) event.set_attribute("type", str(achievement.id))
state = 0x0 state = 0x0
state = ( state = state + 0x2 if achievement.data.get_bool("is_completed") else 0x0
state + 0x2 if achievement.data.get_bool("is_completed") else 0x0
)
event.add_child(Node.u8("state", state)) event.add_child(Node.u8("state", state))
# Full combo challenge # Full combo challenge
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "fc_challenge")
self.game, self.version, "fc_challenge"
)
if entry is None: if entry is None:
entry = ValidatedDict() entry = ValidatedDict()
@ -1161,15 +1081,9 @@ class JubeatProp(
league = Node.void("league") league = Node.void("league")
rival.add_child(league) rival.add_child(league)
league.add_child( league.add_child(Node.bool("is_first_play", rprofile.get_bool("league_is_first_play", True)))
Node.bool(
"is_first_play", rprofile.get_bool("league_is_first_play", True)
)
)
league.add_child(Node.s32("class", rprofile.get_int("league_class", 1))) league.add_child(Node.s32("class", rprofile.get_int("league_class", 1)))
league.add_child( league.add_child(Node.s32("subclass", rprofile.get_int("league_subclass", 5)))
Node.s32("subclass", rprofile.get_int("league_subclass", 5))
)
# Lazy way of keeping track of rivals, since we can only have 3 # Lazy way of keeping track of rivals, since we can only have 3
# or the game with throw up. # or the game with throw up.
@ -1214,17 +1128,13 @@ class JubeatProp(
player.add_child(career) player.add_child(career)
career.add_child(Node.s16("level", careerdict.get_int("level", 1))) career.add_child(Node.s16("level", careerdict.get_int("level", 1)))
career.add_child(Node.s32("point", careerdict.get_int("point"))) career.add_child(Node.s32("point", careerdict.get_int("point")))
career.add_child( career.add_child(Node.s32_array("param", careerdict.get_int_array("param", 10, [-1] * 10)))
Node.s32_array("param", careerdict.get_int_array("param", 10, [-1] * 10))
)
career.add_child(Node.bool("is_unlocked", careerdict.get_bool("is_unlocked"))) career.add_child(Node.bool("is_unlocked", careerdict.get_bool("is_unlocked")))
# League stuff # League stuff
league = Node.void("league") league = Node.void("league")
player.add_child(league) player.add_child(league)
league.add_child( league.add_child(Node.bool("is_first_play", profile.get_bool("league_is_first_play", True)))
Node.bool("is_first_play", profile.get_bool("league_is_first_play", True))
)
league.add_child(Node.s32("class", profile.get_int("league_class", 1))) league.add_child(Node.s32("class", profile.get_int("league_class", 1)))
league.add_child(Node.s32("subclass", profile.get_int("league_subclass", 5))) league.add_child(Node.s32("subclass", profile.get_int("league_subclass", 5)))
@ -1276,9 +1186,7 @@ class JubeatProp(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
newprofile.replace_bool("saved", True) newprofile.replace_bool("saved", True)
data = request.child("data") data = request.child("data")
@ -1318,17 +1226,11 @@ class JubeatProp(
newprofile.replace_int("clear_cnt", info.child_value("clear_cnt")) newprofile.replace_int("clear_cnt", info.child_value("clear_cnt"))
newprofile.replace_int("match_cnt", info.child_value("match_cnt")) newprofile.replace_int("match_cnt", info.child_value("match_cnt"))
newprofile.replace_int("beat_cnt", info.child_value("beat_cnt")) newprofile.replace_int("beat_cnt", info.child_value("beat_cnt"))
newprofile.replace_int( newprofile.replace_int("total_best_score", info.child_value("total_best_score"))
"total_best_score", info.child_value("total_best_score")
)
newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt")) newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt"))
newprofile.replace_int( newprofile.replace_int("bonus_tune_points", info.child_value("bonus_tune_points"))
"bonus_tune_points", info.child_value("bonus_tune_points") newprofile.replace_bool("is_bonus_tune_played", info.child_value("is_bonus_tune_played"))
)
newprofile.replace_bool(
"is_bonus_tune_played", info.child_value("is_bonus_tune_played")
)
# Grab last settings (finally mostly in its own node!) # Grab last settings (finally mostly in its own node!)
lastnode = player.child("last") lastnode = player.child("last")
@ -1353,25 +1255,15 @@ class JubeatProp(
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
newprofile.replace_int_array( newprofile.replace_int_array("title_list", 160, item.child_value("title_list"))
"title_list", 160, item.child_value("title_list")
)
newprofile.replace_int("theme_list", item.child_value("theme_list")) newprofile.replace_int("theme_list", item.child_value("theme_list"))
newprofile.replace_int_array( newprofile.replace_int_array("marker_list", 2, item.child_value("marker_list"))
"marker_list", 2, item.child_value("marker_list") newprofile.replace_int_array("parts_list", 160, item.child_value("parts_list"))
) newprofile.replace_int_array("music_list", 32, item.child_value("music_list"))
newprofile.replace_int_array(
"parts_list", 160, item.child_value("parts_list")
)
newprofile.replace_int_array(
"music_list", 32, item.child_value("music_list")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_songs = self.calculate_owned_items( owned_songs = self.calculate_owned_items(item.child_value("secret_list"))
item.child_value("secret_list")
)
for index in owned_songs: for index in owned_songs:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -1395,18 +1287,12 @@ class JubeatProp(
newitem = item.child("new") newitem = item.child("new")
if newitem is not None: if newitem is not None:
newprofile.replace_int( newprofile.replace_int("theme_list_new", newitem.child_value("theme_list"))
"theme_list_new", newitem.child_value("theme_list") newprofile.replace_int_array("marker_list_new", 2, newitem.child_value("marker_list"))
)
newprofile.replace_int_array(
"marker_list_new", 2, newitem.child_value("marker_list")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_secrets = self.calculate_owned_items( owned_secrets = self.calculate_owned_items(newitem.child_value("secret_list"))
newitem.child_value("secret_list")
)
for index in owned_secrets: for index in owned_secrets:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -1478,9 +1364,7 @@ class JubeatProp(
# A whole bunch of miscelaneous shit # A whole bunch of miscelaneous shit
newprofile.replace_int("navi_flag", player.child_value("navi/flag")) newprofile.replace_int("navi_flag", player.child_value("navi/flag"))
newprofile.replace_int( newprofile.replace_int("kaitou_bisco_read_flag", player.child_value("kaitou_bisco/read_flag"))
"kaitou_bisco_read_flag", player.child_value("kaitou_bisco/read_flag")
)
# Get timestamps for played songs # Get timestamps for played songs
timestamps: Dict[int, int] = {} timestamps: Dict[int, int] = {}
@ -1527,9 +1411,7 @@ class JubeatProp(
if flags & bit > 0: if flags & bit > 0:
medal = max(medal, mapping[bit]) medal = max(medal, mapping[bit])
self.update_score( self.update_score(userid, timestamp, songid, chart, points, medal, combo, ghost)
userid, timestamp, songid, chart, points, medal, combo, ghost
)
# If this was a course save, grab and save that info too # If this was a course save, grab and save that info too
course = player.child("course") course = player.child("course")
@ -1558,12 +1440,8 @@ class JubeatProp(
league = player.child("league") league = player.child("league")
if league is not None: if league is not None:
leagueid = league.child_value("league_id") leagueid = league.child_value("league_id")
newprofile.replace_bool( newprofile.replace_bool("league_is_checked", league.child_value("is_checked"))
"league_is_checked", league.child_value("is_checked") newprofile.replace_bool("league_is_first_play", league.child_value("is_first_play"))
)
newprofile.replace_bool(
"league_is_first_play", league.child_value("is_first_play")
)
# Extract scores # Extract scores
score = [0] * 3 score = [0] * 3
@ -1605,9 +1483,7 @@ class JubeatProp(
return newprofile return newprofile
def format_scores( def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
self, userid: UserID, profile: Profile, scores: List[Score]
) -> Node:
root = Node.void("gametop") root = Node.void("gametop")
datanode = Node.void("data") datanode = Node.void("data")
root.add_child(datanode) root.add_child(datanode)
@ -1673,24 +1549,12 @@ class JubeatProp(
playdata.add_child(musicdata) playdata.add_child(musicdata)
musicdata.set_attribute("music_id", scoreid) musicdata.set_attribute("music_id", scoreid)
musicdata.add_child( musicdata.add_child(Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)))
Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)) musicdata.add_child(Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)))
) musicdata.add_child(Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3)))
musicdata.add_child( musicdata.add_child(Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3)))
Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)) musicdata.add_child(Node.s32_array("score", scoredata.get_int_array("points", 3)))
) musicdata.add_child(Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3)))
musicdata.add_child(
Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3))
)
musicdata.add_child(
Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3))
)
musicdata.add_child(
Node.s32_array("score", scoredata.get_int_array("points", 3))
)
musicdata.add_child(
Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3))
)
ghosts = scoredata.get("ghost", [None, None, None]) ghosts = scoredata.get("ghost", [None, None, None])
for i in range(len(ghosts)): for i in range(len(ghosts)):

View File

@ -56,22 +56,15 @@ class JubeatQubell(
return JubeatProp(self.data, self.config, self.model) return JubeatProp(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert daily FC challenges into the DB. Insert daily FC challenges into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "fc_challenge", "daily"):
cls.game, cls.version, "fc_challenge", "daily"
):
# Generate a new list of two FC challenge songs. # Generate a new list of two FC challenge songs.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = set( all_songs = set(song.id for song in data.local.music.get_all_songs(cls.game, cls.version))
song.id
for song in data.local.music.get_all_songs(cls.game, cls.version)
)
if len(all_songs) >= 2: if len(all_songs) >= 2:
daily_songs = random.sample(all_songs, 2) daily_songs = random.sample(all_songs, 2)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -97,9 +90,7 @@ class JubeatQubell(
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "fc_challenge", "daily")
cls.game, cls.version, "fc_challenge", "daily"
)
return events return events
@classmethod @classmethod
@ -674,9 +665,7 @@ class JubeatQubell(
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
owned_emblems = self.calculate_owned_items( owned_emblems = self.calculate_owned_items(item.child_value("emblem_list"))
item.child_value("emblem_list")
)
for index in owned_emblems: for index in owned_emblems:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -722,9 +711,7 @@ class JubeatQubell(
game_config = self.get_game_config() game_config = self.get_game_config()
force_unlock = game_config.get_bool("force_song_unlock") force_unlock = game_config.get_bool("force_song_unlock")
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
owned_songs: Set[int] = set() owned_songs: Set[int] = set()
owned_secrets: Set[int] = set() owned_secrets: Set[int] = set()
owned_emblems: Set[int] = set() owned_emblems: Set[int] = set()
@ -773,12 +760,8 @@ class JubeatQubell(
info.add_child(Node.s32("match_cnt", profile.get_int("match_cnt"))) info.add_child(Node.s32("match_cnt", profile.get_int("match_cnt")))
info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt"))) info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt")))
info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt"))) info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt")))
info.add_child( info.add_child(Node.s32("bonus_tune_points", profile.get_int("bonus_tune_points")))
Node.s32("bonus_tune_points", profile.get_int("bonus_tune_points")) info.add_child(Node.bool("is_bonus_tune_played", profile.get_bool("is_bonus_tune_played")))
)
info.add_child(
Node.bool("is_bonus_tune_played", profile.get_bool("is_bonus_tune_played"))
)
# Looks to be set to true when there's an old profile, stops tutorial from # Looks to be set to true when there's an old profile, stops tutorial from
# happening on first load. # happening on first load.
@ -829,63 +812,29 @@ class JubeatQubell(
# Secret unlocks # Secret unlocks
item = Node.void("item") item = Node.void("item")
player.add_child(item) player.add_child(item)
item.add_child( item.add_child(Node.s32_array("music_list", profile.get_int_array("music_list", 64, [-1] * 64)))
Node.s32_array(
"music_list", profile.get_int_array("music_list", 64, [-1] * 64)
)
)
item.add_child( item.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 64) ([-1] * 64) if force_unlock else self.create_owned_items(owned_songs, 64),
if force_unlock
else self.create_owned_items(owned_songs, 64),
) )
) )
item.add_child( item.add_child(Node.s32_array("theme_list", profile.get_int_array("theme_list", 16, [-1] * 16)))
Node.s32_array( item.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list", 16, [-1] * 16)))
"theme_list", profile.get_int_array("theme_list", 16, [-1] * 16) item.add_child(Node.s32_array("title_list", profile.get_int_array("title_list", 160, [-1] * 160)))
) item.add_child(Node.s32_array("parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)))
) item.add_child(Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96)))
item.add_child(
Node.s32_array(
"marker_list", profile.get_int_array("marker_list", 16, [-1] * 16)
)
)
item.add_child(
Node.s32_array(
"title_list", profile.get_int_array("title_list", 160, [-1] * 160)
)
)
item.add_child(
Node.s32_array(
"parts_list", profile.get_int_array("parts_list", 160, [-1] * 160)
)
)
item.add_child(
Node.s32_array("emblem_list", self.create_owned_items(owned_emblems, 96))
)
new = Node.void("new") new = Node.void("new")
item.add_child(new) item.add_child(new)
new.add_child( new.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 64) ([-1] * 64) if force_unlock else self.create_owned_items(owned_secrets, 64),
if force_unlock
else self.create_owned_items(owned_secrets, 64),
)
)
new.add_child(
Node.s32_array(
"theme_list", profile.get_int_array("theme_list_new", 16, [-1] * 16)
)
)
new.add_child(
Node.s32_array(
"marker_list", profile.get_int_array("marker_list_new", 16, [-1] * 16)
) )
) )
new.add_child(Node.s32_array("theme_list", profile.get_int_array("theme_list_new", 16, [-1] * 16)))
new.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list_new", 16, [-1] * 16)))
# Add rivals to profile. # Add rivals to profile.
rivallist = Node.void("rivallist") rivallist = Node.void("rivallist")
@ -924,9 +873,7 @@ class JubeatQubell(
lab_edit_seq.set_attribute("count", "0") lab_edit_seq.set_attribute("count", "0")
# Full combo challenge # Full combo challenge
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "fc_challenge")
self.game, self.version, "fc_challenge"
)
if entry is None: if entry is None:
entry = ValidatedDict() entry = ValidatedDict()
@ -987,9 +934,7 @@ class JubeatQubell(
event.set_attribute("type", str(achievement.id)) event.set_attribute("type", str(achievement.id))
state = 0x0 state = 0x0
state = ( state = state + 0x2 if achievement.data.get_bool("is_completed") else 0x0
state + 0x2 if achievement.data.get_bool("is_completed") else 0x0
)
event.add_child(Node.u8("state", state)) event.add_child(Node.u8("state", state))
# JBox stuff # JBox stuff
@ -1025,9 +970,7 @@ class JubeatQubell(
main.add_child(stage) main.add_child(stage)
stage.set_attribute("number", str(digdigdict.get_int("stage_number", 1))) stage.set_attribute("number", str(digdigdict.get_int("stage_number", 1)))
stage.add_child(Node.s32("point", digdigdict.get_int("point"))) stage.add_child(Node.s32("point", digdigdict.get_int("point")))
stage.add_child( stage.add_child(Node.s32_array("param", digdigdict.get_int_array("param", 12, [0] * 12)))
Node.s32_array("param", digdigdict.get_int_array("param", 12, [0] * 12))
)
# Emerald eternal stages # Emerald eternal stages
eternal = Node.void("eternal") eternal = Node.void("eternal")
@ -1035,42 +978,20 @@ class JubeatQubell(
eternal.add_child(Node.s32("ratio", 1)) eternal.add_child(Node.s32("ratio", 1))
eternal.add_child(Node.s64("used_point", eternaldict.get_int("used_point"))) eternal.add_child(Node.s64("used_point", eternaldict.get_int("used_point")))
eternal.add_child(Node.s64("point", eternaldict.get_int("point"))) eternal.add_child(Node.s64("point", eternaldict.get_int("point")))
eternal.add_child( eternal.add_child(Node.s64("excavated_point", eternaldict.get_int("excavated_point")))
Node.s64("excavated_point", eternaldict.get_int("excavated_point"))
)
cube = Node.void("cube") cube = Node.void("cube")
eternal.add_child(cube) eternal.add_child(cube)
cube.add_child( cube.add_child(Node.s8_array("state", eternaldict.get_int_array("state", 12, [0] * 12)))
Node.s8_array("state", eternaldict.get_int_array("state", 12, [0] * 12))
)
item = Node.void("item") item = Node.void("item")
cube.add_child(item) cube.add_child(item)
item.add_child( item.add_child(Node.s32_array("kind", eternaldict.get_int_array("item_kind", 12, [0] * 12)))
Node.s32_array("kind", eternaldict.get_int_array("item_kind", 12, [0] * 12)) item.add_child(Node.s32_array("value", eternaldict.get_int_array("item_value", 12, [0] * 12)))
)
item.add_child(
Node.s32_array(
"value", eternaldict.get_int_array("item_value", 12, [0] * 12)
)
)
norma = Node.void("norma") norma = Node.void("norma")
cube.add_child(norma) cube.add_child(norma)
norma.add_child(Node.s64_array("till_time", [0] * 12)) norma.add_child(Node.s64_array("till_time", [0] * 12))
norma.add_child( norma.add_child(Node.s32_array("kind", eternaldict.get_int_array("norma_kind", 12, [0] * 12)))
Node.s32_array( norma.add_child(Node.s32_array("value", eternaldict.get_int_array("norma_value", 12, [0] * 12)))
"kind", eternaldict.get_int_array("norma_kind", 12, [0] * 12) norma.add_child(Node.s32_array("param", eternaldict.get_int_array("norma_param", 12, [0] * 12)))
)
)
norma.add_child(
Node.s32_array(
"value", eternaldict.get_int_array("norma_value", 12, [0] * 12)
)
)
norma.add_child(
Node.s32_array(
"param", eternaldict.get_int_array("norma_param", 12, [0] * 12)
)
)
if self.ENABLE_GARNET: if self.ENABLE_GARNET:
# Garnet # Garnet
@ -1084,14 +1005,8 @@ class JubeatQubell(
olddict.get_int_array("excavated_point", 5, [0] * 5), olddict.get_int_array("excavated_point", 5, [0] * 5),
) )
) )
old.add_child( old.add_child(Node.s32_array("excavated", olddict.get_int_array("excavated", 5, [0] * 5)))
Node.s32_array( old.add_child(Node.s32_array("param", olddict.get_int_array("param", 5, [0] * 5)))
"excavated", olddict.get_int_array("excavated", 5, [0] * 5)
)
)
old.add_child(
Node.s32_array("param", olddict.get_int_array("param", 5, [0] * 5))
)
# This should have a bunch of sub-nodes with the following format. Note that only # This should have a bunch of sub-nodes with the following format. Note that only
# the first ten nodes are saved even if more are read. Presumably this is the list # the first ten nodes are saved even if more are read. Presumably this is the list
# of old songs we are allowing the player to unlock? Doesn't matter, we're disabling # of old songs we are allowing the player to unlock? Doesn't matter, we're disabling
@ -1110,9 +1025,7 @@ class JubeatQubell(
main.add_child(stage_list) main.add_child(stage_list)
# Stage numbers are between 1 and 13 inclusive. # Stage numbers are between 1 and 13 inclusive.
for i in range(1, 14): for i in range(1, 14):
stage_flags = self.data.local.user.get_achievement( stage_flags = self.data.local.user.get_achievement(self.game, self.version, userid, i, "stage")
self.game, self.version, userid, i, "stage"
)
if stage_flags is None: if stage_flags is None:
stage_flags = ValidatedDict() stage_flags = ValidatedDict()
@ -1167,9 +1080,7 @@ class JubeatQubell(
return root return root
def format_scores( def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
self, userid: UserID, profile: Profile, scores: List[Score]
) -> Node:
root = Node.void("gametop") root = Node.void("gametop")
datanode = Node.void("data") datanode = Node.void("data")
root.add_child(datanode) root.add_child(datanode)
@ -1235,24 +1146,12 @@ class JubeatQubell(
playdata.add_child(musicdata) playdata.add_child(musicdata)
musicdata.set_attribute("music_id", scoreid) musicdata.set_attribute("music_id", scoreid)
musicdata.add_child( musicdata.add_child(Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)))
Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)) musicdata.add_child(Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)))
) musicdata.add_child(Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3)))
musicdata.add_child( musicdata.add_child(Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3)))
Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)) musicdata.add_child(Node.s32_array("score", scoredata.get_int_array("points", 3)))
) musicdata.add_child(Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3)))
musicdata.add_child(
Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3))
)
musicdata.add_child(
Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3))
)
musicdata.add_child(
Node.s32_array("score", scoredata.get_int_array("points", 3))
)
musicdata.add_child(
Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3))
)
ghosts = scoredata.get("ghost", [None, None, None]) ghosts = scoredata.get("ghost", [None, None, None])
for i in range(len(ghosts)): for i in range(len(ghosts)):
@ -1266,9 +1165,7 @@ class JubeatQubell(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
newprofile.replace_bool("saved", True) newprofile.replace_bool("saved", True)
data = request.child("data") data = request.child("data")
@ -1309,12 +1206,8 @@ class JubeatQubell(
newprofile.replace_int("beat_cnt", info.child_value("beat_cnt")) newprofile.replace_int("beat_cnt", info.child_value("beat_cnt"))
newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt")) newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt"))
newprofile.replace_int( newprofile.replace_int("bonus_tune_points", info.child_value("bonus_tune_points"))
"bonus_tune_points", info.child_value("bonus_tune_points") newprofile.replace_bool("is_bonus_tune_played", info.child_value("is_bonus_tune_played"))
)
newprofile.replace_bool(
"is_bonus_tune_played", info.child_value("is_bonus_tune_played")
)
# Grab last settings # Grab last settings
lastnode = player.child("last") lastnode = player.child("last")
@ -1340,27 +1233,15 @@ class JubeatQubell(
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
newprofile.replace_int_array( newprofile.replace_int_array("music_list", 64, item.child_value("music_list"))
"music_list", 64, item.child_value("music_list") newprofile.replace_int_array("theme_list", 16, item.child_value("theme_list"))
) newprofile.replace_int_array("marker_list", 16, item.child_value("marker_list"))
newprofile.replace_int_array( newprofile.replace_int_array("title_list", 160, item.child_value("title_list"))
"theme_list", 16, item.child_value("theme_list") newprofile.replace_int_array("parts_list", 160, item.child_value("parts_list"))
)
newprofile.replace_int_array(
"marker_list", 16, item.child_value("marker_list")
)
newprofile.replace_int_array(
"title_list", 160, item.child_value("title_list")
)
newprofile.replace_int_array(
"parts_list", 160, item.child_value("parts_list")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_songs = self.calculate_owned_items( owned_songs = self.calculate_owned_items(item.child_value("secret_list"))
item.child_value("secret_list")
)
for index in owned_songs: for index in owned_songs:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -1384,18 +1265,12 @@ class JubeatQubell(
newitem = item.child("new") newitem = item.child("new")
if newitem is not None: if newitem is not None:
newprofile.replace_int_array( newprofile.replace_int_array("theme_list_new", 16, newitem.child_value("theme_list"))
"theme_list_new", 16, newitem.child_value("theme_list") newprofile.replace_int_array("marker_list_new", 16, newitem.child_value("marker_list"))
)
newprofile.replace_int_array(
"marker_list_new", 16, newitem.child_value("marker_list")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_secrets = self.calculate_owned_items( owned_secrets = self.calculate_owned_items(newitem.child_value("secret_list"))
newitem.child_value("secret_list")
)
for index in owned_secrets: for index in owned_secrets:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -1492,27 +1367,13 @@ class JubeatQubell(
if eternal is not None: if eternal is not None:
eternaldict.replace_int("used_point", eternal.child_value("used_point")) eternaldict.replace_int("used_point", eternal.child_value("used_point"))
eternaldict.replace_int("point", eternal.child_value("point")) eternaldict.replace_int("point", eternal.child_value("point"))
eternaldict.replace_int( eternaldict.replace_int("excavated_point", eternal.child_value("excavated_point"))
"excavated_point", eternal.child_value("excavated_point") eternaldict.replace_int_array("state", 12, eternal.child_value("cube/state"))
) eternaldict.replace_int_array("item_kind", 12, eternal.child_value("cube/item/kind"))
eternaldict.replace_int_array( eternaldict.replace_int_array("item_value", 12, eternal.child_value("cube/item/value"))
"state", 12, eternal.child_value("cube/state") eternaldict.replace_int_array("norma_kind", 12, eternal.child_value("cube/norma/kind"))
) eternaldict.replace_int_array("norma_value", 12, eternal.child_value("cube/norma/value"))
eternaldict.replace_int_array( eternaldict.replace_int_array("norma_param", 12, eternal.child_value("cube/norma/param"))
"item_kind", 12, eternal.child_value("cube/item/kind")
)
eternaldict.replace_int_array(
"item_value", 12, eternal.child_value("cube/item/value")
)
eternaldict.replace_int_array(
"norma_kind", 12, eternal.child_value("cube/norma/kind")
)
eternaldict.replace_int_array(
"norma_value", 12, eternal.child_value("cube/norma/value")
)
eternaldict.replace_int_array(
"norma_param", 12, eternal.child_value("cube/norma/param")
)
digdigdict.replace_dict("eternal", eternaldict) digdigdict.replace_dict("eternal", eternaldict)
if self.ENABLE_GARNET: if self.ENABLE_GARNET:
@ -1521,12 +1382,8 @@ class JubeatQubell(
if old is not None: if old is not None:
olddict.replace_int("need_point", old.child_value("need_point")) olddict.replace_int("need_point", old.child_value("need_point"))
olddict.replace_int("point", old.child_value("point")) olddict.replace_int("point", old.child_value("point"))
olddict.replace_int_array( olddict.replace_int_array("excavated_point", 5, old.child_value("excavated_point"))
"excavated_point", 5, old.child_value("excavated_point") olddict.replace_int_array("excavated", 5, old.child_value("excavated"))
)
olddict.replace_int_array(
"excavated", 5, old.child_value("excavated")
)
olddict.replace_int_array("param", 5, old.child_value("param")) olddict.replace_int_array("param", 5, old.child_value("param"))
digdigdict.replace_dict("old", olddict) digdigdict.replace_dict("old", olddict)
@ -1599,9 +1456,7 @@ class JubeatQubell(
if flags & bit > 0: if flags & bit > 0:
medal = max(medal, mapping[bit]) medal = max(medal, mapping[bit])
self.update_score( self.update_score(userid, timestamp, songid, chart, points, medal, combo, ghost, stats)
userid, timestamp, songid, chart, points, medal, combo, ghost, stats
)
# Born stuff # Born stuff
born = player.child("born") born = player.child("born")

View File

@ -34,22 +34,15 @@ class JubeatSaucer(
return JubeatCopiousAppend(self.data, self.config, self.model) return JubeatCopiousAppend(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert daily FC challenges into the DB. Insert daily FC challenges into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "fc_challenge", "daily"):
cls.game, cls.version, "fc_challenge", "daily"
):
# Generate a new list of two FC challenge songs. # Generate a new list of two FC challenge songs.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = set( all_songs = set(song.id for song in data.local.music.get_all_songs(cls.game, cls.version))
song.id
for song in data.local.music.get_all_songs(cls.game, cls.version)
)
if all_songs: if all_songs:
today_song = random.sample(all_songs, 1)[0] today_song = random.sample(all_songs, 1)[0]
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -73,9 +66,7 @@ class JubeatSaucer(
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "fc_challenge", "daily")
cls.game, cls.version, "fc_challenge", "daily"
)
return events return events
@classmethod @classmethod
@ -215,9 +206,7 @@ class JubeatSaucer(
force_unlock = game_config.get_bool("force_song_unlock") force_unlock = game_config.get_bool("force_song_unlock")
# Allow figuring out owned songs. # Allow figuring out owned songs.
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
owned_songs: Set[int] = set() owned_songs: Set[int] = set()
owned_secrets: Set[int] = set() owned_secrets: Set[int] = set()
for achievement in achievements: for achievement in achievements:
@ -242,9 +231,7 @@ class JubeatSaucer(
info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt"))) info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt")))
info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt"))) info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt")))
if "total_best_score" in profile: if "total_best_score" in profile:
info.add_child( info.add_child(Node.s32("total_best_score", profile.get_int("total_best_score")))
Node.s32("total_best_score", profile.get_int("total_best_score"))
)
# Looks to be set to true when there's an old profile, stops tutorial from # Looks to be set to true when there's an old profile, stops tutorial from
# happening on first load. # happening on first load.
@ -266,9 +253,7 @@ class JubeatSaucer(
item.add_child( item.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 32) ([-1] * 32) if force_unlock else self.create_owned_items(owned_songs, 32),
if force_unlock
else self.create_owned_items(owned_songs, 32),
) )
) )
item.add_child( item.add_child(
@ -282,25 +267,15 @@ class JubeatSaucer(
) )
) )
item.add_child(Node.s16("theme_list", profile.get_int("theme_list", -1))) item.add_child(Node.s16("theme_list", profile.get_int("theme_list", -1)))
item.add_child( item.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list", 2, [-1] * 2)))
Node.s32_array( item.add_child(Node.s32_array("parts_list", profile.get_int_array("parts_list", 96, [-1] * 96)))
"marker_list", profile.get_int_array("marker_list", 2, [-1] * 2)
)
)
item.add_child(
Node.s32_array(
"parts_list", profile.get_int_array("parts_list", 96, [-1] * 96)
)
)
new = Node.void("new") new = Node.void("new")
item.add_child(new) item.add_child(new)
new.add_child( new.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 32) ([-1] * 32) if force_unlock else self.create_owned_items(owned_secrets, 32),
if force_unlock
else self.create_owned_items(owned_secrets, 32),
) )
) )
new.add_child( new.add_child(
@ -314,11 +289,7 @@ class JubeatSaucer(
) )
) )
new.add_child(Node.s16("theme_list", profile.get_int("theme_list_new", -1))) new.add_child(Node.s16("theme_list", profile.get_int("theme_list_new", -1)))
new.add_child( new.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list_new", 2, [-1] * 2)))
Node.s32_array(
"marker_list", profile.get_int_array("marker_list_new", 2, [-1] * 2)
)
)
# Last played data, for showing cursor and such # Last played data, for showing cursor and such
lastdict = profile.get_dict("last") lastdict = profile.get_dict("last")
@ -393,9 +364,7 @@ class JubeatSaucer(
collabo.add_child(Node.bool("completed", False)) collabo.add_child(Node.bool("completed", False))
# Daily FC challenge. # Daily FC challenge.
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "fc_challenge")
self.game, self.version, "fc_challenge"
)
if entry is None: if entry is None:
entry = ValidatedDict() entry = ValidatedDict()
@ -510,9 +479,7 @@ class JubeatSaucer(
music.add_child(Node.s32("price_s32", routedata["price"])) music.add_child(Node.s32("price_s32", routedata["price"]))
# Look up any updated satisfaction stored by the game # Look up any updated satisfaction stored by the game
routesaved = self.data.local.user.get_achievement( routesaved = self.data.local.user.get_achievement(self.game, self.version, userid, route_no + 1, "route")
self.game, self.version, userid, route_no + 1, "route"
)
if routesaved is None: if routesaved is None:
routesaved = ValidatedDict() routesaved = ValidatedDict()
satisfaction = routesaved.get_int("satisfaction", routedata["satisfaction"]) satisfaction = routesaved.get_int("satisfaction", routedata["satisfaction"])
@ -697,9 +664,7 @@ class JubeatSaucer(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
newprofile.replace_bool("saved", True) newprofile.replace_bool("saved", True)
data = request.child("data") data = request.child("data")
@ -727,44 +692,28 @@ class JubeatSaucer(
newprofile.replace_int("save_cnt", info.child_value("save_cnt")) newprofile.replace_int("save_cnt", info.child_value("save_cnt"))
newprofile.replace_int("saved_cnt", info.child_value("saved_cnt")) newprofile.replace_int("saved_cnt", info.child_value("saved_cnt"))
newprofile.replace_int("fc_cnt", info.child_value("fc_cnt")) newprofile.replace_int("fc_cnt", info.child_value("fc_cnt"))
newprofile.replace_int( newprofile.replace_int("ex_cnt", info.child_value("exc_cnt")) # Not a mistake, Jubeat is weird
"ex_cnt", info.child_value("exc_cnt")
) # Not a mistake, Jubeat is weird
newprofile.replace_int("pf_cnt", info.child_value("pf_cnt")) newprofile.replace_int("pf_cnt", info.child_value("pf_cnt"))
newprofile.replace_int("clear_cnt", info.child_value("clear_cnt")) newprofile.replace_int("clear_cnt", info.child_value("clear_cnt"))
newprofile.replace_int("match_cnt", info.child_value("match_cnt")) newprofile.replace_int("match_cnt", info.child_value("match_cnt"))
newprofile.replace_int("beat_cnt", info.child_value("beat_cnt")) newprofile.replace_int("beat_cnt", info.child_value("beat_cnt"))
newprofile.replace_int( newprofile.replace_int("total_best_score", info.child_value("total_best_score"))
"total_best_score", info.child_value("total_best_score")
)
newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt")) newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt"))
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
newprofile.replace_int_array( newprofile.replace_int_array("title_list", 96, item.child_value("title_list"))
"title_list", 96, item.child_value("title_list")
)
newprofile.replace_int("theme_list", item.child_value("theme_list")) newprofile.replace_int("theme_list", item.child_value("theme_list"))
newprofile.replace_int_array( newprofile.replace_int_array("marker_list", 2, item.child_value("marker_list"))
"marker_list", 2, item.child_value("marker_list") newprofile.replace_int_array("parts_list", 96, item.child_value("parts_list"))
) newprofile.replace_int_array("title_list_new", 96, item.child_value("title_new"))
newprofile.replace_int_array(
"parts_list", 96, item.child_value("parts_list")
)
newprofile.replace_int_array(
"title_list_new", 96, item.child_value("title_new")
)
newprofile.replace_int("theme_list_new", item.child_value("theme_new")) newprofile.replace_int("theme_list_new", item.child_value("theme_new"))
newprofile.replace_int_array( newprofile.replace_int_array("marker_list_new", 2, item.child_value("marker_new"))
"marker_list_new", 2, item.child_value("marker_new")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_songs = self.calculate_owned_items( owned_songs = self.calculate_owned_items(item.child_value("secret_list"))
item.child_value("secret_list")
)
for index in owned_songs: for index in owned_songs:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -775,9 +724,7 @@ class JubeatSaucer(
{}, {},
) )
owned_secrets = self.calculate_owned_items( owned_secrets = self.calculate_owned_items(item.child_value("secret_new"))
item.child_value("secret_new")
)
for index in owned_secrets: for index in owned_secrets:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -791,9 +738,7 @@ class JubeatSaucer(
# Grab bistro progress # Grab bistro progress
bistro = player.child("bistro") bistro = player.child("bistro")
if bistro is not None: if bistro is not None:
newprofile.replace_int( newprofile.replace_int("bistro_carry_over", bistro.child_value("carry_over"))
"bistro_carry_over", bistro.child_value("carry_over")
)
chefdata = newprofile.get_dict("chef") chefdata = newprofile.get_dict("chef")
chef = bistro.child("chef") chef = bistro.child("chef")
@ -877,9 +822,7 @@ class JubeatSaucer(
if flags & bit > 0: if flags & bit > 0:
medal = max(medal, mapping[bit]) medal = max(medal, mapping[bit])
self.update_score( self.update_score(userid, timestamp, songid, chart, points, medal, combo, ghost)
userid, timestamp, songid, chart, points, medal, combo, ghost
)
# Save back last information gleaned from results # Save back last information gleaned from results
newprofile.replace_dict("last", last) newprofile.replace_dict("last", last)
@ -889,9 +832,7 @@ class JubeatSaucer(
return newprofile return newprofile
def format_scores( def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
self, userid: UserID, profile: Profile, scores: List[Score]
) -> Node:
root = Node.void("gametop") root = Node.void("gametop")
datanode = Node.void("data") datanode = Node.void("data")
root.add_child(datanode) root.add_child(datanode)
@ -958,24 +899,12 @@ class JubeatSaucer(
playdata.add_child(musicdata) playdata.add_child(musicdata)
musicdata.set_attribute("music_id", scoreid) musicdata.set_attribute("music_id", scoreid)
musicdata.add_child( musicdata.add_child(Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)))
Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)) musicdata.add_child(Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)))
) musicdata.add_child(Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3)))
musicdata.add_child( musicdata.add_child(Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3)))
Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)) musicdata.add_child(Node.s32_array("score", scoredata.get_int_array("points", 3)))
) musicdata.add_child(Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3)))
musicdata.add_child(
Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3))
)
musicdata.add_child(
Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3))
)
musicdata.add_child(
Node.s32_array("score", scoredata.get_int_array("points", 3))
)
musicdata.add_child(
Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3))
)
ghosts = scoredata.get("ghost", [None, None, None]) ghosts = scoredata.get("ghost", [None, None, None])
for i in range(len(ghosts)): for i in range(len(ghosts)):

View File

@ -46,22 +46,15 @@ class JubeatSaucerFulfill(
return JubeatSaucer(self.data, self.config, self.model) return JubeatSaucer(self.data, self.config, self.model)
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Insert daily FC challenges into the DB. Insert daily FC challenges into the DB.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "fc_challenge", "daily"):
cls.game, cls.version, "fc_challenge", "daily"
):
# Generate a new list of two FC challenge songs. # Generate a new list of two FC challenge songs.
start_time, end_time = data.local.network.get_schedule_duration("daily") start_time, end_time = data.local.network.get_schedule_duration("daily")
all_songs = set( all_songs = set(song.id for song in data.local.music.get_all_songs(cls.game, cls.version))
song.id
for song in data.local.music.get_all_songs(cls.game, cls.version)
)
if len(all_songs) >= 2: if len(all_songs) >= 2:
daily_songs = random.sample(all_songs, 2) daily_songs = random.sample(all_songs, 2)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -87,9 +80,7 @@ class JubeatSaucerFulfill(
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "fc_challenge", "daily")
cls.game, cls.version, "fc_challenge", "daily"
)
return events return events
@classmethod @classmethod
@ -289,9 +280,7 @@ class JubeatSaucerFulfill(
result.add_child(Node.s32_array("score", scores)) result.add_child(Node.s32_array("score", scores))
# Last course ID # Last course ID
last_course_id = Node.s32( last_course_id = Node.s32("last_course_id", profile.get_dict("last").get_int("last_course_id", -1))
"last_course_id", profile.get_dict("last").get_int("last_course_id", -1)
)
data.add_child(last_course_id) data.add_child(last_course_id)
return gametop return gametop
@ -350,9 +339,7 @@ class JubeatSaucerFulfill(
force_unlock = game_config.get_bool("force_song_unlock") force_unlock = game_config.get_bool("force_song_unlock")
# Allow figuring out owned songs. # Allow figuring out owned songs.
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
owned_songs: Set[int] = set() owned_songs: Set[int] = set()
owned_secrets: Set[int] = set() owned_secrets: Set[int] = set()
for achievement in achievements: for achievement in achievements:
@ -377,13 +364,9 @@ class JubeatSaucerFulfill(
info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt"))) info.add_child(Node.s32("beat_cnt", profile.get_int("beat_cnt")))
info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt"))) info.add_child(Node.s32("mynews_cnt", profile.get_int("mynews_cnt")))
info.add_child(Node.s32("extra_point", profile.get_int("extra_point"))) info.add_child(Node.s32("extra_point", profile.get_int("extra_point")))
info.add_child( info.add_child(Node.bool("is_extra_played", profile.get_bool("is_extra_played")))
Node.bool("is_extra_played", profile.get_bool("is_extra_played"))
)
if "total_best_score" in profile: if "total_best_score" in profile:
info.add_child( info.add_child(Node.s32("total_best_score", profile.get_int("total_best_score")))
Node.s32("total_best_score", profile.get_int("total_best_score"))
)
# Looks to be set to true when there's an old profile, stops tutorial from # Looks to be set to true when there's an old profile, stops tutorial from
# happening on first load. # happening on first load.
@ -412,9 +395,7 @@ class JubeatSaucerFulfill(
item.add_child( item.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 32) ([-1] * 32) if force_unlock else self.create_owned_items(owned_songs, 32),
if force_unlock
else self.create_owned_items(owned_songs, 32),
) )
) )
item.add_child( item.add_child(
@ -428,25 +409,15 @@ class JubeatSaucerFulfill(
) )
) )
item.add_child(Node.s16("theme_list", profile.get_int("theme_list", -1))) item.add_child(Node.s16("theme_list", profile.get_int("theme_list", -1)))
item.add_child( item.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list", 2, [-1] * 2)))
Node.s32_array( item.add_child(Node.s32_array("parts_list", profile.get_int_array("parts_list", 96, [-1] * 96)))
"marker_list", profile.get_int_array("marker_list", 2, [-1] * 2)
)
)
item.add_child(
Node.s32_array(
"parts_list", profile.get_int_array("parts_list", 96, [-1] * 96)
)
)
new = Node.void("new") new = Node.void("new")
item.add_child(new) item.add_child(new)
new.add_child( new.add_child(
Node.s32_array( Node.s32_array(
"secret_list", "secret_list",
([-1] * 32) ([-1] * 32) if force_unlock else self.create_owned_items(owned_secrets, 32),
if force_unlock
else self.create_owned_items(owned_secrets, 32),
) )
) )
new.add_child( new.add_child(
@ -460,11 +431,7 @@ class JubeatSaucerFulfill(
) )
) )
new.add_child(Node.s16("theme_list", profile.get_int("theme_list_new", -1))) new.add_child(Node.s16("theme_list", profile.get_int("theme_list_new", -1)))
new.add_child( new.add_child(Node.s32_array("marker_list", profile.get_int_array("marker_list_new", 2, [-1] * 2)))
Node.s32_array(
"marker_list", profile.get_int_array("marker_list_new", 2, [-1] * 2)
)
)
# Last played data, for showing cursor and such # Last played data, for showing cursor and such
lastdict = profile.get_dict("last") lastdict = profile.get_dict("last")
@ -498,37 +465,23 @@ class JubeatSaucerFulfill(
player.add_child(macchiato) player.add_child(macchiato)
macchiato.add_child(Node.s32("pack_id", macchiatodict.get_int("pack_id"))) macchiato.add_child(Node.s32("pack_id", macchiatodict.get_int("pack_id")))
macchiato.add_child(Node.u16("bean_num", macchiatodict.get_int("bean_num"))) macchiato.add_child(Node.u16("bean_num", macchiatodict.get_int("bean_num")))
macchiato.add_child( macchiato.add_child(Node.s32("daily_milk_num", macchiatodict.get_int("daily_milk_num")))
Node.s32("daily_milk_num", macchiatodict.get_int("daily_milk_num"))
)
macchiato.add_child( macchiato.add_child(
Node.bool( Node.bool(
"is_received_daily_milk", "is_received_daily_milk",
macchiatodict.get_bool("is_received_daily_milk"), macchiatodict.get_bool("is_received_daily_milk"),
) )
) )
macchiato.add_child( macchiato.add_child(Node.s32("today_tune_cnt", macchiatodict.get_int("today_tune_cnt")))
Node.s32("today_tune_cnt", macchiatodict.get_int("today_tune_cnt"))
)
macchiato.add_child( macchiato.add_child(
Node.s32_array( Node.s32_array(
"daily_milk_bonus", "daily_milk_bonus",
macchiatodict.get_int_array( macchiatodict.get_int_array("daily_milk_bonus", 9, [-1, -1, -1, -1, -1, -1, -1, -1, -1]),
"daily_milk_bonus", 9, [-1, -1, -1, -1, -1, -1, -1, -1, -1]
),
) )
) )
macchiato.add_child( macchiato.add_child(Node.s32("daily_play_burst", macchiatodict.get_int("daily_play_burst")))
Node.s32("daily_play_burst", macchiatodict.get_int("daily_play_burst")) macchiato.add_child(Node.bool("sub_menu_is_completed", macchiatodict.get_bool("sub_menu_is_completed")))
) macchiato.add_child(Node.s32("compensation_milk", macchiatodict.get_int("compensation_milk")))
macchiato.add_child(
Node.bool(
"sub_menu_is_completed", macchiatodict.get_bool("sub_menu_is_completed")
)
)
macchiato.add_child(
Node.s32("compensation_milk", macchiatodict.get_int("compensation_milk"))
)
macchiato.add_child(Node.s32("match_cnt", macchiatodict.get_int("match_cnt"))) macchiato.add_child(Node.s32("match_cnt", macchiatodict.get_int("match_cnt")))
# Probably never will support this # Probably never will support this
@ -593,9 +546,7 @@ class JubeatSaucerFulfill(
rivallist.set_attribute("count", str(rivalcount)) rivallist.set_attribute("count", str(rivalcount))
# Full combo daily challenge. # Full combo daily challenge.
entry = self.data.local.game.get_time_sensitive_settings( entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, "fc_challenge")
self.game, self.version, "fc_challenge"
)
if entry is None: if entry is None:
entry = ValidatedDict() entry = ValidatedDict()
@ -779,9 +730,7 @@ class JubeatSaucerFulfill(
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
newprofile.replace_bool("saved", True) newprofile.replace_bool("saved", True)
data = request.child("data") data = request.child("data")
@ -809,21 +758,15 @@ class JubeatSaucerFulfill(
newprofile.replace_int("save_cnt", info.child_value("save_cnt")) newprofile.replace_int("save_cnt", info.child_value("save_cnt"))
newprofile.replace_int("saved_cnt", info.child_value("saved_cnt")) newprofile.replace_int("saved_cnt", info.child_value("saved_cnt"))
newprofile.replace_int("fc_cnt", info.child_value("fc_cnt")) newprofile.replace_int("fc_cnt", info.child_value("fc_cnt"))
newprofile.replace_int( newprofile.replace_int("ex_cnt", info.child_value("exc_cnt")) # Not a mistake, Jubeat is weird
"ex_cnt", info.child_value("exc_cnt")
) # Not a mistake, Jubeat is weird
newprofile.replace_int("pf_cnt", info.child_value("pf_cnt")) newprofile.replace_int("pf_cnt", info.child_value("pf_cnt"))
newprofile.replace_int("clear_cnt", info.child_value("clear_cnt")) newprofile.replace_int("clear_cnt", info.child_value("clear_cnt"))
newprofile.replace_int("match_cnt", info.child_value("match_cnt")) newprofile.replace_int("match_cnt", info.child_value("match_cnt"))
newprofile.replace_int("beat_cnt", info.child_value("beat_cnt")) newprofile.replace_int("beat_cnt", info.child_value("beat_cnt"))
newprofile.replace_int( newprofile.replace_int("total_best_score", info.child_value("total_best_score"))
"total_best_score", info.child_value("total_best_score")
)
newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt")) newprofile.replace_int("mynews_cnt", info.child_value("mynews_cnt"))
newprofile.replace_int("extra_point", info.child_value("extra_point")) newprofile.replace_int("extra_point", info.child_value("extra_point"))
newprofile.replace_bool( newprofile.replace_bool("is_extra_played", info.child_value("is_extra_played"))
"is_extra_played", info.child_value("is_extra_played")
)
last.replace_int("expert_option", info.child_value("expert_option")) last.replace_int("expert_option", info.child_value("expert_option"))
last.replace_int("matching", info.child_value("matching")) last.replace_int("matching", info.child_value("matching"))
@ -833,29 +776,17 @@ class JubeatSaucerFulfill(
# Grab unlock progress # Grab unlock progress
item = player.child("item") item = player.child("item")
if item is not None: if item is not None:
newprofile.replace_int_array( newprofile.replace_int_array("title_list", 96, item.child_value("title_list"))
"title_list", 96, item.child_value("title_list")
)
newprofile.replace_int("theme_list", item.child_value("theme_list")) newprofile.replace_int("theme_list", item.child_value("theme_list"))
newprofile.replace_int_array( newprofile.replace_int_array("marker_list", 2, item.child_value("marker_list"))
"marker_list", 2, item.child_value("marker_list") newprofile.replace_int_array("parts_list", 96, item.child_value("parts_list"))
) newprofile.replace_int_array("title_list_new", 96, item.child_value("title_new"))
newprofile.replace_int_array(
"parts_list", 96, item.child_value("parts_list")
)
newprofile.replace_int_array(
"title_list_new", 96, item.child_value("title_new")
)
newprofile.replace_int("theme_list_new", item.child_value("theme_new")) newprofile.replace_int("theme_list_new", item.child_value("theme_new"))
newprofile.replace_int_array( newprofile.replace_int_array("marker_list_new", 2, item.child_value("marker_new"))
"marker_list_new", 2, item.child_value("marker_new")
)
if not force_unlock: if not force_unlock:
# Don't persist if we're force-unlocked, this data will be bogus. # Don't persist if we're force-unlocked, this data will be bogus.
owned_songs = self.calculate_owned_items( owned_songs = self.calculate_owned_items(item.child_value("secret_list"))
item.child_value("secret_list")
)
for index in owned_songs: for index in owned_songs:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -866,9 +797,7 @@ class JubeatSaucerFulfill(
{}, {},
) )
owned_secrets = self.calculate_owned_items( owned_secrets = self.calculate_owned_items(item.child_value("secret_new"))
item.child_value("secret_new")
)
for index in owned_secrets: for index in owned_secrets:
self.data.local.user.put_achievement( self.data.local.user.put_achievement(
self.game, self.game,
@ -885,31 +814,19 @@ class JubeatSaucerFulfill(
if macchiato is not None: if macchiato is not None:
macchiatodict.replace_int("pack_id", macchiato.child_value("pack_id")) macchiatodict.replace_int("pack_id", macchiato.child_value("pack_id"))
macchiatodict.replace_int("bean_num", macchiato.child_value("bean_num")) macchiatodict.replace_int("bean_num", macchiato.child_value("bean_num"))
macchiatodict.replace_int( macchiatodict.replace_int("daily_milk_num", macchiato.child_value("daily_milk_num"))
"daily_milk_num", macchiato.child_value("daily_milk_num")
)
macchiatodict.replace_bool( macchiatodict.replace_bool(
"is_received_daily_milk", "is_received_daily_milk",
macchiato.child_value("is_received_daily_milk"), macchiato.child_value("is_received_daily_milk"),
) )
macchiatodict.replace_bool( macchiatodict.replace_bool("sub_menu_is_completed", macchiato.child_value("sub_menu_is_completed"))
"sub_menu_is_completed", macchiato.child_value("sub_menu_is_completed") macchiatodict.replace_int("today_tune_cnt", macchiato.child_value("today_tune_cnt"))
) macchiatodict.replace_int_array("daily_milk_bonus", 9, macchiato.child_value("daily_milk_bonus"))
macchiatodict.replace_int( macchiatodict.replace_int("compensation_milk", macchiato.child_value("compensation_milk"))
"today_tune_cnt", macchiato.child_value("today_tune_cnt")
)
macchiatodict.replace_int_array(
"daily_milk_bonus", 9, macchiato.child_value("daily_milk_bonus")
)
macchiatodict.replace_int(
"compensation_milk", macchiato.child_value("compensation_milk")
)
macchiatodict.replace_int("match_cnt", macchiato.child_value("match_cnt")) macchiatodict.replace_int("match_cnt", macchiato.child_value("match_cnt"))
macchiatodict.replace_int("used_bean", macchiato.child_value("used_bean")) macchiatodict.replace_int("used_bean", macchiato.child_value("used_bean"))
macchiatodict.replace_int("used_milk", macchiato.child_value("used_milk")) macchiatodict.replace_int("used_milk", macchiato.child_value("used_milk"))
macchiatodict.replace_int( macchiatodict.replace_int("daily_play_burst", macchiato.child_value("daily_play_burst"))
"daily_play_burst", macchiato.child_value("daily_play_burst")
)
newprofile.replace_dict("macchiato", macchiatodict) newprofile.replace_dict("macchiato", macchiatodict)
# Get timestamps for played songs # Get timestamps for played songs
@ -967,9 +884,7 @@ class JubeatSaucerFulfill(
if flags & bit > 0: if flags & bit > 0:
medal = max(medal, mapping[bit]) medal = max(medal, mapping[bit])
self.update_score( self.update_score(userid, timestamp, songid, chart, points, medal, combo, ghost)
userid, timestamp, songid, chart, points, medal, combo, ghost
)
# Grab the course results as well # Grab the course results as well
course = data.child("course") course = data.child("course")
@ -1002,9 +917,7 @@ class JubeatSaucerFulfill(
return newprofile return newprofile
def format_scores( def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
self, userid: UserID, profile: Profile, scores: List[Score]
) -> Node:
root = Node.void("gametop") root = Node.void("gametop")
datanode = Node.void("data") datanode = Node.void("data")
root.add_child(datanode) root.add_child(datanode)
@ -1071,24 +984,12 @@ class JubeatSaucerFulfill(
playdata.add_child(musicdata) playdata.add_child(musicdata)
musicdata.set_attribute("music_id", scoreid) musicdata.set_attribute("music_id", scoreid)
musicdata.add_child( musicdata.add_child(Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)))
Node.s32_array("play_cnt", scoredata.get_int_array("play_cnt", 3)) musicdata.add_child(Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)))
) musicdata.add_child(Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3)))
musicdata.add_child( musicdata.add_child(Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3)))
Node.s32_array("clear_cnt", scoredata.get_int_array("clear_cnt", 3)) musicdata.add_child(Node.s32_array("score", scoredata.get_int_array("points", 3)))
) musicdata.add_child(Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3)))
musicdata.add_child(
Node.s32_array("fc_cnt", scoredata.get_int_array("fc_cnt", 3))
)
musicdata.add_child(
Node.s32_array("ex_cnt", scoredata.get_int_array("ex_cnt", 3))
)
musicdata.add_child(
Node.s32_array("score", scoredata.get_int_array("points", 3))
)
musicdata.add_child(
Node.s8_array("clear", scoredata.get_int_array("clear_flags", 3))
)
ghosts = scoredata.get("ghost", [None, None, None]) ghosts = scoredata.get("ghost", [None, None, None])
for i in range(len(ghosts)): for i in range(len(ghosts)):

View File

@ -52,7 +52,9 @@ class MetalGearArcade(
if reqtype == "S_SRVMSG" and reqkey == "INFO": if reqtype == "S_SRVMSG" and reqkey == "INFO":
# Generate system message # Generate system message
settings1_str = "2011081000:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1" settings1_str = (
"2011081000:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1"
)
settings2_str = "1,1,1,1,1,1,1,1,1,1,1,1,1,1" settings2_str = "1,1,1,1,1,1,1,1,1,1,1,1,1,1"
# Send it to the client, making sure to inform the client that it was valid. # Send it to the client, making sure to inform the client that it was valid.
@ -82,9 +84,7 @@ class MetalGearArcade(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is None: if userid is None:
root = Node.void("playerdata") root = Node.void("playerdata")
root.add_child( root.add_child(Node.s32("result", 1)) # Unclear if this is the right thing to do here.
Node.s32("result", 1)
) # Unclear if this is the right thing to do here.
return root return root
# Extract new profile info from old profile # Extract new profile info from old profile
@ -117,9 +117,7 @@ class MetalGearArcade(
return self.format_profile(userid, profiletypes, profile) return self.format_profile(userid, profiletypes, profile)
else: else:
root = Node.void("playerdata") root = Node.void("playerdata")
root.add_child( root.add_child(Node.s32("result", 1)) # Unclear if this is the right thing to do here.
Node.s32("result", 1)
) # Unclear if this is the right thing to do here.
return root return root
def handle_playerdata_usergamedata_scorerank_request(self, request: Node) -> Node: def handle_playerdata_usergamedata_scorerank_request(self, request: Node) -> Node:
@ -151,9 +149,7 @@ class MetalGearArcade(
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is None: if userid is None:
root = Node.void("matching") root = Node.void("matching")
root.add_child( root.add_child(Node.s32("result", -1)) # Set to error so matching doesn't happen.
Node.s32("result", -1)
) # Set to error so matching doesn't happen.
return root return root
# Game sends how long it intends to wait, so we should use that. # Game sends how long it intends to wait, so we should use that.
@ -162,21 +158,13 @@ class MetalGearArcade(
# Look up active lobbies, see if there was a previous one for us. # Look up active lobbies, see if there was a previous one for us.
# Matchmaking takes at most 60 seconds, so assume any lobbies older # Matchmaking takes at most 60 seconds, so assume any lobbies older
# than this are dead. # than this are dead.
lobbies = self.data.local.lobby.get_all_lobbies( lobbies = self.data.local.lobby.get_all_lobbies(self.game, self.version, max_age=wait_time)
self.game, self.version, max_age=wait_time
)
previous_hosted_lobbies = [True for uid, _ in lobbies if uid == userid] previous_hosted_lobbies = [True for uid, _ in lobbies if uid == userid]
previous_joined_lobbies = [ previous_joined_lobbies = [(uid, lobby) for uid, lobby in lobbies if userid in lobby["participants"]]
(uid, lobby) for uid, lobby in lobbies if userid in lobby["participants"]
]
# See if there's a random lobby we can be slotted into. Don't choose potentially # See if there's a random lobby we can be slotted into. Don't choose potentially
# our old one, since it will be overwritten by a new entry, if we were ever a host. # our old one, since it will be overwritten by a new entry, if we were ever a host.
nonfull_lobbies = [ nonfull_lobbies = [(uid, lobby) for uid, lobby in lobbies if len(lobby["participants"]) < lobby["lobbysize"]]
(uid, lobby)
for uid, lobby in lobbies
if len(lobby["participants"]) < lobby["lobbysize"]
]
# Make sure to put our session information somewhere that we can find again. # Make sure to put our session information somewhere that we can find again.
self.data.local.lobby.put_play_session_info( self.data.local.lobby.put_play_session_info(
@ -225,18 +213,10 @@ class MetalGearArcade(
Node.s32("result", 1) Node.s32("result", 1)
) # Setting this to 1 makes the client consider itself a guest and join a host. ) # Setting this to 1 makes the client consider itself a guest and join a host.
root.add_child(Node.s64("hostid", lobby.get_int("id"))) root.add_child(Node.s64("hostid", lobby.get_int("id")))
root.add_child( root.add_child(Node.string("hostip_g", host_play_session_info.get_str("joinip")))
Node.string("hostip_g", host_play_session_info.get_str("joinip")) root.add_child(Node.s32("hostport_g", host_play_session_info.get_int("joinport")))
) root.add_child(Node.string("hostip_l", host_play_session_info.get_str("localip")))
root.add_child( root.add_child(Node.s32("hostport_l", host_play_session_info.get_int("localport")))
Node.s32("hostport_g", host_play_session_info.get_int("joinport"))
)
root.add_child(
Node.string("hostip_l", host_play_session_info.get_str("localip"))
)
root.add_child(
Node.s32("hostport_l", host_play_session_info.get_int("localport"))
)
return root return root
# The game does weird things if you let it wait as long as its own countdown, # The game does weird things if you let it wait as long as its own countdown,
@ -281,16 +261,11 @@ class MetalGearArcade(
# List all lobbies out, find the one that we're either a host or a guest of. # List all lobbies out, find the one that we're either a host or a guest of.
lobbies = self.data.local.lobby.get_all_lobbies(self.game, self.version) lobbies = self.data.local.lobby.get_all_lobbies(self.game, self.version)
info_by_uid = { info_by_uid = {
uid: data uid: data for uid, data in self.data.local.lobby.get_all_play_session_infos(self.game, self.version)
for uid, data in self.data.local.lobby.get_all_play_session_infos(
self.game, self.version
)
} }
# We should be able to filter by host_id that the game gave us. # We should be able to filter by host_id that the game gave us.
joined_lobby = [ joined_lobby = [(uid, lobby) for uid, lobby in lobbies if lobby.get_int("id") == host_id]
(uid, lobby) for uid, lobby in lobbies if lobby.get_int("id") == host_id
]
if len(joined_lobby) != 1: if len(joined_lobby) != 1:
# This shouldn't happen. # This shouldn't happen.
root = Node.void("matching") root = Node.void("matching")
@ -299,14 +274,10 @@ class MetalGearArcade(
# Calculate creation time, figure out when to join the match after that. # Calculate creation time, figure out when to join the match after that.
host_uid, lobby = joined_lobby[0] host_uid, lobby = joined_lobby[0]
time_left = max( time_left = max(lobby.get_int("waittime") - (Time.now() - lobby.get_int("createtime")), 0)
lobby.get_int("waittime") - (Time.now() - lobby.get_int("createtime")), 0
)
root = Node.void("matching") root = Node.void("matching")
root.add_child( root.add_child(Node.s32("result", 0 if time_left > 0 else 1)) # We send 1 to start the match.
Node.s32("result", 0 if time_left > 0 else 1)
) # We send 1 to start the match.
root.add_child(Node.s32("prwtime", time_left)) root.add_child(Node.s32("prwtime", time_left))
matchlist = Node.void("matchlist") matchlist = Node.void("matchlist")
root.add_child(matchlist) root.add_child(matchlist)
@ -339,9 +310,7 @@ class MetalGearArcade(
return root return root
def format_profile( def format_profile(self, userid: UserID, profiletypes: List[str], profile: Profile) -> Node:
self, userid: UserID, profiletypes: List[str], profile: Profile
) -> Node:
root = Node.void("playerdata") root = Node.void("playerdata")
root.add_child(Node.s32("result", 0)) root.add_child(Node.s32("result", 0))
player = Node.void("player") player = Node.void("player")
@ -371,9 +340,7 @@ class MetalGearArcade(
strdata = b",".join(csvs[2:]) strdata = b",".join(csvs[2:])
d = Node.string("d", base64.b64encode(strdata).decode("ascii")) d = Node.string("d", base64.b64encode(strdata).decode("ascii"))
record.add_child(d) record.add_child(d)
d.add_child( d.add_child(Node.string("bin1", base64.b64encode(bindata).decode("ascii")))
Node.string("bin1", base64.b64encode(bindata).decode("ascii"))
)
# Remember that we had this record # Remember that we had this record
records = records + 1 records = records + 1
@ -381,9 +348,7 @@ class MetalGearArcade(
player.add_child(Node.u32("record_num", records)) player.add_child(Node.u32("record_num", records))
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile, is_new: bool) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile, is_new: bool
) -> Profile:
# Profile save request, data values are base64 encoded. # Profile save request, data values are base64 encoded.
# d is a CSV, and bin1 is binary data. # d is a CSV, and bin1 is binary data.
newprofile = oldprofile.clone() newprofile = oldprofile.clone()

View File

@ -95,9 +95,7 @@ class MusecaBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# Now, return it # Now, return it
return self.format_profile(userid, profile) return self.format_profile(userid, profile)
def new_profile_by_refid( def new_profile_by_refid(self, refid: Optional[str], name: Optional[str], locid: Optional[int]) -> Node:
self, refid: Optional[str], name: Optional[str], locid: Optional[int]
) -> Node:
""" """
Given a RefID and an optional name, create a profile and then return Given a RefID and an optional name, create a profile and then return
a formatted profile node. Similar rationale to get_profile_by_refid. a formatted profile node. Similar rationale to get_profile_by_refid.
@ -130,9 +128,7 @@ class MusecaBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
return Node.void("game") return Node.void("game")
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
""" """
Base handler for profile parsing. Given a request and an old profile, Base handler for profile parsing. Given a request and an old profile,
return a new profile that's been updated with the contents of the request. return a new profile that's been updated with the contents of the request.
@ -177,21 +173,14 @@ class MusecaBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
} }
# We saw an attempt, keep the total attempts in sync. # We saw an attempt, keep the total attempts in sync.
attempts[attempt.id][attempt.chart]["total"] = ( attempts[attempt.id][attempt.chart]["total"] = attempts[attempt.id][attempt.chart]["total"] + 1
attempts[attempt.id][attempt.chart]["total"] + 1
)
if ( if attempt.data.get_int("clear_type", self.CLEAR_TYPE_FAILED) != self.CLEAR_TYPE_FAILED:
attempt.data.get_int("clear_type", self.CLEAR_TYPE_FAILED)
!= self.CLEAR_TYPE_FAILED
):
# This attempt was a failure, so don't count it against clears of full combos # This attempt was a failure, so don't count it against clears of full combos
continue continue
# It was at least a clear # It was at least a clear
attempts[attempt.id][attempt.chart]["clears"] = ( attempts[attempt.id][attempt.chart]["clears"] = attempts[attempt.id][attempt.chart]["clears"] + 1
attempts[attempt.id][attempt.chart]["clears"] + 1
)
# Merge in remote attempts # Merge in remote attempts
for songid in remote_attempts: for songid in remote_attempts:
@ -205,12 +194,8 @@ class MusecaBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
"clears": 0, "clears": 0,
} }
attempts[songid][songchart]["total"] += remote_attempts[songid][ attempts[songid][songchart]["total"] += remote_attempts[songid][songchart]["plays"]
songchart attempts[songid][songchart]["clears"] += remote_attempts[songid][songchart]["clears"]
]["plays"]
attempts[songid][songchart]["clears"] += remote_attempts[songid][
songchart
]["clears"]
return attempts return attempts
@ -280,9 +265,7 @@ class MusecaBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
scoredata = oldscore.data scoredata = oldscore.data
# Replace grade and clear type # Replace grade and clear type
scoredata.replace_int( scoredata.replace_int("clear_type", max(scoredata.get_int("clear_type"), clear_type))
"clear_type", max(scoredata.get_int("clear_type"), clear_type)
)
history.replace_int("clear_type", clear_type) history.replace_int("clear_type", clear_type)
scoredata.replace_int("grade", max(scoredata.get_int("grade"), grade)) scoredata.replace_int("grade", max(scoredata.get_int("grade"), grade))
history.replace_int("grade", grade) history.replace_int("grade", grade)

View File

@ -34,9 +34,7 @@ class MusecaGameHiscoreHandler(MusecaBase):
# Now, grab user records # Now, grab user records
records = self.data.remote.music.get_all_records(self.game, self.version) records = self.data.remote.music.get_all_records(self.game, self.version)
users = { users = {uid: prof for (uid, prof) in self.get_any_profiles([r[0] for r in records])}
uid: prof for (uid, prof) in self.get_any_profiles([r[0] for r in records])
}
hiscore_allover = Node.void("hiscore_allover") hiscore_allover = Node.void("hiscore_allover")
game.add_child(hiscore_allover) game.add_child(hiscore_allover)
@ -61,14 +59,10 @@ class MusecaGameHiscoreHandler(MusecaBase):
# Now, grab local records # Now, grab local records
area_users = [ area_users = [
uid uid
for (uid, prof) in self.data.local.user.get_all_profiles( for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version)
self.game, self.version
)
if prof.get_int("loc", -1) == locid if prof.get_int("loc", -1) == locid
] ]
records = self.data.local.music.get_all_records( records = self.data.local.music.get_all_records(self.game, self.version, userlist=area_users)
self.game, self.version, userlist=area_users
)
missing_players = [uid for (uid, _) in records if uid not in users] missing_players = [uid for (uid, _) in records if uid not in users]
for uid, prof in self.get_any_profiles(missing_players): for uid, prof in self.get_any_profiles(missing_players):
users[uid] = prof users[uid] = prof
@ -101,9 +95,7 @@ class MusecaGameHiscoreHandler(MusecaBase):
for songid in clears: for songid in clears:
for chart in clears[songid]: for chart in clears[songid]:
if clears[songid][chart]["total"] > 0: if clears[songid][chart]["total"] > 0:
rate = float(clears[songid][chart]["clears"]) / float( rate = float(clears[songid][chart]["clears"]) / float(clears[songid][chart]["total"])
clears[songid][chart]["total"]
)
dnode = Node.void("d") dnode = Node.void("d")
clear_rate.add_child(dnode) clear_rate.add_child(dnode)
dnode.add_child(Node.u32("id", songid)) dnode.add_child(Node.u32("id", songid))

View File

@ -177,9 +177,7 @@ class Museca1(
userid = None userid = None
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
else: else:
scores = [] scores = []
@ -201,11 +199,7 @@ class Museca1(
self.db_to_game_clear_type(score.data.get_int("clear_type")), self.db_to_game_clear_type(score.data.get_int("clear_type")),
) )
) )
music.add_child( music.add_child(Node.u32("score_grade", self.db_to_game_grade(score.data.get_int("grade"))))
Node.u32(
"score_grade", self.db_to_game_grade(score.data.get_int("grade"))
)
)
stats = score.data.get_dict("stats") stats = score.data.get_dict("stats")
music.add_child(Node.u32("btn_rate", stats.get_int("btn_rate"))) music.add_child(Node.u32("btn_rate", stats.get_int("btn_rate")))
music.add_child(Node.u32("long_rate", stats.get_int("long_rate"))) music.add_child(Node.u32("long_rate", stats.get_int("long_rate")))
@ -222,9 +216,7 @@ class Museca1(
game.add_child(Node.u32("gamecoin_packet", profile.get_int("packet"))) game.add_child(Node.u32("gamecoin_packet", profile.get_int("packet")))
game.add_child(Node.u32("gamecoin_block", profile.get_int("block"))) game.add_child(Node.u32("gamecoin_block", profile.get_int("block")))
game.add_child(Node.s16("skill_name_id", profile.get_int("skill_name_id", -1))) game.add_child(Node.s16("skill_name_id", profile.get_int("skill_name_id", -1)))
game.add_child( game.add_child(Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20)))
Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20))
)
game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy"))) game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy")))
game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count"))) game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count")))
@ -253,19 +245,14 @@ class Museca1(
game.add_child(itemnode) game.add_child(itemnode)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for item in achievements: for item in achievements:
if item.type[:5] != "item_": if item.type[:5] != "item_":
continue continue
itemtype = int(item.type[5:]) itemtype = int(item.type[5:])
if ( if game_config.get_bool("force_unlock_songs") and itemtype == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and itemtype == self.GAME_CATALOG_TYPE_SONG
):
# Don't echo unlocked songs, we will add all of them later # Don't echo unlocked songs, we will add all of them later
continue continue
@ -299,22 +286,16 @@ class Museca1(
return game return game
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies # Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value("earned_gamecoin_packet") earned_gamecoin_packet = request.child_value("earned_gamecoin_packet")
if earned_gamecoin_packet is not None: if earned_gamecoin_packet is not None:
newprofile.replace_int( newprofile.replace_int("packet", newprofile.get_int("packet") + earned_gamecoin_packet)
"packet", newprofile.get_int("packet") + earned_gamecoin_packet
)
earned_gamecoin_block = request.child_value("earned_gamecoin_block") earned_gamecoin_block = request.child_value("earned_gamecoin_block")
if earned_gamecoin_block is not None: if earned_gamecoin_block is not None:
newprofile.replace_int( newprofile.replace_int("block", newprofile.get_int("block") + earned_gamecoin_block)
"block", newprofile.get_int("block") + earned_gamecoin_block
)
earned_blaster_energy = request.child_value("earned_blaster_energy") earned_blaster_energy = request.child_value("earned_blaster_energy")
if earned_blaster_energy is not None: if earned_blaster_energy is not None:
newprofile.replace_int( newprofile.replace_int(
@ -325,9 +306,7 @@ class Museca1(
# Miscelaneous stuff # Miscelaneous stuff
newprofile.replace_int("blaster_count", request.child_value("blaster_count")) newprofile.replace_int("blaster_count", request.child_value("blaster_count"))
newprofile.replace_int("skill_name_id", request.child_value("skill_name_id")) newprofile.replace_int("skill_name_id", request.child_value("skill_name_id"))
newprofile.replace_int_array( newprofile.replace_int_array("hidden_param", 20, request.child_value("hidden_param"))
"hidden_param", 20, request.child_value("hidden_param")
)
# Update user's unlock status if we aren't force unlocked # Update user's unlock status if we aren't force unlocked
game_config = self.get_game_config() game_config = self.get_game_config()
@ -342,10 +321,7 @@ class Museca1(
param = child.child_value("param") param = child.child_value("param")
diff_param = child.child_value("diff_param") diff_param = child.child_value("diff_param")
if ( if game_config.get_bool("force_unlock_songs") and item_type == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and item_type == self.GAME_CATALOG_TYPE_SONG
):
# Don't save back songs, because they were force unlocked # Don't save back songs, because they were force unlocked
continue continue

View File

@ -309,9 +309,7 @@ class Museca1Plus(
userid = None userid = None
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
else: else:
scores = [] scores = []
@ -334,11 +332,7 @@ class Museca1Plus(
self.db_to_game_clear_type(score.data.get_int("clear_type")), self.db_to_game_clear_type(score.data.get_int("clear_type")),
) )
) )
music.add_child( music.add_child(Node.u32("score_grade", self.db_to_game_grade(score.data.get_int("grade"))))
Node.u32(
"score_grade", self.db_to_game_grade(score.data.get_int("grade"))
)
)
stats = score.data.get_dict("stats") stats = score.data.get_dict("stats")
music.add_child(Node.u32("btn_rate", stats.get_int("btn_rate"))) music.add_child(Node.u32("btn_rate", stats.get_int("btn_rate")))
music.add_child(Node.u32("long_rate", stats.get_int("long_rate"))) music.add_child(Node.u32("long_rate", stats.get_int("long_rate")))
@ -355,9 +349,7 @@ class Museca1Plus(
game.add_child(Node.u32("gamecoin_packet", profile.get_int("packet"))) game.add_child(Node.u32("gamecoin_packet", profile.get_int("packet")))
game.add_child(Node.u32("gamecoin_block", profile.get_int("block"))) game.add_child(Node.u32("gamecoin_block", profile.get_int("block")))
game.add_child(Node.s16("skill_name_id", profile.get_int("skill_name_id", -1))) game.add_child(Node.s16("skill_name_id", profile.get_int("skill_name_id", -1)))
game.add_child( game.add_child(Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20)))
Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20))
)
game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy"))) game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy")))
game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count"))) game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count")))
@ -391,19 +383,14 @@ class Museca1Plus(
game.add_child(itemnode) game.add_child(itemnode)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for item in achievements: for item in achievements:
if item.type[:5] != "item_": if item.type[:5] != "item_":
continue continue
itemtype = int(item.type[5:]) itemtype = int(item.type[5:])
if ( if game_config.get_bool("force_unlock_songs") and itemtype == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and itemtype == self.GAME_CATALOG_TYPE_SONG
):
# Don't echo unlocked songs, we will add all of them later # Don't echo unlocked songs, we will add all of them later
continue continue
@ -437,22 +424,16 @@ class Museca1Plus(
return game return game
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies # Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value("earned_gamecoin_packet") earned_gamecoin_packet = request.child_value("earned_gamecoin_packet")
if earned_gamecoin_packet is not None: if earned_gamecoin_packet is not None:
newprofile.replace_int( newprofile.replace_int("packet", newprofile.get_int("packet") + earned_gamecoin_packet)
"packet", newprofile.get_int("packet") + earned_gamecoin_packet
)
earned_gamecoin_block = request.child_value("earned_gamecoin_block") earned_gamecoin_block = request.child_value("earned_gamecoin_block")
if earned_gamecoin_block is not None: if earned_gamecoin_block is not None:
newprofile.replace_int( newprofile.replace_int("block", newprofile.get_int("block") + earned_gamecoin_block)
"block", newprofile.get_int("block") + earned_gamecoin_block
)
earned_blaster_energy = request.child_value("earned_blaster_energy") earned_blaster_energy = request.child_value("earned_blaster_energy")
if earned_blaster_energy is not None: if earned_blaster_energy is not None:
newprofile.replace_int( newprofile.replace_int(
@ -463,9 +444,7 @@ class Museca1Plus(
# Miscelaneous stuff # Miscelaneous stuff
newprofile.replace_int("blaster_count", request.child_value("blaster_count")) newprofile.replace_int("blaster_count", request.child_value("blaster_count"))
newprofile.replace_int("skill_name_id", request.child_value("skill_name_id")) newprofile.replace_int("skill_name_id", request.child_value("skill_name_id"))
newprofile.replace_int_array( newprofile.replace_int_array("hidden_param", 20, request.child_value("hidden_param"))
"hidden_param", 20, request.child_value("hidden_param")
)
# Update user's unlock status if we aren't force unlocked # Update user's unlock status if we aren't force unlocked
game_config = self.get_game_config() game_config = self.get_game_config()
@ -480,10 +459,7 @@ class Museca1Plus(
param = child.child_value("param") param = child.child_value("param")
diff_param = child.child_value("diff_param") diff_param = child.child_value("diff_param")
if ( if game_config.get_bool("force_unlock_songs") and item_type == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and item_type == self.GAME_CATALOG_TYPE_SONG
):
# Don't save back songs, because they were force unlocked # Don't save back songs, because they were force unlocked
continue continue

View File

@ -28,30 +28,16 @@ class PopnMusicBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# Play medals, as saved into/loaded from the DB # Play medals, as saved into/loaded from the DB
PLAY_MEDAL_NO_PLAY: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_NO_PLAY PLAY_MEDAL_NO_PLAY: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_NO_PLAY
PLAY_MEDAL_CIRCLE_FAILED: Final[ PLAY_MEDAL_CIRCLE_FAILED: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FAILED
int PLAY_MEDAL_DIAMOND_FAILED: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FAILED
] = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FAILED
PLAY_MEDAL_DIAMOND_FAILED: Final[
int
] = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FAILED
PLAY_MEDAL_STAR_FAILED: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FAILED PLAY_MEDAL_STAR_FAILED: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FAILED
PLAY_MEDAL_EASY_CLEAR: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_EASY_CLEAR PLAY_MEDAL_EASY_CLEAR: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_EASY_CLEAR
PLAY_MEDAL_CIRCLE_CLEARED: Final[ PLAY_MEDAL_CIRCLE_CLEARED: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_CLEARED
int PLAY_MEDAL_DIAMOND_CLEARED: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_CLEARED
] = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_CLEARED
PLAY_MEDAL_DIAMOND_CLEARED: Final[
int
] = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_CLEARED
PLAY_MEDAL_STAR_CLEARED: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_CLEARED PLAY_MEDAL_STAR_CLEARED: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_CLEARED
PLAY_MEDAL_CIRCLE_FULL_COMBO: Final[ PLAY_MEDAL_CIRCLE_FULL_COMBO: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FULL_COMBO
int PLAY_MEDAL_DIAMOND_FULL_COMBO: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FULL_COMBO
] = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FULL_COMBO PLAY_MEDAL_STAR_FULL_COMBO: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FULL_COMBO
PLAY_MEDAL_DIAMOND_FULL_COMBO: Final[
int
] = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FULL_COMBO
PLAY_MEDAL_STAR_FULL_COMBO: Final[
int
] = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FULL_COMBO
PLAY_MEDAL_PERFECT: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_PERFECT PLAY_MEDAL_PERFECT: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_PERFECT
# Chart type, as saved into/loaded from the DB, and returned to game # Chart type, as saved into/loaded from the DB, and returned to game
@ -107,9 +93,7 @@ class PopnMusicBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
return Node.void("playerdata") return Node.void("playerdata")
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
""" """
Base handler for profile parsing. Given a request and an old profile, Base handler for profile parsing. Given a request and an old profile,
return a new profile that's been updated with the contents of the request. return a new profile that's been updated with the contents of the request.
@ -117,9 +101,7 @@ class PopnMusicBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
return oldprofile return oldprofile
def get_profile_by_refid( def get_profile_by_refid(self, refid: Optional[str], load_mode: int) -> Optional[Node]:
self, refid: Optional[str], load_mode: int
) -> Optional[Node]:
""" """
Given a RefID, return a formatted profile node. Basically every game Given a RefID, return a formatted profile node. Basically every game
needs a profile lookup, even if it handles where that happens in needs a profile lookup, even if it handles where that happens in
@ -341,9 +323,7 @@ class PopnMusicBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
) -> None: ) -> None:
# Generate scorecard # Generate scorecard
profile = self.get_profile(userid) profile = self.get_profile(userid)
song = self.data.local.music.get_song( song = self.data.local.music.get_song(self.game, self.music_version, songid, chart)
self.game, self.music_version, songid, chart
)
card_medal = { card_medal = {
self.PLAY_MEDAL_CIRCLE_FAILED: "Failed", self.PLAY_MEDAL_CIRCLE_FAILED: "Failed",

View File

@ -55,22 +55,15 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
] ]
@classmethod @classmethod
def run_scheduled_work( def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
cls, data: Data, config: Dict[str, Any]
) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Once a week, insert a new course. Once a week, insert a new course.
""" """
events = [] events = []
if data.local.network.should_schedule( if data.local.network.should_schedule(cls.game, cls.version, "course", "weekly"):
cls.game, cls.version, "course", "weekly"
):
# Generate a new course list, save it to the DB. # Generate a new course list, save it to the DB.
start_time, end_time = data.local.network.get_schedule_duration("weekly") start_time, end_time = data.local.network.get_schedule_duration("weekly")
all_songs = [ all_songs = [song.id for song in data.local.music.get_all_songs(cls.game, cls.version)]
song.id
for song in data.local.music.get_all_songs(cls.game, cls.version)
]
if all_songs: if all_songs:
course_song = random.choice(all_songs) course_song = random.choice(all_songs)
data.local.game.put_time_sensitive_settings( data.local.game.put_time_sensitive_settings(
@ -94,9 +87,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
) )
# Mark that we did some actual work here. # Mark that we did some actual work here.
data.local.network.mark_scheduled( data.local.network.mark_scheduled(cls.game, cls.version, "course", "weekly")
cls.game, cls.version, "course", "weekly"
)
return events return events
def __score_to_rank(self, score: int) -> int: def __score_to_rank(self, score: int) -> int:
@ -152,12 +143,8 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
# Gather course information and course ranking for users. # Gather course information and course ranking for users.
course_infos, achievements, profiles = Parallel.execute( course_infos, achievements, profiles = Parallel.execute(
[ [
lambda: self.data.local.game.get_all_time_sensitive_settings( lambda: self.data.local.game.get_all_time_sensitive_settings(self.game, self.version, "course"),
self.game, self.version, "course" lambda: self.data.local.user.get_all_achievements(self.game, self.version),
),
lambda: self.data.local.user.get_all_achievements(
self.game, self.version
),
lambda: self.data.local.user.get_all_profiles(self.game, self.version), lambda: self.data.local.user.get_all_profiles(self.game, self.version),
] ]
) )
@ -168,9 +155,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
reverse=True, reverse=True,
) )
# Sort achievements within course ID from best to worst ranking. # Sort achievements within course ID from best to worst ranking.
achievements_by_course_id: Dict[ achievements_by_course_id: Dict[int, Dict[str, List[Tuple[UserID, Achievement]]]] = {}
int, Dict[str, List[Tuple[UserID, Achievement]]]
] = {}
type_to_chart_lut: Dict[str, str] = { type_to_chart_lut: Dict[str, str] = {
f"course_{self.GAME_CHART_TYPE_EASY}": "loc_ranking_e", f"course_{self.GAME_CHART_TYPE_EASY}": "loc_ranking_e",
f"course_{self.GAME_CHART_TYPE_NORMAL}": "loc_ranking_n", f"course_{self.GAME_CHART_TYPE_NORMAL}": "loc_ranking_n",
@ -187,9 +172,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
"loc_ranking_h": [], "loc_ranking_h": [],
"loc_ranking_ex": [], "loc_ranking_ex": [],
} }
achievements_by_course_id[ach.id][type_to_chart_lut[ach.type]].append( achievements_by_course_id[ach.id][type_to_chart_lut[ach.type]].append((uid, ach))
(uid, ach)
)
for courseid in achievements_by_course_id: for courseid in achievements_by_course_id:
for chart in [ for chart in [
"loc_ranking_e", "loc_ranking_e",
@ -204,9 +187,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
) )
# Cache of userID to profile # Cache of userID to profile
userid_to_profile: Dict[UserID, Profile] = { userid_to_profile: Dict[UserID, Profile] = {uid: profile for (uid, profile) in profiles}
uid: profile for (uid, profile) in profiles
}
# Course ranking info for the last 256 courses # Course ranking info for the last 256 courses
for course_info in course_infos[:256]: for course_info in course_infos[:256]:
@ -216,9 +197,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
ranking_info = Node.void("ranking_info") ranking_info = Node.void("ranking_info")
root.add_child(ranking_info) root.add_child(ranking_info)
ranking_info.add_child(Node.s16("course_id", course_id)) ranking_info.add_child(Node.s16("course_id", course_id))
ranking_info.add_child( ranking_info.add_child(Node.u64("start_date", course_info["start_time"] * 1000))
Node.u64("start_date", course_info["start_time"] * 1000)
)
ranking_info.add_child(Node.u64("end_date", course_info["end_time"] * 1000)) ranking_info.add_child(Node.u64("end_date", course_info["end_time"] * 1000))
ranking_info.add_child(Node.s32("music_id", course_info["music"])) ranking_info.add_child(Node.s32("music_id", course_info["music"]))
@ -232,26 +211,16 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
chart_rankings = course_rankings.get(name, []) chart_rankings = course_rankings.get(name, [])
for pos, (uid, ach) in enumerate(chart_rankings[:20]): for pos, (uid, ach) in enumerate(chart_rankings[:20]):
profile = userid_to_profile.get( profile = userid_to_profile.get(uid, Profile(self.game, self.version, "", 0))
uid, Profile(self.game, self.version, "", 0)
)
subnode = Node.void(name) subnode = Node.void(name)
ranking_info.add_child(subnode) ranking_info.add_child(subnode)
subnode.add_child(Node.s16("rank", pos + 1)) subnode.add_child(Node.s16("rank", pos + 1))
subnode.add_child(Node.string("name", profile.get_str("name"))) subnode.add_child(Node.string("name", profile.get_str("name")))
subnode.add_child( subnode.add_child(Node.s16("chara_num", profile.get_int("chara", -1)))
Node.s16("chara_num", profile.get_int("chara", -1)) subnode.add_child(Node.s32("total_score", ach.data.get_int("score")))
) subnode.add_child(Node.u8("clear_type", ach.data.get_int("clear_type")))
subnode.add_child( subnode.add_child(Node.u8("clear_rank", ach.data.get_int("clear_rank")))
Node.s32("total_score", ach.data.get_int("score"))
)
subnode.add_child(
Node.u8("clear_type", ach.data.get_int("clear_type"))
)
subnode.add_child(
Node.u8("clear_rank", ach.data.get_int("clear_rank"))
)
if send_areas: if send_areas:
for area_id in range(1, 16): for area_id in range(1, 16):
@ -327,9 +296,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
popular.add_child(Node.s16("chara_num", charaid)) popular.add_child(Node.s16("chara_num", charaid))
# Top 500 Popular music # Top 500 Popular music
for songid, _plays in self.data.local.music.get_hit_chart( for songid, _plays in self.data.local.music.get_hit_chart(self.game, self.music_version, 500):
self.game, self.music_version, 500
):
popular_music = Node.void("popular_music") popular_music = Node.void("popular_music")
root.add_child(popular_music) root.add_child(popular_music)
popular_music.add_child(Node.s16("music_num", songid)) popular_music.add_child(Node.s16("music_num", songid))
@ -418,9 +385,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
userid = None userid = None
if userid is not None: if userid is not None:
oldprofile = self.get_profile(userid) or Profile( oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
newprofile = self.unformat_profile(userid, request, oldprofile) newprofile = self.unformat_profile(userid, request, oldprofile)
if newprofile is not None: if newprofile is not None:
@ -480,34 +445,23 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
# Handle fetching all scores # Handle fetching all scores
uids_and_courses, profile = Parallel.execute( uids_and_courses, profile = Parallel.execute(
[ [
lambda: self.data.local.user.get_all_achievements( lambda: self.data.local.user.get_all_achievements(self.game, self.version),
self.game, self.version lambda: self.get_profile(userid) or Profile(self.game, self.version, "", 0),
),
lambda: self.get_profile(userid)
or Profile(self.game, self.version, "", 0),
] ]
) )
# Grab a sorted list of all scores for this course and chart # Grab a sorted list of all scores for this course and chart
global_uids_and_courses = sorted( global_uids_and_courses = sorted(
[ [(uid, ach) for (uid, ach) in uids_and_courses if ach.type == course_type and ach.id == course_id],
(uid, ach)
for (uid, ach) in uids_and_courses
if ach.type == course_type and ach.id == course_id
],
key=lambda uid_and_course: uid_and_course[1].data.get_int("score"), key=lambda uid_and_course: uid_and_course[1].data.get_int("score"),
reverse=True, reverse=True,
) )
# Grab smaller lists that contain only sorted for our prefecture/location # Grab smaller lists that contain only sorted for our prefecture/location
pref_uids_and_courses = [ pref_uids_and_courses = [
(uid, ach) (uid, ach) for (uid, ach) in global_uids_and_courses if ach.data.get_int("pref") == prefecture
for (uid, ach) in global_uids_and_courses
if ach.data.get_int("pref") == prefecture
] ]
loc_uids_and_courses = [ loc_uids_and_courses = [
(uid, ach) (uid, ach) for (uid, ach) in global_uids_and_courses if ach.data.get_int("lid") == loc_id
for (uid, ach) in global_uids_and_courses
if ach.data.get_int("lid") == loc_id
] ]
def _get_rank(uac: List[Tuple[UserID, Achievement]]) -> Optional[int]: def _get_rank(uac: List[Tuple[UserID, Achievement]]) -> Optional[int]:
@ -575,17 +529,13 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
return root return root
rivalid = links[no].other_userid rivalid = links[no].other_userid
rivalprofile = profiles[rivalid] rivalprofile = profiles[rivalid]
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, rivalid)
self.game, self.music_version, rivalid
)
# First, output general profile info. # First, output general profile info.
friend = Node.void("friend") friend = Node.void("friend")
root.add_child(friend) root.add_child(friend)
friend.add_child(Node.s16("no", no)) friend.add_child(Node.s16("no", no))
friend.add_child( friend.add_child(Node.string("g_pm_id", self.format_extid(rivalprofile.extid))) # UsaNeko formats on its own
Node.string("g_pm_id", self.format_extid(rivalprofile.extid))
) # UsaNeko formats on its own
friend.add_child(Node.string("name", rivalprofile.get_str("name", "なし"))) friend.add_child(Node.string("name", rivalprofile.get_str("name", "なし")))
friend.add_child(Node.s16("chara_num", rivalprofile.get_int("chara", -1))) friend.add_child(Node.s16("chara_num", rivalprofile.get_int("chara", -1)))
# This might be for having non-active or non-confirmed friends, but setting to 0 makes the # This might be for having non-active or non-confirmed friends, but setting to 0 makes the
@ -642,9 +592,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
), ),
) )
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, rivalid)
self.game, self.version, rivalid
)
for achievement in achievements: for achievement in achievements:
if achievement.type[:7] == "course_": if achievement.type[:7] == "course_":
sheet = int(achievement.type[7:]) sheet = int(achievement.type[7:])
@ -652,18 +600,10 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
course_data = Node.void("course_data") course_data = Node.void("course_data")
root.add_child(course_data) root.add_child(course_data)
course_data.add_child(Node.s16("course_id", achievement.id)) course_data.add_child(Node.s16("course_id", achievement.id))
course_data.add_child( course_data.add_child(Node.u8("clear_type", achievement.data.get_int("clear_type")))
Node.u8("clear_type", achievement.data.get_int("clear_type")) course_data.add_child(Node.u8("clear_rank", achievement.data.get_int("clear_rank")))
) course_data.add_child(Node.s32("total_score", achievement.data.get_int("score")))
course_data.add_child( course_data.add_child(Node.s32("update_count", achievement.data.get_int("count")))
Node.u8("clear_rank", achievement.data.get_int("clear_rank"))
)
course_data.add_child(
Node.s32("total_score", achievement.data.get_int("score"))
)
course_data.add_child(
Node.s32("update_count", achievement.data.get_int("count"))
)
course_data.add_child(Node.u8("sheet_num", sheet)) course_data.add_child(Node.u8("sheet_num", sheet))
return root return root
@ -675,9 +615,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
return Node.void("player24") return Node.void("player24")
root = Node.void("player24") root = Node.void("player24")
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
# Skip any scores for chart types we don't support # Skip any scores for chart types we don't support
if score.chart not in [ if score.chart not in [
@ -768,9 +706,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
self.GAME_PLAY_MEDAL_STAR_FULL_COMBO: self.PLAY_MEDAL_STAR_FULL_COMBO, self.GAME_PLAY_MEDAL_STAR_FULL_COMBO: self.PLAY_MEDAL_STAR_FULL_COMBO,
self.GAME_PLAY_MEDAL_PERFECT: self.PLAY_MEDAL_PERFECT, self.GAME_PLAY_MEDAL_PERFECT: self.PLAY_MEDAL_PERFECT,
}[medal] }[medal]
self.update_score( self.update_score(userid, songid, chart, points, medal, combo=combo, stats=stats)
userid, songid, chart, points, medal, combo=combo, stats=stats
)
if request.child_value("is_image_store") == 1: if request.child_value("is_image_store") == 1:
self.broadcast_score(userid, songid, chart, medal, points, combo, stats) self.broadcast_score(userid, songid, chart, medal, points, combo, stats)
@ -804,9 +740,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
if lumina >= price: if lumina >= price:
# Update player lumina balance # Update player lumina balance
profile = self.get_profile(userid) or Profile( profile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
profile.replace_int("player_point", lumina - price) profile.replace_int("player_point", lumina - price)
self.put_profile(userid, profile) self.put_profile(userid, profile)
@ -833,9 +767,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
root.add_child(Node.s8("result", 1)) root.add_child(Node.s8("result", 1))
# Scores # Scores
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
# Skip any scores for chart types we don't support # Skip any scores for chart types we don't support
if score.chart not in [ if score.chart not in [
@ -905,57 +837,31 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
account.add_child(Node.s16("area_id", profile.get_int("area_id"))) account.add_child(Node.s16("area_id", profile.get_int("area_id")))
account.add_child(Node.s16("use_navi", profile.get_int("use_navi"))) account.add_child(Node.s16("use_navi", profile.get_int("use_navi")))
account.add_child(Node.s16("read_news", profile.get_int("read_news"))) account.add_child(Node.s16("read_news", profile.get_int("read_news")))
account.add_child( account.add_child(Node.s16_array("nice", profile.get_int_array("nice", 30, [-1] * 30)))
Node.s16_array("nice", profile.get_int_array("nice", 30, [-1] * 30)) account.add_child(Node.s16_array("favorite_chara", profile.get_int_array("favorite_chara", 20, [-1] * 20)))
) account.add_child(Node.s16_array("special_area", profile.get_int_array("special_area", 8, [-1] * 8)))
account.add_child(
Node.s16_array(
"favorite_chara", profile.get_int_array("favorite_chara", 20, [-1] * 20)
)
)
account.add_child(
Node.s16_array(
"special_area", profile.get_int_array("special_area", 8, [-1] * 8)
)
)
account.add_child( account.add_child(
Node.s16_array( Node.s16_array(
"chocolate_charalist", "chocolate_charalist",
profile.get_int_array("chocolate_charalist", 5, [-1] * 5), profile.get_int_array("chocolate_charalist", 5, [-1] * 5),
) )
) )
account.add_child( account.add_child(Node.s32("chocolate_sp_chara", profile.get_int("chocolate_sp_chara", -1)))
Node.s32("chocolate_sp_chara", profile.get_int("chocolate_sp_chara", -1)) account.add_child(Node.s32("chocolate_pass_cnt", profile.get_int("chocolate_pass_cnt")))
) account.add_child(Node.s32("chocolate_hon_cnt", profile.get_int("chocolate_hon_cnt")))
account.add_child(
Node.s32("chocolate_pass_cnt", profile.get_int("chocolate_pass_cnt"))
)
account.add_child(
Node.s32("chocolate_hon_cnt", profile.get_int("chocolate_hon_cnt"))
)
account.add_child( account.add_child(
Node.s16_array( Node.s16_array(
"teacher_setting", "teacher_setting",
profile.get_int_array("teacher_setting", 10, [-1] * 10), profile.get_int_array("teacher_setting", 10, [-1] * 10),
) )
) )
account.add_child( account.add_child(Node.bool("welcom_pack", False)) # Set to true to grant extra stage no matter what.
Node.bool("welcom_pack", False)
) # Set to true to grant extra stage no matter what.
account.add_child(Node.s32("ranking_node", profile.get_int("ranking_node"))) account.add_child(Node.s32("ranking_node", profile.get_int("ranking_node")))
account.add_child( account.add_child(Node.s32("chara_ranking_kind_id", profile.get_int("chara_ranking_kind_id")))
Node.s32("chara_ranking_kind_id", profile.get_int("chara_ranking_kind_id")) account.add_child(Node.s8("navi_evolution_flg", profile.get_int("navi_evolution_flg")))
) account.add_child(Node.s32("ranking_news_last_no", profile.get_int("ranking_news_last_no")))
account.add_child(
Node.s8("navi_evolution_flg", profile.get_int("navi_evolution_flg"))
)
account.add_child(
Node.s32("ranking_news_last_no", profile.get_int("ranking_news_last_no"))
)
account.add_child(Node.s32("power_point", profile.get_int("power_point"))) account.add_child(Node.s32("power_point", profile.get_int("power_point")))
account.add_child( account.add_child(Node.s32("player_point", profile.get_int("player_point", 300)))
Node.s32("player_point", profile.get_int("player_point", 300))
)
account.add_child( account.add_child(
Node.s32_array( Node.s32_array(
"power_point_list", "power_point_list",
@ -1039,18 +945,8 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
account.add_child(Node.s16_array("license_data", [-1] * 20)) account.add_child(Node.s16_array("license_data", [-1] * 20))
# Song statistics # Song statistics
last_played = [ last_played = [x[0] for x in self.data.local.music.get_last_played(self.game, self.music_version, userid, 10)]
x[0] most_played = [x[0] for x in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)]
for x in self.data.local.music.get_last_played(
self.game, self.music_version, userid, 10
)
]
most_played = [
x[0]
for x in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
]
while len(last_played) < 10: while len(last_played) < 10:
last_played.append(-1) last_played.append(-1)
while len(most_played) < 20: while len(most_played) < 20:
@ -1104,14 +1000,10 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
config.add_child(Node.u8("sheet", profile.get_int("sheet"))) config.add_child(Node.u8("sheet", profile.get_int("sheet")))
config.add_child(Node.s8("category", profile.get_int("category", -1))) config.add_child(Node.s8("category", profile.get_int("category", -1)))
config.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1))) config.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1)))
config.add_child( config.add_child(Node.s8("chara_category", profile.get_int("chara_category", -1)))
Node.s8("chara_category", profile.get_int("chara_category", -1))
)
config.add_child(Node.s16("course_id", profile.get_int("course_id", -1))) config.add_child(Node.s16("course_id", profile.get_int("course_id", -1)))
config.add_child(Node.s8("course_folder", profile.get_int("course_folder", -1))) config.add_child(Node.s8("course_folder", profile.get_int("course_folder", -1)))
config.add_child( config.add_child(Node.s8("ms_banner_disp", profile.get_int("ms_banner_disp", -1)))
Node.s8("ms_banner_disp", profile.get_int("ms_banner_disp", -1))
)
config.add_child(Node.s8("ms_down_info", profile.get_int("ms_down_info", -1))) config.add_child(Node.s8("ms_down_info", profile.get_int("ms_down_info", -1)))
config.add_child(Node.s8("ms_side_info", profile.get_int("ms_side_info", -1))) config.add_child(Node.s8("ms_side_info", profile.get_int("ms_side_info", -1)))
config.add_child(Node.s8("ms_raise_type", profile.get_int("ms_raise_type", -1))) config.add_child(Node.s8("ms_raise_type", profile.get_int("ms_raise_type", -1)))
@ -1134,9 +1026,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
option.add_child(Node.u8("ojama_1", option_dict.get_int("ojama_1"))) option.add_child(Node.u8("ojama_1", option_dict.get_int("ojama_1")))
option.add_child(Node.bool("forever_0", option_dict.get_bool("forever_0"))) option.add_child(Node.bool("forever_0", option_dict.get_bool("forever_0")))
option.add_child(Node.bool("forever_1", option_dict.get_bool("forever_1"))) option.add_child(Node.bool("forever_1", option_dict.get_bool("forever_1")))
option.add_child( option.add_child(Node.bool("full_setting", option_dict.get_bool("full_setting")))
Node.bool("full_setting", option_dict.get_bool("full_setting"))
)
option.add_child(Node.u8("judge", option_dict.get_int("judge"))) option.add_child(Node.u8("judge", option_dict.get_int("judge")))
option.add_child(Node.s8("guide_se", option_dict.get_int("guide_se"))) option.add_child(Node.s8("guide_se", option_dict.get_int("guide_se")))
@ -1155,18 +1045,11 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
navi_data = Node.void("navi_data") navi_data = Node.void("navi_data")
root.add_child(navi_data) root.add_child(navi_data)
if "navi_points" in profile: if "navi_points" in profile:
navi_data.add_child( navi_data.add_child(Node.s32_array("raisePoint", profile.get_int_array("navi_points", 5)))
Node.s32_array("raisePoint", profile.get_int_array("navi_points", 5))
)
game_config = self.get_game_config() game_config = self.get_game_config()
if game_config.get_bool("force_unlock_songs"): if game_config.get_bool("force_unlock_songs"):
songs = { songs = {song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)}
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
}
for song in songs: for song in songs:
item = Node.void("item") item = Node.void("item")
root.add_child(item) root.add_child(item)
@ -1177,9 +1060,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
item.add_child(Node.u64("get_time", 0)) item.add_child(Node.u64("get_time", 0))
# Set up achievements # Set up achievements
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for achievement in achievements: for achievement in achievements:
if achievement.type[:5] == "item_": if achievement.type[:5] == "item_":
itemtype = int(achievement.type[5:]) itemtype = int(achievement.type[5:])
@ -1243,18 +1124,10 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
course_data = Node.void("course_data") course_data = Node.void("course_data")
root.add_child(course_data) root.add_child(course_data)
course_data.add_child(Node.s16("course_id", achievement.id)) course_data.add_child(Node.s16("course_id", achievement.id))
course_data.add_child( course_data.add_child(Node.u8("clear_type", achievement.data.get_int("clear_type")))
Node.u8("clear_type", achievement.data.get_int("clear_type")) course_data.add_child(Node.u8("clear_rank", achievement.data.get_int("clear_rank")))
) course_data.add_child(Node.s32("total_score", achievement.data.get_int("score")))
course_data.add_child( course_data.add_child(Node.s32("update_count", achievement.data.get_int("count")))
Node.u8("clear_rank", achievement.data.get_int("clear_rank"))
)
course_data.add_child(
Node.s32("total_score", achievement.data.get_int("score"))
)
course_data.add_child(
Node.s32("update_count", achievement.data.get_int("count"))
)
course_data.add_child(Node.u8("sheet_num", sheet)) course_data.add_child(Node.u8("sheet_num", sheet))
elif achievement.type == "fes": elif achievement.type == "fes":
@ -1340,9 +1213,7 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
account = request.child("account") account = request.child("account")
@ -1352,49 +1223,23 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
newprofile.replace_int("area_id", account.child_value("area_id")) newprofile.replace_int("area_id", account.child_value("area_id"))
newprofile.replace_int("use_navi", account.child_value("use_navi")) newprofile.replace_int("use_navi", account.child_value("use_navi"))
newprofile.replace_int("ranking_node", account.child_value("ranking_node")) newprofile.replace_int("ranking_node", account.child_value("ranking_node"))
newprofile.replace_int( newprofile.replace_int("chara_ranking_kind_id", account.child_value("chara_ranking_kind_id"))
"chara_ranking_kind_id", account.child_value("chara_ranking_kind_id") newprofile.replace_int("navi_evolution_flg", account.child_value("navi_evolution_flg"))
) newprofile.replace_int("ranking_news_last_no", account.child_value("ranking_news_last_no"))
newprofile.replace_int(
"navi_evolution_flg", account.child_value("navi_evolution_flg")
)
newprofile.replace_int(
"ranking_news_last_no", account.child_value("ranking_news_last_no")
)
newprofile.replace_int("power_point", account.child_value("power_point")) newprofile.replace_int("power_point", account.child_value("power_point"))
newprofile.replace_int("player_point", account.child_value("player_point")) newprofile.replace_int("player_point", account.child_value("player_point"))
newprofile.replace_int_array("nice", 30, account.child_value("nice")) newprofile.replace_int_array("nice", 30, account.child_value("nice"))
newprofile.replace_int_array( newprofile.replace_int_array("favorite_chara", 20, account.child_value("favorite_chara"))
"favorite_chara", 20, account.child_value("favorite_chara") newprofile.replace_int_array("special_area", 8, account.child_value("special_area"))
) newprofile.replace_int_array("chocolate_charalist", 5, account.child_value("chocolate_charalist"))
newprofile.replace_int_array( newprofile.replace_int("chocolate_sp_chara", account.child_value("chocolate_sp_chara"))
"special_area", 8, account.child_value("special_area") newprofile.replace_int("chocolate_pass_cnt", account.child_value("chocolate_pass_cnt"))
) newprofile.replace_int("chocolate_hon_cnt", account.child_value("chocolate_hon_cnt"))
newprofile.replace_int_array( newprofile.replace_int("chocolate_giri_cnt", account.child_value("chocolate_giri_cnt"))
"chocolate_charalist", 5, account.child_value("chocolate_charalist") newprofile.replace_int("chocolate_kokyu_cnt", account.child_value("chocolate_kokyu_cnt"))
) newprofile.replace_int_array("teacher_setting", 10, account.child_value("teacher_setting"))
newprofile.replace_int( newprofile.replace_int_array("power_point_list", 20, account.child_value("power_point_list"))
"chocolate_sp_chara", account.child_value("chocolate_sp_chara")
)
newprofile.replace_int(
"chocolate_pass_cnt", account.child_value("chocolate_pass_cnt")
)
newprofile.replace_int(
"chocolate_hon_cnt", account.child_value("chocolate_hon_cnt")
)
newprofile.replace_int(
"chocolate_giri_cnt", account.child_value("chocolate_giri_cnt")
)
newprofile.replace_int(
"chocolate_kokyu_cnt", account.child_value("chocolate_kokyu_cnt")
)
newprofile.replace_int_array(
"teacher_setting", 10, account.child_value("teacher_setting")
)
newprofile.replace_int_array(
"power_point_list", 20, account.child_value("power_point_list")
)
info = request.child("info") info = request.child("info")
if info is not None: if info is not None:
@ -1413,14 +1258,10 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
newprofile.replace_int("sheet", config.child_value("sheet")) newprofile.replace_int("sheet", config.child_value("sheet"))
newprofile.replace_int("category", config.child_value("category")) newprofile.replace_int("category", config.child_value("category"))
newprofile.replace_int("sub_category", config.child_value("sub_category")) newprofile.replace_int("sub_category", config.child_value("sub_category"))
newprofile.replace_int( newprofile.replace_int("chara_category", config.child_value("chara_category"))
"chara_category", config.child_value("chara_category")
)
newprofile.replace_int("course_id", config.child_value("course_id")) newprofile.replace_int("course_id", config.child_value("course_id"))
newprofile.replace_int("course_folder", config.child_value("course_folder")) newprofile.replace_int("course_folder", config.child_value("course_folder"))
newprofile.replace_int( newprofile.replace_int("ms_banner_disp", config.child_value("ms_banner_disp"))
"ms_banner_disp", config.child_value("ms_banner_disp")
)
newprofile.replace_int("ms_down_info", config.child_value("ms_down_info")) newprofile.replace_int("ms_down_info", config.child_value("ms_down_info"))
newprofile.replace_int("ms_side_info", config.child_value("ms_side_info")) newprofile.replace_int("ms_side_info", config.child_value("ms_side_info"))
newprofile.replace_int("ms_raise_type", config.child_value("ms_raise_type")) newprofile.replace_int("ms_raise_type", config.child_value("ms_raise_type"))
@ -1450,21 +1291,15 @@ class PopnMusicModernBase(PopnMusicBase, ABC):
customize = request.child("customize") customize = request.child("customize")
if customize is not None: if customize is not None:
newprofile.replace_int("effect_left", customize.child_value("effect_left")) newprofile.replace_int("effect_left", customize.child_value("effect_left"))
newprofile.replace_int( newprofile.replace_int("effect_center", customize.child_value("effect_center"))
"effect_center", customize.child_value("effect_center") newprofile.replace_int("effect_right", customize.child_value("effect_right"))
)
newprofile.replace_int(
"effect_right", customize.child_value("effect_right")
)
newprofile.replace_int("hukidashi", customize.child_value("hukidashi")) newprofile.replace_int("hukidashi", customize.child_value("hukidashi"))
newprofile.replace_int("comment_1", customize.child_value("comment_1")) newprofile.replace_int("comment_1", customize.child_value("comment_1"))
newprofile.replace_int("comment_2", customize.child_value("comment_2")) newprofile.replace_int("comment_2", customize.child_value("comment_2"))
navi_data = request.child("navi_data") navi_data = request.child("navi_data")
if navi_data is not None: if navi_data is not None:
newprofile.replace_int_array( newprofile.replace_int_array("navi_points", 5, navi_data.child_value("raisePoint"))
"navi_points", 5, navi_data.child_value("raisePoint")
)
# Extract navi achievements # Extract navi achievements
for node in navi_data.children: for node in navi_data.children:

View File

@ -209,9 +209,7 @@ class PopnMusicEclale(PopnMusicBase):
rank = rank + 1 rank = rank + 1
# Output the hit chart # Output the hit chart
for songid, _plays in self.data.local.music.get_hit_chart( for songid, _plays in self.data.local.music.get_hit_chart(self.game, self.music_version, 500):
self.game, self.music_version, 500
):
popular_music = Node.void("popular_music") popular_music = Node.void("popular_music")
root.add_child(popular_music) root.add_child(popular_music)
popular_music.add_child(Node.s16("music_num", songid)) popular_music.add_child(Node.s16("music_num", songid))
@ -285,9 +283,7 @@ class PopnMusicEclale(PopnMusicBase):
userid = None userid = None
if userid is not None: if userid is not None:
oldprofile = self.get_profile(userid) or Profile( oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
newprofile = self.unformat_profile(userid, request, oldprofile) newprofile = self.unformat_profile(userid, request, oldprofile)
if newprofile is not None: if newprofile is not None:
@ -332,9 +328,7 @@ class PopnMusicEclale(PopnMusicBase):
if lumina >= price: if lumina >= price:
# Update player lumina balance # Update player lumina balance
profile = self.get_profile(userid) or Profile( profile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
profile.replace_int("lumina", lumina - price) profile.replace_int("lumina", lumina - price)
self.put_profile(userid, profile) self.put_profile(userid, profile)
@ -360,9 +354,7 @@ class PopnMusicEclale(PopnMusicBase):
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is not None: if userid is not None:
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
else: else:
scores = [] scores = []
@ -453,17 +445,13 @@ class PopnMusicEclale(PopnMusicBase):
return root return root
rivalid = links[no].other_userid rivalid = links[no].other_userid
rivalprofile = profiles[rivalid] rivalprofile = profiles[rivalid]
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, rivalid)
self.game, self.music_version, rivalid
)
# First, output general profile info. # First, output general profile info.
friend = Node.void("friend") friend = Node.void("friend")
root.add_child(friend) root.add_child(friend)
friend.add_child(Node.s16("no", no)) friend.add_child(Node.s16("no", no))
friend.add_child( friend.add_child(Node.string("g_pm_id", self.format_extid(rivalprofile.extid))) # Eclale formats on its own
Node.string("g_pm_id", self.format_extid(rivalprofile.extid))
) # Eclale formats on its own
friend.add_child(Node.string("name", rivalprofile.get_str("name", "なし"))) friend.add_child(Node.string("name", rivalprofile.get_str("name", "なし")))
friend.add_child(Node.s16("chara_num", rivalprofile.get_int("chara", -1))) friend.add_child(Node.s16("chara_num", rivalprofile.get_int("chara", -1)))
# This might be for having non-active or non-confirmed friends, but setting to 0 makes the # This might be for having non-active or non-confirmed friends, but setting to 0 makes the
@ -561,9 +549,7 @@ class PopnMusicEclale(PopnMusicBase):
self.GAME_PLAY_MEDAL_STAR_FULL_COMBO: self.PLAY_MEDAL_STAR_FULL_COMBO, self.GAME_PLAY_MEDAL_STAR_FULL_COMBO: self.PLAY_MEDAL_STAR_FULL_COMBO,
self.GAME_PLAY_MEDAL_PERFECT: self.PLAY_MEDAL_PERFECT, self.GAME_PLAY_MEDAL_PERFECT: self.PLAY_MEDAL_PERFECT,
}[medal] }[medal]
self.update_score( self.update_score(userid, songid, chart, points, medal, combo=combo, stats=stats)
userid, songid, chart, points, medal, combo=combo, stats=stats
)
if request.child_value("is_image_store") == 1: if request.child_value("is_image_store") == 1:
self.broadcast_score(userid, songid, chart, medal, points, combo, stats) self.broadcast_score(userid, songid, chart, medal, points, combo, stats)
@ -577,9 +563,7 @@ class PopnMusicEclale(PopnMusicBase):
root.add_child(Node.s8("result", 1)) root.add_child(Node.s8("result", 1))
# Scores # Scores
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
# Skip any scores for chart types we don't support # Skip any scores for chart types we don't support
if score.chart not in [ if score.chart not in [
@ -649,34 +633,18 @@ class PopnMusicEclale(PopnMusicBase):
account.add_child(Node.s16("area_id", profile.get_int("area_id"))) account.add_child(Node.s16("area_id", profile.get_int("area_id")))
account.add_child(Node.s16("lumina", profile.get_int("lumina", 300))) account.add_child(Node.s16("lumina", profile.get_int("lumina", 300)))
account.add_child(Node.s16("read_news", profile.get_int("read_news"))) account.add_child(Node.s16("read_news", profile.get_int("read_news")))
account.add_child( account.add_child(Node.bool("welcom_pack", False)) # Set this to true to grant extra stage no matter what.
Node.bool("welcom_pack", False) account.add_child(Node.s16_array("medal_set", profile.get_int_array("medal_set", 4)))
) # Set this to true to grant extra stage no matter what. account.add_child(Node.s16_array("nice", profile.get_int_array("nice", 30, [-1] * 30)))
account.add_child( account.add_child(Node.s16_array("favorite_chara", profile.get_int_array("favorite_chara", 20, [-1] * 20)))
Node.s16_array("medal_set", profile.get_int_array("medal_set", 4)) account.add_child(Node.s16_array("special_area", profile.get_int_array("special_area", 8)))
)
account.add_child(
Node.s16_array("nice", profile.get_int_array("nice", 30, [-1] * 30))
)
account.add_child(
Node.s16_array(
"favorite_chara", profile.get_int_array("favorite_chara", 20, [-1] * 20)
)
)
account.add_child(
Node.s16_array("special_area", profile.get_int_array("special_area", 8))
)
account.add_child( account.add_child(
Node.s16_array( Node.s16_array(
"chocolate_charalist", "chocolate_charalist",
profile.get_int_array("chocolate_charalist", 5, [-1] * 5), profile.get_int_array("chocolate_charalist", 5, [-1] * 5),
) )
) )
account.add_child( account.add_child(Node.s16_array("teacher_setting", profile.get_int_array("teacher_setting", 10)))
Node.s16_array(
"teacher_setting", profile.get_int_array("teacher_setting", 10)
)
)
# Stuff we never change # Stuff we never change
account.add_child(Node.s8("staff", 0)) account.add_child(Node.s8("staff", 0))
@ -687,18 +655,8 @@ class PopnMusicEclale(PopnMusicBase):
account.add_child(Node.s16_array("license_data", [-1] * 20)) account.add_child(Node.s16_array("license_data", [-1] * 20))
# Add statistics section # Add statistics section
last_played = [ last_played = [x[0] for x in self.data.local.music.get_last_played(self.game, self.music_version, userid, 5)]
x[0] most_played = [x[0] for x in self.data.local.music.get_most_played(self.game, self.music_version, userid, 10)]
for x in self.data.local.music.get_last_played(
self.game, self.music_version, userid, 5
)
]
most_played = [
x[0]
for x in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 10
)
]
while len(last_played) < 5: while len(last_played) < 5:
last_played.append(-1) last_played.append(-1)
while len(most_played) < 10: while len(most_played) < 10:
@ -753,9 +711,7 @@ class PopnMusicEclale(PopnMusicBase):
config.add_child(Node.u8("sheet", profile.get_int("sheet"))) config.add_child(Node.u8("sheet", profile.get_int("sheet")))
config.add_child(Node.s8("category", profile.get_int("category", -1))) config.add_child(Node.s8("category", profile.get_int("category", -1)))
config.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1))) config.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1)))
config.add_child( config.add_child(Node.s8("chara_category", profile.get_int("chara_category", -1)))
Node.s8("chara_category", profile.get_int("chara_category", -1))
)
config.add_child(Node.s16("course_id", profile.get_int("course_id", -1))) config.add_child(Node.s16("course_id", profile.get_int("course_id", -1)))
config.add_child(Node.s8("course_folder", profile.get_int("course_folder", -1))) config.add_child(Node.s8("course_folder", profile.get_int("course_folder", -1)))
config.add_child(Node.s8("ms_banner_disp", profile.get_int("ms_banner_disp"))) config.add_child(Node.s8("ms_banner_disp", profile.get_int("ms_banner_disp")))
@ -780,9 +736,7 @@ class PopnMusicEclale(PopnMusicBase):
option.add_child(Node.u8("ojama_1", option_dict.get_int("ojama_1"))) option.add_child(Node.u8("ojama_1", option_dict.get_int("ojama_1")))
option.add_child(Node.bool("forever_0", option_dict.get_bool("forever_0"))) option.add_child(Node.bool("forever_0", option_dict.get_bool("forever_0")))
option.add_child(Node.bool("forever_1", option_dict.get_bool("forever_1"))) option.add_child(Node.bool("forever_1", option_dict.get_bool("forever_1")))
option.add_child( option.add_child(Node.bool("full_setting", option_dict.get_bool("full_setting")))
Node.bool("full_setting", option_dict.get_bool("full_setting"))
)
option.add_child(Node.u8("judge", option_dict.get_int("judge"))) option.add_child(Node.u8("judge", option_dict.get_int("judge")))
# Unknown custom category stuff? # Unknown custom category stuff?
@ -798,12 +752,7 @@ class PopnMusicEclale(PopnMusicBase):
game_config = self.get_game_config() game_config = self.get_game_config()
if game_config.get_bool("force_unlock_songs"): if game_config.get_bool("force_unlock_songs"):
songs = { songs = {song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)}
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
}
for song in songs: for song in songs:
item = Node.void("item") item = Node.void("item")
root.add_child(item) root.add_child(item)
@ -813,9 +762,7 @@ class PopnMusicEclale(PopnMusicBase):
item.add_child(Node.bool("is_new", False)) item.add_child(Node.bool("is_new", False))
# Set up achievements # Set up achievements
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for achievement in achievements: for achievement in achievements:
if achievement.type[:5] == "item_": if achievement.type[:5] == "item_":
itemtype = int(achievement.type[5:]) itemtype = int(achievement.type[5:])
@ -898,9 +845,7 @@ class PopnMusicEclale(PopnMusicBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
account = request.child("account") account = request.child("account")
@ -909,22 +854,12 @@ class PopnMusicEclale(PopnMusicBase):
newprofile.replace_int("read_news", account.child_value("read_news")) newprofile.replace_int("read_news", account.child_value("read_news"))
newprofile.replace_int("area_id", account.child_value("area_id")) newprofile.replace_int("area_id", account.child_value("area_id"))
newprofile.replace_int("lumina", account.child_value("lumina")) newprofile.replace_int("lumina", account.child_value("lumina"))
newprofile.replace_int_array( newprofile.replace_int_array("medal_set", 4, account.child_value("medal_set"))
"medal_set", 4, account.child_value("medal_set")
)
newprofile.replace_int_array("nice", 30, account.child_value("nice")) newprofile.replace_int_array("nice", 30, account.child_value("nice"))
newprofile.replace_int_array( newprofile.replace_int_array("favorite_chara", 20, account.child_value("favorite_chara"))
"favorite_chara", 20, account.child_value("favorite_chara") newprofile.replace_int_array("special_area", 8, account.child_value("special_area"))
) newprofile.replace_int_array("chocolate_charalist", 5, account.child_value("chocolate_charalist"))
newprofile.replace_int_array( newprofile.replace_int_array("teacher_setting", 10, account.child_value("teacher_setting"))
"special_area", 8, account.child_value("special_area")
)
newprofile.replace_int_array(
"chocolate_charalist", 5, account.child_value("chocolate_charalist")
)
newprofile.replace_int_array(
"teacher_setting", 10, account.child_value("teacher_setting")
)
info = request.child("info") info = request.child("info")
if info is not None: if info is not None:
@ -938,14 +873,10 @@ class PopnMusicEclale(PopnMusicBase):
newprofile.replace_int("sheet", config.child_value("sheet")) newprofile.replace_int("sheet", config.child_value("sheet"))
newprofile.replace_int("category", config.child_value("category")) newprofile.replace_int("category", config.child_value("category"))
newprofile.replace_int("sub_category", config.child_value("sub_category")) newprofile.replace_int("sub_category", config.child_value("sub_category"))
newprofile.replace_int( newprofile.replace_int("chara_category", config.child_value("chara_category"))
"chara_category", config.child_value("chara_category")
)
newprofile.replace_int("course_id", config.child_value("course_id")) newprofile.replace_int("course_id", config.child_value("course_id"))
newprofile.replace_int("course_folder", config.child_value("course_folder")) newprofile.replace_int("course_folder", config.child_value("course_folder"))
newprofile.replace_int( newprofile.replace_int("ms_banner_disp", config.child_value("ms_banner_disp"))
"ms_banner_disp", config.child_value("ms_banner_disp")
)
newprofile.replace_int("ms_down_info", config.child_value("ms_down_info")) newprofile.replace_int("ms_down_info", config.child_value("ms_down_info"))
newprofile.replace_int("ms_side_info", config.child_value("ms_side_info")) newprofile.replace_int("ms_side_info", config.child_value("ms_side_info"))
newprofile.replace_int("ms_raise_type", config.child_value("ms_raise_type")) newprofile.replace_int("ms_raise_type", config.child_value("ms_raise_type"))
@ -973,21 +904,15 @@ class PopnMusicEclale(PopnMusicBase):
customize = request.child("customize") customize = request.child("customize")
if customize is not None: if customize is not None:
newprofile.replace_int("effect_left", customize.child_value("effect_left")) newprofile.replace_int("effect_left", customize.child_value("effect_left"))
newprofile.replace_int( newprofile.replace_int("effect_center", customize.child_value("effect_center"))
"effect_center", customize.child_value("effect_center") newprofile.replace_int("effect_right", customize.child_value("effect_right"))
)
newprofile.replace_int(
"effect_right", customize.child_value("effect_right")
)
newprofile.replace_int("hukidashi", customize.child_value("hukidashi")) newprofile.replace_int("hukidashi", customize.child_value("hukidashi"))
newprofile.replace_int("comment_1", customize.child_value("comment_1")) newprofile.replace_int("comment_1", customize.child_value("comment_1"))
newprofile.replace_int("comment_2", customize.child_value("comment_2")) newprofile.replace_int("comment_2", customize.child_value("comment_2"))
event = request.child("event") event = request.child("event")
if event is not None: if event is not None:
newprofile.replace_int( newprofile.replace_int("event_enemy_medal", event.child_value("enemy_medal"))
"event_enemy_medal", event.child_value("enemy_medal")
)
newprofile.replace_int("event_hp", event.child_value("hp")) newprofile.replace_int("event_hp", event.child_value("hp"))
stamp = request.child("stamp") stamp = request.child("stamp")

View File

@ -113,9 +113,7 @@ class PopnMusicFantasia(PopnMusicBase):
base.add_child(Node.u8("mode", profile.get_int("mode", 0))) base.add_child(Node.u8("mode", profile.get_int("mode", 0)))
base.add_child(Node.s8("button", profile.get_int("button", 0))) base.add_child(Node.s8("button", profile.get_int("button", 0)))
base.add_child(Node.s8("last_play_flag", profile.get_int("last_play_flag", -1))) base.add_child(Node.s8("last_play_flag", profile.get_int("last_play_flag", -1)))
base.add_child( base.add_child(Node.u8("medal_and_friend", profile.get_int("medal_and_friend", 0)))
Node.u8("medal_and_friend", profile.get_int("medal_and_friend", 0))
)
base.add_child(Node.s8("category", profile.get_int("category", -1))) base.add_child(Node.s8("category", profile.get_int("category", -1)))
base.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1))) base.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1)))
base.add_child(Node.s16("chara", profile.get_int("chara", -1))) base.add_child(Node.s16("chara", profile.get_int("chara", -1)))
@ -128,58 +126,32 @@ class PopnMusicFantasia(PopnMusicBase):
base.add_child(Node.s32("option", profile.get_int("option", 0))) base.add_child(Node.s32("option", profile.get_int("option", 0)))
base.add_child(Node.s16("music", profile.get_int("music", -1))) base.add_child(Node.s16("music", profile.get_int("music", -1)))
base.add_child(Node.u16("ep", profile.get_int("ep", 0))) base.add_child(Node.u16("ep", profile.get_int("ep", 0)))
base.add_child( base.add_child(Node.s32_array("sp_color_flg", profile.get_int_array("sp_color_flg", 2)))
Node.s32_array("sp_color_flg", profile.get_int_array("sp_color_flg", 2))
)
base.add_child(Node.s32("read_news", profile.get_int("read_news", 0))) base.add_child(Node.s32("read_news", profile.get_int("read_news", 0)))
base.add_child( base.add_child(Node.s16("consecutive_days_coupon", profile.get_int("consecutive_days_coupon", 0)))
Node.s16(
"consecutive_days_coupon", profile.get_int("consecutive_days_coupon", 0)
)
)
base.add_child(Node.s8("staff", 0)) base.add_child(Node.s8("staff", 0))
# Player card section # Player card section
player_card_dict = profile.get_dict("player_card") player_card_dict = profile.get_dict("player_card")
player_card = Node.void("player_card") player_card = Node.void("player_card")
root.add_child(player_card) root.add_child(player_card)
player_card.add_child( player_card.add_child(Node.u8_array("title", player_card_dict.get_int_array("title", 2, [0, 1])))
Node.u8_array("title", player_card_dict.get_int_array("title", 2, [0, 1]))
)
player_card.add_child(Node.u8("frame", player_card_dict.get_int("frame"))) player_card.add_child(Node.u8("frame", player_card_dict.get_int("frame")))
player_card.add_child(Node.u8("base", player_card_dict.get_int("base"))) player_card.add_child(Node.u8("base", player_card_dict.get_int("base")))
player_card.add_child( player_card.add_child(Node.u8_array("seal", player_card_dict.get_int_array("seal", 2)))
Node.u8_array("seal", player_card_dict.get_int_array("seal", 2)) player_card.add_child(Node.s32_array("get_title", player_card_dict.get_int_array("get_title", 4)))
) player_card.add_child(Node.s32("get_frame", player_card_dict.get_int("get_frame")))
player_card.add_child( player_card.add_child(Node.s32("get_base", player_card_dict.get_int("get_base")))
Node.s32_array("get_title", player_card_dict.get_int_array("get_title", 4)) player_card.add_child(Node.s32_array("get_seal", player_card_dict.get_int_array("get_seal", 2)))
)
player_card.add_child(
Node.s32("get_frame", player_card_dict.get_int("get_frame"))
)
player_card.add_child(
Node.s32("get_base", player_card_dict.get_int("get_base"))
)
player_card.add_child(
Node.s32_array("get_seal", player_card_dict.get_int_array("get_seal", 2))
)
player_card.add_child(Node.s8("is_open", 1)) player_card.add_child(Node.s8("is_open", 1))
# Player card EX section # Player card EX section
player_card_ex = Node.void("player_card_ex") player_card_ex = Node.void("player_card_ex")
root.add_child(player_card_ex) root.add_child(player_card_ex)
player_card_ex.add_child( player_card_ex.add_child(Node.s32("get_title_ex", player_card_dict.get_int("get_title_ex")))
Node.s32("get_title_ex", player_card_dict.get_int("get_title_ex")) player_card_ex.add_child(Node.s32("get_frame_ex", player_card_dict.get_int("get_frame_ex")))
) player_card_ex.add_child(Node.s32("get_base_ex", player_card_dict.get_int("get_base_ex")))
player_card_ex.add_child( player_card_ex.add_child(Node.s32("get_seal_ex", player_card_dict.get_int("get_seal_ex")))
Node.s32("get_frame_ex", player_card_dict.get_int("get_frame_ex"))
)
player_card_ex.add_child(
Node.s32("get_base_ex", player_card_dict.get_int("get_base_ex"))
)
player_card_ex.add_child(
Node.s32("get_seal_ex", player_card_dict.get_int("get_seal_ex"))
)
# Statistics section and scores section # Statistics section and scores section
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
@ -201,18 +173,8 @@ class PopnMusicFantasia(PopnMusicBase):
rivalcount += 1 rivalcount += 1
base.add_child(Node.u8("active_fr_num", rivalcount)) base.add_child(Node.u8("active_fr_num", rivalcount))
last_played = [ last_played = [x[0] for x in self.data.local.music.get_last_played(self.game, self.music_version, userid, 3)]
x[0] most_played = [x[0] for x in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)]
for x in self.data.local.music.get_last_played(
self.game, self.music_version, userid, 3
)
]
most_played = [
x[0]
for x in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
]
while len(last_played) < 3: while len(last_played) < 3:
last_played.append(-1) last_played.append(-1)
while len(most_played) < 20: while len(most_played) < 20:
@ -222,9 +184,7 @@ class PopnMusicFantasia(PopnMusicBase):
clear_medal = [0] * self.GAME_MAX_MUSIC_ID clear_medal = [0] * self.GAME_MAX_MUSIC_ID
clear_medal_sub = [0] * self.GAME_MAX_MUSIC_ID clear_medal_sub = [0] * self.GAME_MAX_MUSIC_ID
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
if score.id > self.GAME_MAX_MUSIC_ID: if score.id > self.GAME_MAX_MUSIC_ID:
continue continue
@ -240,9 +200,7 @@ class PopnMusicFantasia(PopnMusicBase):
if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY: if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY:
continue continue
clear_medal[score.id] = clear_medal[ clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
score.id
] | self.__format_medal_for_score(score)
hiscore_index = (score.id * 4) + { hiscore_index = (score.id * 4) + {
self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION, self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION, self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
@ -252,15 +210,9 @@ class PopnMusicFantasia(PopnMusicBase):
hiscore_byte_pos = int((hiscore_index * 17) / 8) hiscore_byte_pos = int((hiscore_index * 17) / 8)
hiscore_bit_pos = int((hiscore_index * 17) % 8) hiscore_bit_pos = int((hiscore_index * 17) % 8)
hiscore_value = score.points << hiscore_bit_pos hiscore_value = score.points << hiscore_bit_pos
hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | ( hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | (hiscore_value & 0xFF)
hiscore_value & 0xFF hiscore_array[hiscore_byte_pos + 1] = hiscore_array[hiscore_byte_pos + 1] | ((hiscore_value >> 8) & 0xFF)
) hiscore_array[hiscore_byte_pos + 2] = hiscore_array[hiscore_byte_pos + 2] | ((hiscore_value >> 16) & 0xFF)
hiscore_array[hiscore_byte_pos + 1] = hiscore_array[
hiscore_byte_pos + 1
] | ((hiscore_value >> 8) & 0xFF)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[
hiscore_byte_pos + 2
] | ((hiscore_value >> 16) & 0xFF)
hiscore = bytes(hiscore_array) hiscore = bytes(hiscore_array)
@ -294,9 +246,7 @@ class PopnMusicFantasia(PopnMusicBase):
reflec_data = Node.void("reflec_data") reflec_data = Node.void("reflec_data")
root.add_child(reflec_data) root.add_child(reflec_data)
reflec_data.add_child( reflec_data.add_child(Node.s8_array("reflec", profile.get_int_array("reflec", 2)))
Node.s8_array("reflec", profile.get_int_array("reflec", 2))
)
# Navigate section # Navigate section
for i in range(3): for i in range(3):
@ -307,14 +257,10 @@ class PopnMusicFantasia(PopnMusicBase):
navigate.add_child(Node.s8("image", navigate_dict.get_int("image", -1))) navigate.add_child(Node.s8("image", navigate_dict.get_int("image", -1)))
navigate.add_child(Node.s8("level", navigate_dict.get_int("level", -1))) navigate.add_child(Node.s8("level", navigate_dict.get_int("level", -1)))
navigate.add_child(Node.s8("ojama", navigate_dict.get_int("ojama", -1))) navigate.add_child(Node.s8("ojama", navigate_dict.get_int("ojama", -1)))
navigate.add_child( navigate.add_child(Node.s16("limit_num", navigate_dict.get_int("limit_num", -1)))
Node.s16("limit_num", navigate_dict.get_int("limit_num", -1))
)
navigate.add_child(Node.s8("button", navigate_dict.get_int("button", -1))) navigate.add_child(Node.s8("button", navigate_dict.get_int("button", -1)))
navigate.add_child(Node.s8("life", navigate_dict.get_int("life", -1))) navigate.add_child(Node.s8("life", navigate_dict.get_int("life", -1)))
navigate.add_child( navigate.add_child(Node.s16("progress", navigate_dict.get_int("progress", -1)))
Node.s16("progress", navigate_dict.get_int("progress", -1))
)
return root return root
@ -331,9 +277,7 @@ class PopnMusicFantasia(PopnMusicBase):
clear_medal = [0] * self.GAME_MAX_MUSIC_ID clear_medal = [0] * self.GAME_MAX_MUSIC_ID
hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8) hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8)
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
if score.id > self.GAME_MAX_MUSIC_ID: if score.id > self.GAME_MAX_MUSIC_ID:
continue continue
@ -349,9 +293,7 @@ class PopnMusicFantasia(PopnMusicBase):
if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY: if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY:
continue continue
clear_medal[score.id] = clear_medal[ clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
score.id
] | self.__format_medal_for_score(score)
hiscore_index = (score.id * 4) + { hiscore_index = (score.id * 4) + {
self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION, self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION, self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
@ -361,24 +303,16 @@ class PopnMusicFantasia(PopnMusicBase):
hiscore_byte_pos = int((hiscore_index * 17) / 8) hiscore_byte_pos = int((hiscore_index * 17) / 8)
hiscore_bit_pos = int((hiscore_index * 17) % 8) hiscore_bit_pos = int((hiscore_index * 17) % 8)
hiscore_value = score.points << hiscore_bit_pos hiscore_value = score.points << hiscore_bit_pos
hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | ( hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | (hiscore_value & 0xFF)
hiscore_value & 0xFF hiscore_array[hiscore_byte_pos + 1] = hiscore_array[hiscore_byte_pos + 1] | ((hiscore_value >> 8) & 0xFF)
) hiscore_array[hiscore_byte_pos + 2] = hiscore_array[hiscore_byte_pos + 2] | ((hiscore_value >> 16) & 0xFF)
hiscore_array[hiscore_byte_pos + 1] = hiscore_array[
hiscore_byte_pos + 1
] | ((hiscore_value >> 8) & 0xFF)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[
hiscore_byte_pos + 2
] | ((hiscore_value >> 16) & 0xFF)
root.add_child(Node.u16_array("clear_medal", clear_medal)) root.add_child(Node.u16_array("clear_medal", clear_medal))
root.add_child(Node.binary("hiscore", bytes(hiscore_array))) root.add_child(Node.binary("hiscore", bytes(hiscore_array)))
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
# For some reason, Pop'n 20 sends us two profile saves, one with 'not done yet' # For some reason, Pop'n 20 sends us two profile saves, one with 'not done yet'
# so we only want to process the done yet node. The 'not gameover' save has # so we only want to process the done yet node. The 'not gameover' save has
# jubeat collabo stuff set in it, but we don't use that so it doesn't matter. # jubeat collabo stuff set in it, but we don't use that so it doesn't matter.
@ -396,17 +330,11 @@ class PopnMusicFantasia(PopnMusicBase):
newprofile.replace_int("category", request.child_value("category")) newprofile.replace_int("category", request.child_value("category"))
newprofile.replace_int("sub_category", request.child_value("sub_category")) newprofile.replace_int("sub_category", request.child_value("sub_category"))
newprofile.replace_int("chara_category", request.child_value("chara_category")) newprofile.replace_int("chara_category", request.child_value("chara_category"))
newprofile.replace_int( newprofile.replace_int("medal_and_friend", request.child_value("medal_and_friend"))
"medal_and_friend", request.child_value("medal_and_friend")
)
newprofile.replace_int("ep", request.child_value("ep")) newprofile.replace_int("ep", request.child_value("ep"))
newprofile.replace_int_array( newprofile.replace_int_array("sp_color_flg", 2, request.child_value("sp_color_flg"))
"sp_color_flg", 2, request.child_value("sp_color_flg")
)
newprofile.replace_int("read_news", request.child_value("read_news")) newprofile.replace_int("read_news", request.child_value("read_news"))
newprofile.replace_int( newprofile.replace_int("consecutive_days_coupon", request.child_value("consecutive_days_coupon"))
"consecutive_days_coupon", request.child_value("consecutive_days_coupon")
)
newprofile.replace_int("tutorial", request.child_value("tutorial")) newprofile.replace_int("tutorial", request.child_value("tutorial"))
newprofile.replace_int("music_open_pt", request.child_value("music_open_pt")) newprofile.replace_int("music_open_pt", request.child_value("music_open_pt"))
newprofile.replace_int("collabo", request.child_value("collabo")) newprofile.replace_int("collabo", request.child_value("collabo"))
@ -428,29 +356,17 @@ class PopnMusicFantasia(PopnMusicBase):
player_card_dict.replace_int("frame", request.child_value("frame")) player_card_dict.replace_int("frame", request.child_value("frame"))
player_card_dict.replace_int("base", request.child_value("base")) player_card_dict.replace_int("base", request.child_value("base"))
player_card_dict.replace_int_array("seal", 2, request.child_value("seal")) player_card_dict.replace_int_array("seal", 2, request.child_value("seal"))
player_card_dict.replace_int_array( player_card_dict.replace_int_array("get_title", 4, request.child_value("get_title"))
"get_title", 4, request.child_value("get_title")
)
player_card_dict.replace_int("get_frame", request.child_value("get_frame")) player_card_dict.replace_int("get_frame", request.child_value("get_frame"))
player_card_dict.replace_int("get_base", request.child_value("get_base")) player_card_dict.replace_int("get_base", request.child_value("get_base"))
player_card_dict.replace_int_array( player_card_dict.replace_int_array("get_seal", 2, request.child_value("get_seal"))
"get_seal", 2, request.child_value("get_seal")
)
player_card_ex = request.child("player_card_ex") player_card_ex = request.child("player_card_ex")
if player_card_ex is not None: if player_card_ex is not None:
player_card_dict.replace_int( player_card_dict.replace_int("get_title_ex", player_card_ex.child_value("get_title_ex"))
"get_title_ex", player_card_ex.child_value("get_title_ex") player_card_dict.replace_int("get_frame_ex", player_card_ex.child_value("get_frame_ex"))
) player_card_dict.replace_int("get_base_ex", player_card_ex.child_value("get_base_ex"))
player_card_dict.replace_int( player_card_dict.replace_int("get_seal_ex", player_card_ex.child_value("get_seal_ex"))
"get_frame_ex", player_card_ex.child_value("get_frame_ex")
)
player_card_dict.replace_int(
"get_base_ex", player_card_ex.child_value("get_base_ex")
)
player_card_dict.replace_int(
"get_seal_ex", player_card_ex.child_value("get_seal_ex")
)
newprofile.replace_dict("player_card", player_card_dict) newprofile.replace_dict("player_card", player_card_dict)
# Extract navigate stuff # Extract navigate stuff
@ -462,9 +378,7 @@ class PopnMusicFantasia(PopnMusicBase):
navigate_dict.replace_int("image", navigate.child_value("image")) navigate_dict.replace_int("image", navigate.child_value("image"))
navigate_dict.replace_int("level", navigate.child_value("level")) navigate_dict.replace_int("level", navigate.child_value("level"))
navigate_dict.replace_int("ojama", navigate.child_value("ojama")) navigate_dict.replace_int("ojama", navigate.child_value("ojama"))
navigate_dict.replace_int( navigate_dict.replace_int("limit_num", navigate.child_value("limit_num"))
"limit_num", navigate.child_value("limit_num")
)
navigate_dict.replace_int("button", navigate.child_value("button")) navigate_dict.replace_int("button", navigate.child_value("button"))
navigate_dict.replace_int("life", navigate.child_value("life")) navigate_dict.replace_int("life", navigate.child_value("life"))
navigate_dict.replace_int("progress", navigate.child_value("progress")) navigate_dict.replace_int("progress", navigate.child_value("progress"))
@ -549,9 +463,7 @@ class PopnMusicFantasia(PopnMusicBase):
machine = self.get_machine() machine = self.get_machine()
root = Node.void("playerdata") root = Node.void("playerdata")
root.add_child( root.add_child(Node.s8("pref", machine.data.get_int("pref", self.get_machine_region())))
Node.s8("pref", machine.data.get_int("pref", self.get_machine_region()))
)
if refid is None: if refid is None:
root.add_child(Node.string("name", "")) root.add_child(Node.string("name", ""))
@ -584,9 +496,7 @@ class PopnMusicFantasia(PopnMusicBase):
root.add_child(Node.string("message", "")) root.add_child(Node.string("message", ""))
return root return root
oldprofile = self.get_profile(userid) or Profile( oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
newprofile = self.unformat_profile(userid, request, oldprofile) newprofile = self.unformat_profile(userid, request, oldprofile)
if newprofile is not None: if newprofile is not None:
@ -597,22 +507,10 @@ class PopnMusicFantasia(PopnMusicBase):
root.add_child(Node.s16("chara", newprofile.get_int("chara", -1))) root.add_child(Node.s16("chara", newprofile.get_int("chara", -1)))
root.add_child(Node.u8("frame", player_card_dict.get_int("frame"))) root.add_child(Node.u8("frame", player_card_dict.get_int("frame")))
root.add_child(Node.u8("base", player_card_dict.get_int("base"))) root.add_child(Node.u8("base", player_card_dict.get_int("base")))
root.add_child( root.add_child(Node.u8("seal_1", player_card_dict.get_int_array("seal", 2)[0]))
Node.u8("seal_1", player_card_dict.get_int_array("seal", 2)[0]) root.add_child(Node.u8("seal_2", player_card_dict.get_int_array("seal", 2)[1]))
) root.add_child(Node.u8("title_1", player_card_dict.get_int_array("title", 2, [0, 1])[0]))
root.add_child( root.add_child(Node.u8("title_2", player_card_dict.get_int_array("title", 2, [0, 1])[1]))
Node.u8("seal_2", player_card_dict.get_int_array("seal", 2)[1])
)
root.add_child(
Node.u8(
"title_1", player_card_dict.get_int_array("title", 2, [0, 1])[0]
)
)
root.add_child(
Node.u8(
"title_2", player_card_dict.get_int_array("title", 2, [0, 1])[1]
)
)
root.add_child(Node.s16("recommend_1", -1)) root.add_child(Node.s16("recommend_1", -1))
root.add_child(Node.s16("recommend_2", -1)) root.add_child(Node.s16("recommend_2", -1))
root.add_child(Node.s16("recommend_3", -1)) root.add_child(Node.s16("recommend_3", -1))
@ -647,9 +545,7 @@ class PopnMusicFantasia(PopnMusicBase):
for rival in links[:2]: for rival in links[:2]:
rivalid = rival.other_userid rivalid = rival.other_userid
rivalprofile = profiles[rivalid] rivalprofile = profiles[rivalid]
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, rivalid)
self.game, self.music_version, rivalid
)
# First, output general profile info. # First, output general profile info.
friend = Node.void("friend") friend = Node.void("friend")
@ -661,9 +557,7 @@ class PopnMusicFantasia(PopnMusicBase):
# Set up some sane defaults. # Set up some sane defaults.
friend.add_child(Node.string("name", rivalprofile.get_str("name", "なし"))) friend.add_child(Node.string("name", rivalprofile.get_str("name", "なし")))
friend.add_child( friend.add_child(Node.string("g_pm_id", ID.format_extid(rivalprofile.extid)))
Node.string("g_pm_id", ID.format_extid(rivalprofile.extid))
)
friend.add_child(Node.s16("chara", rivalprofile.get_int("chara", -1))) friend.add_child(Node.s16("chara", rivalprofile.get_int("chara", -1)))
# Perform hiscore/medal conversion. # Perform hiscore/medal conversion.
@ -684,9 +578,7 @@ class PopnMusicFantasia(PopnMusicBase):
if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY: if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY:
continue continue
clear_medal[score.id] = clear_medal[ clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
score.id
] | self.__format_medal_for_score(score)
hiscore_index = (score.id * 4) + { hiscore_index = (score.id * 4) + {
self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION, self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION, self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
@ -696,15 +588,13 @@ class PopnMusicFantasia(PopnMusicBase):
hiscore_byte_pos = int((hiscore_index * 17) / 8) hiscore_byte_pos = int((hiscore_index * 17) / 8)
hiscore_bit_pos = int((hiscore_index * 17) % 8) hiscore_bit_pos = int((hiscore_index * 17) % 8)
hiscore_value = score.points << hiscore_bit_pos hiscore_value = score.points << hiscore_bit_pos
hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | ( hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | (hiscore_value & 0xFF)
hiscore_value & 0xFF hiscore_array[hiscore_byte_pos + 1] = hiscore_array[hiscore_byte_pos + 1] | (
(hiscore_value >> 8) & 0xFF
)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[hiscore_byte_pos + 2] | (
(hiscore_value >> 16) & 0xFF
) )
hiscore_array[hiscore_byte_pos + 1] = hiscore_array[
hiscore_byte_pos + 1
] | ((hiscore_value >> 8) & 0xFF)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[
hiscore_byte_pos + 2
] | ((hiscore_value >> 16) & 0xFF)
hiscore = bytes(hiscore_array) hiscore = bytes(hiscore_array)
friend.add_child(Node.u16_array("clear_medal", clear_medal)) friend.add_child(Node.u16_array("clear_medal", clear_medal))
@ -726,14 +616,10 @@ class PopnMusicFantasia(PopnMusicBase):
root.add_child(Node.s32("game_phase", game_phase)) root.add_child(Node.s32("game_phase", game_phase))
root.add_child(Node.s32("ir_phase", 0)) root.add_child(Node.s32("ir_phase", 0))
root.add_child(Node.s32("event_phase", event_phase)) root.add_child(Node.s32("event_phase", event_phase))
root.add_child( root.add_child(Node.s32("netvs_phase", 0)) # Net taisen mode, we don't support lobbies.
Node.s32("netvs_phase", 0)
) # Net taisen mode, we don't support lobbies.
root.add_child(Node.s32("card_phase", 6)) root.add_child(Node.s32("card_phase", 6))
root.add_child(Node.s32("illust_phase", 2)) root.add_child(Node.s32("illust_phase", 2))
root.add_child( root.add_child(Node.s32("psp_phase", 5)) # Unlock songs from Pop'n Music Portable.
Node.s32("psp_phase", 5)
) # Unlock songs from Pop'n Music Portable.
root.add_child(Node.s32("other_phase", 1)) root.add_child(Node.s32("other_phase", 1))
root.add_child(Node.s32("jubeat_phase", 1)) root.add_child(Node.s32("jubeat_phase", 1))
root.add_child(Node.s32("public_phase", 3)) root.add_child(Node.s32("public_phase", 3))

View File

@ -384,9 +384,7 @@ class PopnMusicKaimei(PopnMusicModernBase):
root = super().format_profile(userid, profile) root = super().format_profile(userid, profile)
account = root.child("account") account = root.child("account")
account.add_child( account.add_child(Node.s16("card_again_count", profile.get_int("card_again_count")))
Node.s16("card_again_count", profile.get_int("card_again_count"))
)
account.add_child(Node.s16("sp_riddles_id", profile.get_int("sp_riddles_id"))) account.add_child(Node.s16("sp_riddles_id", profile.get_int("sp_riddles_id")))
# Kaimei riddles events # Kaimei riddles events
@ -394,11 +392,7 @@ class PopnMusicKaimei(PopnMusicModernBase):
root.add_child(event2021) root.add_child(event2021)
event2021.add_child(Node.u32("point", profile.get_int("point"))) event2021.add_child(Node.u32("point", profile.get_int("point")))
event2021.add_child(Node.u8("step", profile.get_int("step"))) event2021.add_child(Node.u8("step", profile.get_int("step")))
event2021.add_child( event2021.add_child(Node.u32_array("quest_point", profile.get_int_array("quest_point", 8, [0] * 8)))
Node.u32_array(
"quest_point", profile.get_int_array("quest_point", 8, [0] * 8)
)
)
event2021.add_child(Node.u8("step_nos", profile.get_int("step_nos"))) event2021.add_child(Node.u8("step_nos", profile.get_int("step_nos")))
event2021.add_child( event2021.add_child(
Node.u32_array( Node.u32_array(
@ -428,9 +422,7 @@ class PopnMusicKaimei(PopnMusicModernBase):
sh_riddles.add_child(Node.u32("sh_riddles_id", riddle)) sh_riddles.add_child(Node.u32("sh_riddles_id", riddle))
# Set up kaimei riddles achievements # Set up kaimei riddles achievements
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for achievement in achievements: for achievement in achievements:
if achievement.type == "riddle": if achievement.type == "riddle":
kaimei_gauge = achievement.data.get_int("kaimei_gauge") kaimei_gauge = achievement.data.get_int("kaimei_gauge")
@ -449,32 +441,22 @@ class PopnMusicKaimei(PopnMusicModernBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = super().unformat_profile(userid, request, oldprofile) newprofile = super().unformat_profile(userid, request, oldprofile)
account = request.child("account") account = request.child("account")
if account is not None: if account is not None:
newprofile.replace_int( newprofile.replace_int("card_again_count", account.child_value("card_again_count"))
"card_again_count", account.child_value("card_again_count") newprofile.replace_int("sp_riddles_id", account.child_value("sp_riddles_id"))
)
newprofile.replace_int(
"sp_riddles_id", account.child_value("sp_riddles_id")
)
# Kaimei riddles events # Kaimei riddles events
event2021 = request.child("event2021") event2021 = request.child("event2021")
if event2021 is not None: if event2021 is not None:
newprofile.replace_int("point", event2021.child_value("point")) newprofile.replace_int("point", event2021.child_value("point"))
newprofile.replace_int("step", event2021.child_value("step")) newprofile.replace_int("step", event2021.child_value("step"))
newprofile.replace_int_array( newprofile.replace_int_array("quest_point", 8, event2021.child_value("quest_point"))
"quest_point", 8, event2021.child_value("quest_point")
)
newprofile.replace_int("step_nos", event2021.child_value("step_nos")) newprofile.replace_int("step_nos", event2021.child_value("step_nos"))
newprofile.replace_int_array( newprofile.replace_int_array("quest_point_nos", 13, event2021.child_value("quest_point_nos"))
"quest_point_nos", 13, event2021.child_value("quest_point_nos")
)
# Extract kaimei riddles achievements # Extract kaimei riddles achievements
for node in request.children: for node in request.children:

View File

@ -289,9 +289,7 @@ class PopnMusicLapistoria(PopnMusicBase):
if userid is None: if userid is None:
return root return root
oldprofile = self.get_profile(userid) or Profile( oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
newprofile = self.unformat_profile(userid, request, oldprofile) newprofile = self.unformat_profile(userid, request, oldprofile)
if newprofile is not None: if newprofile is not None:
@ -334,12 +332,8 @@ class PopnMusicLapistoria(PopnMusicBase):
return root return root
rivalid = links[no].other_userid rivalid = links[no].other_userid
rivalprofile = profiles[rivalid] rivalprofile = profiles[rivalid]
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, rivalid)
self.game, self.music_version, rivalid achievements = self.data.local.user.get_achievements(self.game, self.version, rivalid)
)
achievements = self.data.local.user.get_achievements(
self.game, self.version, rivalid
)
# First, output general profile info. # First, output general profile info.
friend = Node.void("friend") friend = Node.void("friend")
@ -474,9 +468,7 @@ class PopnMusicLapistoria(PopnMusicBase):
self.GAME_PLAY_MEDAL_STAR_FULL_COMBO: self.PLAY_MEDAL_STAR_FULL_COMBO, self.GAME_PLAY_MEDAL_STAR_FULL_COMBO: self.PLAY_MEDAL_STAR_FULL_COMBO,
self.GAME_PLAY_MEDAL_PERFECT: self.PLAY_MEDAL_PERFECT, self.GAME_PLAY_MEDAL_PERFECT: self.PLAY_MEDAL_PERFECT,
}[medal] }[medal]
self.update_score( self.update_score(userid, songid, chart, points, medal, combo=combo, stats=stats)
userid, songid, chart, points, medal, combo=combo, stats=stats
)
return root return root
def handle_player22_write_course_request(self, request: Node) -> Node: def handle_player22_write_course_request(self, request: Node) -> Node:
@ -496,9 +488,7 @@ class PopnMusicLapistoria(PopnMusicBase):
if course_id is not None: if course_id is not None:
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
pref = request.child_value("pref") or self.get_machine_region() pref = request.child_value("pref") or self.get_machine_region()
profile = self.get_profile(userid) or Profile( profile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
course = self.data.local.user.get_achievement( course = self.data.local.user.get_achievement(
self.game, self.game,
@ -569,12 +559,8 @@ class PopnMusicLapistoria(PopnMusicBase):
key=lambda entry: entry[1].data.get_int("total_score"), key=lambda entry: entry[1].data.get_int("total_score"),
reverse=True, reverse=True,
) )
pref_ranking = [ pref_ranking = [c for c in global_ranking if c[1].data.get_int("pref") == pref]
c for c in global_ranking if c[1].data.get_int("pref") == pref local_ranking = [c for c in global_ranking if c[1].data.get_int("lid") == machine.arcade]
]
local_ranking = [
c for c in global_ranking if c[1].data.get_int("lid") == machine.arcade
]
global_rank = len(global_ranking) global_rank = len(global_ranking)
pref_rank = len(pref_ranking) pref_rank = len(pref_ranking)
@ -630,9 +616,7 @@ class PopnMusicLapistoria(PopnMusicBase):
account.add_child(Node.s8("is_conv", 0)) account.add_child(Node.s8("is_conv", 0))
account.add_child(Node.s16("item_type", 0)) account.add_child(Node.s16("item_type", 0))
account.add_child(Node.s16("item_id", 0)) account.add_child(Node.s16("item_id", 0))
account.add_child( account.add_child(Node.s16_array("license_data", [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]))
Node.s16_array("license_data", [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1])
)
# Statistics section and scores section # Statistics section and scores section
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
@ -657,18 +641,8 @@ class PopnMusicLapistoria(PopnMusicBase):
account.add_child(Node.u8("active_fr_num", rivalcount)) account.add_child(Node.u8("active_fr_num", rivalcount))
# Add scores section # Add scores section
last_played = [ last_played = [x[0] for x in self.data.local.music.get_last_played(self.game, self.music_version, userid, 5)]
x[0] most_played = [x[0] for x in self.data.local.music.get_most_played(self.game, self.music_version, userid, 10)]
for x in self.data.local.music.get_last_played(
self.game, self.music_version, userid, 5
)
]
most_played = [
x[0]
for x in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 10
)
]
while len(last_played) < 5: while len(last_played) < 5:
last_played.append(-1) last_played.append(-1)
while len(most_played) < 10: while len(most_played) < 10:
@ -677,9 +651,7 @@ class PopnMusicLapistoria(PopnMusicBase):
account.add_child(Node.s16_array("my_best", most_played)) account.add_child(Node.s16_array("my_best", most_played))
account.add_child(Node.s16_array("latest_music", last_played)) account.add_child(Node.s16_array("latest_music", last_played))
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
# Skip any scores for chart types we don't support # Skip any scores for chart types we don't support
if score.chart not in [ if score.chart not in [
@ -754,9 +726,7 @@ class PopnMusicLapistoria(PopnMusicBase):
config.add_child(Node.u8("sheet", profile.get_int("sheet", 0))) config.add_child(Node.u8("sheet", profile.get_int("sheet", 0)))
config.add_child(Node.s8("category", profile.get_int("category", 1))) config.add_child(Node.s8("category", profile.get_int("category", 1)))
config.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1))) config.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1)))
config.add_child( config.add_child(Node.s8("chara_category", profile.get_int("chara_category", -1)))
Node.s8("chara_category", profile.get_int("chara_category", -1))
)
config.add_child(Node.s16("story_id", profile.get_int("story_id", -1))) config.add_child(Node.s16("story_id", profile.get_int("story_id", -1)))
config.add_child(Node.s16("course_id", profile.get_int("course_id", -1))) config.add_child(Node.s16("course_id", profile.get_int("course_id", -1)))
config.add_child(Node.s8("course_folder", profile.get_int("course_folder", -1))) config.add_child(Node.s8("course_folder", profile.get_int("course_folder", -1)))
@ -774,26 +744,16 @@ class PopnMusicLapistoria(PopnMusicBase):
option.add_child(Node.s16("hispeed", option_dict.get_int("hispeed", 10))) option.add_child(Node.s16("hispeed", option_dict.get_int("hispeed", 10)))
option.add_child(Node.u8("popkun", option_dict.get_int("popkun", 0))) option.add_child(Node.u8("popkun", option_dict.get_int("popkun", 0)))
option.add_child(Node.bool("hidden", option_dict.get_bool("hidden", False))) option.add_child(Node.bool("hidden", option_dict.get_bool("hidden", False)))
option.add_child( option.add_child(Node.s16("hidden_rate", option_dict.get_int("hidden_rate", -1)))
Node.s16("hidden_rate", option_dict.get_int("hidden_rate", -1))
)
option.add_child(Node.bool("sudden", option_dict.get_bool("sudden", False))) option.add_child(Node.bool("sudden", option_dict.get_bool("sudden", False)))
option.add_child( option.add_child(Node.s16("sudden_rate", option_dict.get_int("sudden_rate", -1)))
Node.s16("sudden_rate", option_dict.get_int("sudden_rate", -1))
)
option.add_child(Node.s8("randmir", option_dict.get_int("randmir", 0))) option.add_child(Node.s8("randmir", option_dict.get_int("randmir", 0)))
option.add_child(Node.s8("gauge_type", option_dict.get_int("gauge_type", 0))) option.add_child(Node.s8("gauge_type", option_dict.get_int("gauge_type", 0)))
option.add_child(Node.u8("ojama_0", option_dict.get_int("ojama_0", 0))) option.add_child(Node.u8("ojama_0", option_dict.get_int("ojama_0", 0)))
option.add_child(Node.u8("ojama_1", option_dict.get_int("ojama_1", 0))) option.add_child(Node.u8("ojama_1", option_dict.get_int("ojama_1", 0)))
option.add_child( option.add_child(Node.bool("forever_0", option_dict.get_bool("forever_0", False)))
Node.bool("forever_0", option_dict.get_bool("forever_0", False)) option.add_child(Node.bool("forever_1", option_dict.get_bool("forever_1", False)))
) option.add_child(Node.bool("full_setting", option_dict.get_bool("full_setting", False)))
option.add_child(
Node.bool("forever_1", option_dict.get_bool("forever_1", False))
)
option.add_child(
Node.bool("full_setting", option_dict.get_bool("full_setting", False))
)
# Set up info # Set up info
info = Node.void("info") info = Node.void("info")
@ -824,12 +784,7 @@ class PopnMusicLapistoria(PopnMusicBase):
game_config = self.get_game_config() game_config = self.get_game_config()
if game_config.get_bool("force_unlock_songs"): if game_config.get_bool("force_unlock_songs"):
songs = { songs = {song.id for song in self.data.local.music.get_all_songs(self.game, self.music_version)}
song.id
for song in self.data.local.music.get_all_songs(
self.game, self.music_version
)
}
for song in songs: for song in songs:
item = Node.void("item") item = Node.void("item")
root.add_child(item) root.add_child(item)
@ -839,9 +794,7 @@ class PopnMusicLapistoria(PopnMusicBase):
item.add_child(Node.bool("is_new", False)) item.add_child(Node.bool("is_new", False))
# Set up achievements # Set up achievements
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for achievement in achievements: for achievement in achievements:
if achievement.type == "item": if achievement.type == "item":
itemtype = achievement.data.get_int("type") itemtype = achievement.data.get_int("type")
@ -919,9 +872,7 @@ class PopnMusicLapistoria(PopnMusicBase):
course.add_child(Node.s32("stage3_score", stage3_score)) course.add_child(Node.s32("stage3_score", stage3_score))
course.add_child(Node.s32("stage4_score", stage4_score)) course.add_child(Node.s32("stage4_score", stage4_score))
course.add_child(Node.s32("total_score", total_score)) course.add_child(Node.s32("total_score", total_score))
course.add_child( course.add_child(Node.s16("max_cmbo", max_combo)) # Yes, it is misspelled.
Node.s16("max_cmbo", max_combo)
) # Yes, it is misspelled.
course.add_child(Node.s16("play_cnt", play_cnt)) course.add_child(Node.s16("play_cnt", play_cnt))
course.add_child(Node.s16("all_rank", 1)) # Unclear what this does. course.add_child(Node.s16("all_rank", 1)) # Unclear what this does.
@ -930,9 +881,7 @@ class PopnMusicLapistoria(PopnMusicBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
account = request.child("account") account = request.child("account")
@ -953,16 +902,12 @@ class PopnMusicLapistoria(PopnMusicBase):
newprofile.replace_int("sheet", config.child_value("sheet")) newprofile.replace_int("sheet", config.child_value("sheet"))
newprofile.replace_int("category", config.child_value("category")) newprofile.replace_int("category", config.child_value("category"))
newprofile.replace_int("sub_category", config.child_value("sub_category")) newprofile.replace_int("sub_category", config.child_value("sub_category"))
newprofile.replace_int( newprofile.replace_int("chara_category", config.child_value("chara_category"))
"chara_category", config.child_value("chara_category")
)
newprofile.replace_int("story_id", config.child_value("story_id")) newprofile.replace_int("story_id", config.child_value("story_id"))
newprofile.replace_int("course_id", config.child_value("course_id")) newprofile.replace_int("course_id", config.child_value("course_id"))
newprofile.replace_int("course_folder", config.child_value("course_folder")) newprofile.replace_int("course_folder", config.child_value("course_folder"))
newprofile.replace_int("story_folder", config.child_value("story_folder")) newprofile.replace_int("story_folder", config.child_value("story_folder"))
newprofile.replace_int( newprofile.replace_int("ms_banner_disp", config.child_value("ms_banner_disp"))
"ms_banner_disp", config.child_value("ms_banner_disp")
)
newprofile.replace_int("ms_down_info", config.child_value("ms_down_info")) newprofile.replace_int("ms_down_info", config.child_value("ms_down_info"))
newprofile.replace_int("ms_side_info", config.child_value("ms_side_info")) newprofile.replace_int("ms_side_info", config.child_value("ms_side_info"))
newprofile.replace_int("ms_raise_type", config.child_value("ms_raise_type")) newprofile.replace_int("ms_raise_type", config.child_value("ms_raise_type"))
@ -1088,9 +1033,7 @@ class PopnMusicLapistoria(PopnMusicBase):
root.add_child(Node.s32("option", profile.get_int("option", 0))) root.add_child(Node.s32("option", profile.get_int("option", 0)))
root.add_child(Node.s8("result", 1)) root.add_child(Node.s8("result", 1))
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
if score.id > self.GAME_MAX_MUSIC_ID: if score.id > self.GAME_MAX_MUSIC_ID:
continue continue

View File

@ -126,9 +126,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
base.add_child(Node.u8("mode", profile.get_int("mode", 0))) base.add_child(Node.u8("mode", profile.get_int("mode", 0)))
base.add_child(Node.s8("button", profile.get_int("button", 0))) base.add_child(Node.s8("button", profile.get_int("button", 0)))
base.add_child(Node.s8("last_play_flag", profile.get_int("last_play_flag", -1))) base.add_child(Node.s8("last_play_flag", profile.get_int("last_play_flag", -1)))
base.add_child( base.add_child(Node.u8("medal_and_friend", profile.get_int("medal_and_friend", 0)))
Node.u8("medal_and_friend", profile.get_int("medal_and_friend", 0))
)
base.add_child(Node.s8("category", profile.get_int("category", -1))) base.add_child(Node.s8("category", profile.get_int("category", -1)))
base.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1))) base.add_child(Node.s8("sub_category", profile.get_int("sub_category", -1)))
base.add_child(Node.s16("chara", profile.get_int("chara", -1))) base.add_child(Node.s16("chara", profile.get_int("chara", -1)))
@ -141,15 +139,9 @@ class PopnMusicSunnyPark(PopnMusicBase):
base.add_child(Node.s32("option", profile.get_int("option", 0))) base.add_child(Node.s32("option", profile.get_int("option", 0)))
base.add_child(Node.s16("music", profile.get_int("music", -1))) base.add_child(Node.s16("music", profile.get_int("music", -1)))
base.add_child(Node.u16("ep", profile.get_int("ep", 0))) base.add_child(Node.u16("ep", profile.get_int("ep", 0)))
base.add_child( base.add_child(Node.s32_array("sp_color_flg", profile.get_int_array("sp_color_flg", 2)))
Node.s32_array("sp_color_flg", profile.get_int_array("sp_color_flg", 2))
)
base.add_child(Node.s32("read_news", profile.get_int("read_news", 0))) base.add_child(Node.s32("read_news", profile.get_int("read_news", 0)))
base.add_child( base.add_child(Node.s16("consecutive_days_coupon", profile.get_int("consecutive_days_coupon", 0)))
Node.s16(
"consecutive_days_coupon", profile.get_int("consecutive_days_coupon", 0)
)
)
base.add_child(Node.s8("staff", 0)) base.add_child(Node.s8("staff", 0))
# These are probably from an old event, but if they aren't present and defaulted, # These are probably from an old event, but if they aren't present and defaulted,
# then different songs show up in the Zoo event. # then different songs show up in the Zoo event.
@ -159,9 +151,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
profile.get_int_array("gitadora_point", 3, [2000, 2000, 2000]), profile.get_int_array("gitadora_point", 3, [2000, 2000, 2000]),
) )
) )
base.add_child( base.add_child(Node.u8("gitadora_select", profile.get_int("gitadora_select", 2)))
Node.u8("gitadora_select", profile.get_int("gitadora_select", 2))
)
# Statistics section and scores section # Statistics section and scores section
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
@ -183,18 +173,8 @@ class PopnMusicSunnyPark(PopnMusicBase):
rivalcount += 1 rivalcount += 1
base.add_child(Node.u8("active_fr_num", rivalcount)) base.add_child(Node.u8("active_fr_num", rivalcount))
last_played = [ last_played = [x[0] for x in self.data.local.music.get_last_played(self.game, self.music_version, userid, 3)]
x[0] most_played = [x[0] for x in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)]
for x in self.data.local.music.get_last_played(
self.game, self.music_version, userid, 3
)
]
most_played = [
x[0]
for x in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
]
while len(last_played) < 3: while len(last_played) < 3:
last_played.append(-1) last_played.append(-1)
while len(most_played) < 20: while len(most_played) < 20:
@ -204,9 +184,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
clear_medal = [0] * self.GAME_MAX_MUSIC_ID clear_medal = [0] * self.GAME_MAX_MUSIC_ID
clear_medal_sub = [0] * self.GAME_MAX_MUSIC_ID clear_medal_sub = [0] * self.GAME_MAX_MUSIC_ID
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
if score.id > self.GAME_MAX_MUSIC_ID: if score.id > self.GAME_MAX_MUSIC_ID:
continue continue
@ -222,9 +200,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY: if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY:
continue continue
clear_medal[score.id] = clear_medal[ clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
score.id
] | self.__format_medal_for_score(score)
hiscore_index = (score.id * 4) + { hiscore_index = (score.id * 4) + {
self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION, self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION, self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
@ -234,15 +210,9 @@ class PopnMusicSunnyPark(PopnMusicBase):
hiscore_byte_pos = int((hiscore_index * 17) / 8) hiscore_byte_pos = int((hiscore_index * 17) / 8)
hiscore_bit_pos = int((hiscore_index * 17) % 8) hiscore_bit_pos = int((hiscore_index * 17) % 8)
hiscore_value = score.points << hiscore_bit_pos hiscore_value = score.points << hiscore_bit_pos
hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | ( hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | (hiscore_value & 0xFF)
hiscore_value & 0xFF hiscore_array[hiscore_byte_pos + 1] = hiscore_array[hiscore_byte_pos + 1] | ((hiscore_value >> 8) & 0xFF)
) hiscore_array[hiscore_byte_pos + 2] = hiscore_array[hiscore_byte_pos + 2] | ((hiscore_value >> 16) & 0xFF)
hiscore_array[hiscore_byte_pos + 1] = hiscore_array[
hiscore_byte_pos + 1
] | ((hiscore_value >> 8) & 0xFF)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[
hiscore_byte_pos + 2
] | ((hiscore_value >> 16) & 0xFF)
hiscore = bytes(hiscore_array) hiscore = bytes(hiscore_array)
@ -263,85 +233,37 @@ class PopnMusicSunnyPark(PopnMusicBase):
avatar.add_child(Node.u8("body", avatar_dict.get_int("body", 0))) avatar.add_child(Node.u8("body", avatar_dict.get_int("body", 0)))
avatar.add_child(Node.u8("effect", avatar_dict.get_int("effect", 0))) avatar.add_child(Node.u8("effect", avatar_dict.get_int("effect", 0)))
avatar.add_child(Node.u8("object", avatar_dict.get_int("object", 0))) avatar.add_child(Node.u8("object", avatar_dict.get_int("object", 0)))
avatar.add_child( avatar.add_child(Node.u8_array("comment", avatar_dict.get_int_array("comment", 2)))
Node.u8_array("comment", avatar_dict.get_int_array("comment", 2)) avatar.add_child(Node.s32_array("get_hair", avatar_dict.get_int_array("get_hair", 2)))
) avatar.add_child(Node.s32_array("get_face", avatar_dict.get_int_array("get_face", 2)))
avatar.add_child( avatar.add_child(Node.s32_array("get_body", avatar_dict.get_int_array("get_body", 2)))
Node.s32_array("get_hair", avatar_dict.get_int_array("get_hair", 2)) avatar.add_child(Node.s32_array("get_effect", avatar_dict.get_int_array("get_effect", 2)))
) avatar.add_child(Node.s32_array("get_object", avatar_dict.get_int_array("get_object", 2)))
avatar.add_child( avatar.add_child(Node.s32_array("get_comment_over", avatar_dict.get_int_array("get_comment_over", 3)))
Node.s32_array("get_face", avatar_dict.get_int_array("get_face", 2)) avatar.add_child(Node.s32_array("get_comment_under", avatar_dict.get_int_array("get_comment_under", 3)))
)
avatar.add_child(
Node.s32_array("get_body", avatar_dict.get_int_array("get_body", 2))
)
avatar.add_child(
Node.s32_array("get_effect", avatar_dict.get_int_array("get_effect", 2))
)
avatar.add_child(
Node.s32_array("get_object", avatar_dict.get_int_array("get_object", 2))
)
avatar.add_child(
Node.s32_array(
"get_comment_over", avatar_dict.get_int_array("get_comment_over", 3)
)
)
avatar.add_child(
Node.s32_array(
"get_comment_under", avatar_dict.get_int_array("get_comment_under", 3)
)
)
# Avatar add section # Avatar add section
avatar_add_dict = profile.get_dict("avatar_add") avatar_add_dict = profile.get_dict("avatar_add")
avatar_add = Node.void("avatar_add") avatar_add = Node.void("avatar_add")
root.add_child(avatar_add) root.add_child(avatar_add)
avatar_add.add_child( avatar_add.add_child(Node.s32_array("get_hair", avatar_add_dict.get_int_array("get_hair", 2)))
Node.s32_array("get_hair", avatar_add_dict.get_int_array("get_hair", 2)) avatar_add.add_child(Node.s32_array("get_face", avatar_add_dict.get_int_array("get_face", 2)))
) avatar_add.add_child(Node.s32_array("get_body", avatar_add_dict.get_int_array("get_body", 2)))
avatar_add.add_child( avatar_add.add_child(Node.s32_array("get_effect", avatar_add_dict.get_int_array("get_effect", 2)))
Node.s32_array("get_face", avatar_add_dict.get_int_array("get_face", 2)) avatar_add.add_child(Node.s32_array("get_object", avatar_add_dict.get_int_array("get_object", 2)))
) avatar_add.add_child(Node.s32_array("get_comment_over", avatar_add_dict.get_int_array("get_comment_over", 2)))
avatar_add.add_child(
Node.s32_array("get_body", avatar_add_dict.get_int_array("get_body", 2))
)
avatar_add.add_child(
Node.s32_array("get_effect", avatar_add_dict.get_int_array("get_effect", 2))
)
avatar_add.add_child(
Node.s32_array("get_object", avatar_add_dict.get_int_array("get_object", 2))
)
avatar_add.add_child(
Node.s32_array(
"get_comment_over", avatar_add_dict.get_int_array("get_comment_over", 2)
)
)
avatar_add.add_child( avatar_add.add_child(
Node.s32_array( Node.s32_array(
"get_comment_under", "get_comment_under",
avatar_add_dict.get_int_array("get_comment_under", 2), avatar_add_dict.get_int_array("get_comment_under", 2),
) )
) )
avatar_add.add_child( avatar_add.add_child(Node.s32_array("new_hair", avatar_add_dict.get_int_array("new_hair", 2)))
Node.s32_array("new_hair", avatar_add_dict.get_int_array("new_hair", 2)) avatar_add.add_child(Node.s32_array("new_face", avatar_add_dict.get_int_array("new_face", 2)))
) avatar_add.add_child(Node.s32_array("new_body", avatar_add_dict.get_int_array("new_body", 2)))
avatar_add.add_child( avatar_add.add_child(Node.s32_array("new_effect", avatar_add_dict.get_int_array("new_effect", 2)))
Node.s32_array("new_face", avatar_add_dict.get_int_array("new_face", 2)) avatar_add.add_child(Node.s32_array("new_object", avatar_add_dict.get_int_array("new_object", 2)))
) avatar_add.add_child(Node.s32_array("new_comment_over", avatar_add_dict.get_int_array("new_comment_over", 2)))
avatar_add.add_child(
Node.s32_array("new_body", avatar_add_dict.get_int_array("new_body", 2))
)
avatar_add.add_child(
Node.s32_array("new_effect", avatar_add_dict.get_int_array("new_effect", 2))
)
avatar_add.add_child(
Node.s32_array("new_object", avatar_add_dict.get_int_array("new_object", 2))
)
avatar_add.add_child(
Node.s32_array(
"new_comment_over", avatar_add_dict.get_int_array("new_comment_over", 2)
)
)
avatar_add.add_child( avatar_add.add_child(
Node.s32_array( Node.s32_array(
"new_comment_under", "new_comment_under",
@ -383,35 +305,17 @@ class PopnMusicSunnyPark(PopnMusicBase):
zoo = Node.void("zoo") zoo = Node.void("zoo")
root.add_child(zoo) root.add_child(zoo)
zoo.add_child(Node.u16_array("point", zoo_dict.get_int_array("point", 5))) zoo.add_child(Node.u16_array("point", zoo_dict.get_int_array("point", 5)))
zoo.add_child( zoo.add_child(Node.s32_array("music_list", zoo_dict.get_int_array("music_list", 2)))
Node.s32_array("music_list", zoo_dict.get_int_array("music_list", 2)) zoo.add_child(Node.s8_array("today_play_flag", zoo_dict.get_int_array("today_play_flag", 4)))
)
zoo.add_child(
Node.s8_array(
"today_play_flag", zoo_dict.get_int_array("today_play_flag", 4)
)
)
# Pop'n Walker event # Pop'n Walker event
personal_event_dict = profile.get_dict("personal_event") personal_event_dict = profile.get_dict("personal_event")
personal_event = Node.void("personal_event") personal_event = Node.void("personal_event")
root.add_child(personal_event) root.add_child(personal_event)
personal_event.add_child( personal_event.add_child(Node.s16_array("pos", personal_event_dict.get_int_array("pos", 2)))
Node.s16_array("pos", personal_event_dict.get_int_array("pos", 2)) personal_event.add_child(Node.s16("point", personal_event_dict.get_int("point")))
) personal_event.add_child(Node.u32_array("walk_data", personal_event_dict.get_int_array("walk_data", 128)))
personal_event.add_child( personal_event.add_child(Node.u32_array("event_data", personal_event_dict.get_int_array("event_data", 4)))
Node.s16("point", personal_event_dict.get_int("point"))
)
personal_event.add_child(
Node.u32_array(
"walk_data", personal_event_dict.get_int_array("walk_data", 128)
)
)
personal_event.add_child(
Node.u32_array(
"event_data", personal_event_dict.get_int_array("event_data", 4)
)
)
# We don't support triple journey, so this is stubbed out. # We don't support triple journey, so this is stubbed out.
triple = Node.void("triple_journey") triple = Node.void("triple_journey")
@ -465,9 +369,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
clear_medal = [0] * self.GAME_MAX_MUSIC_ID clear_medal = [0] * self.GAME_MAX_MUSIC_ID
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
if score.id > self.GAME_MAX_MUSIC_ID: if score.id > self.GAME_MAX_MUSIC_ID:
continue continue
@ -483,17 +385,13 @@ class PopnMusicSunnyPark(PopnMusicBase):
if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY: if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY:
continue continue
clear_medal[score.id] = clear_medal[ clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
score.id
] | self.__format_medal_for_score(score)
root.add_child(Node.u16_array("clear_medal", clear_medal)) root.add_child(Node.u16_array("clear_medal", clear_medal))
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
newprofile.replace_int("option", request.child_value("option")) newprofile.replace_int("option", request.child_value("option"))
newprofile.replace_int("chara", request.child_value("chara")) newprofile.replace_int("chara", request.child_value("chara"))
@ -505,25 +403,15 @@ class PopnMusicSunnyPark(PopnMusicBase):
newprofile.replace_int("category", request.child_value("category")) newprofile.replace_int("category", request.child_value("category"))
newprofile.replace_int("sub_category", request.child_value("sub_category")) newprofile.replace_int("sub_category", request.child_value("sub_category"))
newprofile.replace_int("chara_category", request.child_value("chara_category")) newprofile.replace_int("chara_category", request.child_value("chara_category"))
newprofile.replace_int( newprofile.replace_int("medal_and_friend", request.child_value("medal_and_friend"))
"medal_and_friend", request.child_value("medal_and_friend")
)
newprofile.replace_int("ep", request.child_value("ep")) newprofile.replace_int("ep", request.child_value("ep"))
newprofile.replace_int_array( newprofile.replace_int_array("sp_color_flg", 2, request.child_value("sp_color_flg"))
"sp_color_flg", 2, request.child_value("sp_color_flg")
)
newprofile.replace_int("read_news", request.child_value("read_news")) newprofile.replace_int("read_news", request.child_value("read_news"))
newprofile.replace_int( newprofile.replace_int("consecutive_days_coupon", request.child_value("consecutive_days_coupon"))
"consecutive_days_coupon", request.child_value("consecutive_days_coupon")
)
newprofile.replace_int("tutorial", request.child_value("tutorial")) newprofile.replace_int("tutorial", request.child_value("tutorial"))
newprofile.replace_int("music_open_pt", request.child_value("music_open_pt")) newprofile.replace_int("music_open_pt", request.child_value("music_open_pt"))
newprofile.replace_int_array( newprofile.replace_int_array("gitadora_point", 3, request.child_value("gitadora_point"))
"gitadora_point", 3, request.child_value("gitadora_point") newprofile.replace_int("gitadora_select", request.child_value("gitadora_select"))
)
newprofile.replace_int(
"gitadora_select", request.child_value("gitadora_select")
)
sp_node = request.child("sp_data") sp_node = request.child("sp_data")
if sp_node is not None: if sp_node is not None:
@ -533,29 +421,17 @@ class PopnMusicSunnyPark(PopnMusicBase):
zoo_node = request.child("zoo") zoo_node = request.child("zoo")
if zoo_node is not None: if zoo_node is not None:
zoo_dict.replace_int_array("point", 5, zoo_node.child_value("point")) zoo_dict.replace_int_array("point", 5, zoo_node.child_value("point"))
zoo_dict.replace_int_array( zoo_dict.replace_int_array("music_list", 2, zoo_node.child_value("music_list"))
"music_list", 2, zoo_node.child_value("music_list") zoo_dict.replace_int_array("today_play_flag", 4, zoo_node.child_value("today_play_flag"))
)
zoo_dict.replace_int_array(
"today_play_flag", 4, zoo_node.child_value("today_play_flag")
)
newprofile.replace_dict("zoo", zoo_dict) newprofile.replace_dict("zoo", zoo_dict)
personal_event_dict = newprofile.get_dict("personal_event") personal_event_dict = newprofile.get_dict("personal_event")
personal_event_node = request.child("personal_event") personal_event_node = request.child("personal_event")
if personal_event_node is not None: if personal_event_node is not None:
personal_event_dict.replace_int_array( personal_event_dict.replace_int_array("pos", 2, personal_event_node.child_value("pos"))
"pos", 2, personal_event_node.child_value("pos") personal_event_dict.replace_int("point", personal_event_node.child_value("point"))
) personal_event_dict.replace_int_array("walk_data", 128, personal_event_node.child_value("walk_data"))
personal_event_dict.replace_int( personal_event_dict.replace_int_array("event_data", 4, personal_event_node.child_value("event_data"))
"point", personal_event_node.child_value("point")
)
personal_event_dict.replace_int_array(
"walk_data", 128, personal_event_node.child_value("walk_data")
)
personal_event_dict.replace_int_array(
"event_data", 4, personal_event_node.child_value("event_data")
)
newprofile.replace_dict("personal_event", personal_event_dict) newprofile.replace_dict("personal_event", personal_event_dict)
avatar_dict = newprofile.get_dict("avatar") avatar_dict = newprofile.get_dict("avatar")
@ -568,65 +444,29 @@ class PopnMusicSunnyPark(PopnMusicBase):
avatar_dict.replace_int_array("get_hair", 2, request.child_value("get_hair")) avatar_dict.replace_int_array("get_hair", 2, request.child_value("get_hair"))
avatar_dict.replace_int_array("get_face", 2, request.child_value("get_face")) avatar_dict.replace_int_array("get_face", 2, request.child_value("get_face"))
avatar_dict.replace_int_array("get_body", 2, request.child_value("get_body")) avatar_dict.replace_int_array("get_body", 2, request.child_value("get_body"))
avatar_dict.replace_int_array( avatar_dict.replace_int_array("get_effect", 2, request.child_value("get_effect"))
"get_effect", 2, request.child_value("get_effect") avatar_dict.replace_int_array("get_object", 2, request.child_value("get_object"))
) avatar_dict.replace_int_array("get_comment_over", 3, request.child_value("get_comment_over"))
avatar_dict.replace_int_array( avatar_dict.replace_int_array("get_comment_under", 3, request.child_value("get_comment_under"))
"get_object", 2, request.child_value("get_object")
)
avatar_dict.replace_int_array(
"get_comment_over", 3, request.child_value("get_comment_over")
)
avatar_dict.replace_int_array(
"get_comment_under", 3, request.child_value("get_comment_under")
)
newprofile.replace_dict("avatar", avatar_dict) newprofile.replace_dict("avatar", avatar_dict)
avatar_add_dict = newprofile.get_dict("avatar_add") avatar_add_dict = newprofile.get_dict("avatar_add")
avatar_add_node = request.child("avatar_add") avatar_add_node = request.child("avatar_add")
if avatar_add_node is not None: if avatar_add_node is not None:
avatar_add_dict.replace_int_array( avatar_add_dict.replace_int_array("get_hair", 2, avatar_add_node.child_value("get_hair"))
"get_hair", 2, avatar_add_node.child_value("get_hair") avatar_add_dict.replace_int_array("get_face", 2, avatar_add_node.child_value("get_face"))
) avatar_add_dict.replace_int_array("get_body", 2, avatar_add_node.child_value("get_body"))
avatar_add_dict.replace_int_array( avatar_add_dict.replace_int_array("get_effect", 2, avatar_add_node.child_value("get_effect"))
"get_face", 2, avatar_add_node.child_value("get_face") avatar_add_dict.replace_int_array("get_object", 2, avatar_add_node.child_value("get_object"))
) avatar_add_dict.replace_int_array("get_comment_over", 2, avatar_add_node.child_value("get_comment_over"))
avatar_add_dict.replace_int_array( avatar_add_dict.replace_int_array("get_comment_under", 2, avatar_add_node.child_value("get_comment_under"))
"get_body", 2, avatar_add_node.child_value("get_body") avatar_add_dict.replace_int_array("new_hair", 2, avatar_add_node.child_value("new_hair"))
) avatar_add_dict.replace_int_array("new_face", 2, avatar_add_node.child_value("new_face"))
avatar_add_dict.replace_int_array( avatar_add_dict.replace_int_array("new_body", 2, avatar_add_node.child_value("new_body"))
"get_effect", 2, avatar_add_node.child_value("get_effect") avatar_add_dict.replace_int_array("new_effect", 2, avatar_add_node.child_value("new_effect"))
) avatar_add_dict.replace_int_array("new_object", 2, avatar_add_node.child_value("new_object"))
avatar_add_dict.replace_int_array( avatar_add_dict.replace_int_array("new_comment_over", 2, avatar_add_node.child_value("new_comment_over"))
"get_object", 2, avatar_add_node.child_value("get_object") avatar_add_dict.replace_int_array("new_comment_under", 2, avatar_add_node.child_value("new_comment_under"))
)
avatar_add_dict.replace_int_array(
"get_comment_over", 2, avatar_add_node.child_value("get_comment_over")
)
avatar_add_dict.replace_int_array(
"get_comment_under", 2, avatar_add_node.child_value("get_comment_under")
)
avatar_add_dict.replace_int_array(
"new_hair", 2, avatar_add_node.child_value("new_hair")
)
avatar_add_dict.replace_int_array(
"new_face", 2, avatar_add_node.child_value("new_face")
)
avatar_add_dict.replace_int_array(
"new_body", 2, avatar_add_node.child_value("new_body")
)
avatar_add_dict.replace_int_array(
"new_effect", 2, avatar_add_node.child_value("new_effect")
)
avatar_add_dict.replace_int_array(
"new_object", 2, avatar_add_node.child_value("new_object")
)
avatar_add_dict.replace_int_array(
"new_comment_over", 2, avatar_add_node.child_value("new_comment_over")
)
avatar_add_dict.replace_int_array(
"new_comment_under", 2, avatar_add_node.child_value("new_comment_under")
)
newprofile.replace_dict("avatar_add", avatar_add_dict) newprofile.replace_dict("avatar_add", avatar_add_dict)
# Keep track of play statistics # Keep track of play statistics
@ -736,9 +576,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
machine = self.get_machine() machine = self.get_machine()
root = Node.void("playerdata") root = Node.void("playerdata")
root.add_child( root.add_child(Node.s8("pref", machine.data.get_int("pref", self.get_machine_region())))
Node.s8("pref", machine.data.get_int("pref", self.get_machine_region()))
)
if refid is None: if refid is None:
root.add_child(Node.string("name", "")) root.add_child(Node.string("name", ""))
root.add_child(Node.s8("get_coupon_cnt", -1)) root.add_child(Node.s8("get_coupon_cnt", -1))
@ -766,9 +604,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
root.add_child(Node.u8("comment_2", 0)) root.add_child(Node.u8("comment_2", 0))
return root return root
oldprofile = self.get_profile(userid) or Profile( oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
newprofile = self.unformat_profile(userid, request, oldprofile) newprofile = self.unformat_profile(userid, request, oldprofile)
if newprofile is not None: if newprofile is not None:
@ -783,12 +619,8 @@ class PopnMusicSunnyPark(PopnMusicBase):
root.add_child(Node.u8("body", avatar_dict.get_int("body", 0))) root.add_child(Node.u8("body", avatar_dict.get_int("body", 0)))
root.add_child(Node.u8("effect", avatar_dict.get_int("effect", 0))) root.add_child(Node.u8("effect", avatar_dict.get_int("effect", 0)))
root.add_child(Node.u8("object", avatar_dict.get_int("object", 0))) root.add_child(Node.u8("object", avatar_dict.get_int("object", 0)))
root.add_child( root.add_child(Node.u8("comment_1", avatar_dict.get_int_array("comment", 2)[0]))
Node.u8("comment_1", avatar_dict.get_int_array("comment", 2)[0]) root.add_child(Node.u8("comment_2", avatar_dict.get_int_array("comment", 2)[1]))
)
root.add_child(
Node.u8("comment_2", avatar_dict.get_int_array("comment", 2)[1])
)
return root return root
@ -819,9 +651,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
for rival in links[:2]: for rival in links[:2]:
rivalid = rival.other_userid rivalid = rival.other_userid
rivalprofile = profiles[rivalid] rivalprofile = profiles[rivalid]
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, rivalid)
self.game, self.music_version, rivalid
)
# First, output general profile info. # First, output general profile info.
friend = Node.void("friend") friend = Node.void("friend")
@ -833,9 +663,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
# Set up some sane defaults. # Set up some sane defaults.
friend.add_child(Node.string("name", rivalprofile.get_str("name", "なし"))) friend.add_child(Node.string("name", rivalprofile.get_str("name", "なし")))
friend.add_child( friend.add_child(Node.string("g_pm_id", ID.format_extid(rivalprofile.extid)))
Node.string("g_pm_id", ID.format_extid(rivalprofile.extid))
)
friend.add_child(Node.s16("chara", rivalprofile.get_int("chara", -1))) friend.add_child(Node.s16("chara", rivalprofile.get_int("chara", -1)))
# Set up player avatar. # Set up player avatar.
@ -845,9 +673,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
friend.add_child(Node.u8("body", avatar_dict.get_int("body", 0))) friend.add_child(Node.u8("body", avatar_dict.get_int("body", 0)))
friend.add_child(Node.u8("effect", avatar_dict.get_int("effect", 0))) friend.add_child(Node.u8("effect", avatar_dict.get_int("effect", 0)))
friend.add_child(Node.u8("object", avatar_dict.get_int("object", 0))) friend.add_child(Node.u8("object", avatar_dict.get_int("object", 0)))
friend.add_child( friend.add_child(Node.u8_array("comment", avatar_dict.get_int_array("comment", 2)))
Node.u8_array("comment", avatar_dict.get_int_array("comment", 2))
)
# Perform hiscore/medal conversion. # Perform hiscore/medal conversion.
hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8) hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8)
@ -867,9 +693,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY: if score.data.get_int("medal") == self.PLAY_MEDAL_NO_PLAY:
continue continue
clear_medal[score.id] = clear_medal[ clear_medal[score.id] = clear_medal[score.id] | self.__format_medal_for_score(score)
score.id
] | self.__format_medal_for_score(score)
hiscore_index = (score.id * 4) + { hiscore_index = (score.id * 4) + {
self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION, self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION, self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
@ -879,15 +703,13 @@ class PopnMusicSunnyPark(PopnMusicBase):
hiscore_byte_pos = int((hiscore_index * 17) / 8) hiscore_byte_pos = int((hiscore_index * 17) / 8)
hiscore_bit_pos = int((hiscore_index * 17) % 8) hiscore_bit_pos = int((hiscore_index * 17) % 8)
hiscore_value = score.points << hiscore_bit_pos hiscore_value = score.points << hiscore_bit_pos
hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | ( hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | (hiscore_value & 0xFF)
hiscore_value & 0xFF hiscore_array[hiscore_byte_pos + 1] = hiscore_array[hiscore_byte_pos + 1] | (
(hiscore_value >> 8) & 0xFF
)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[hiscore_byte_pos + 2] | (
(hiscore_value >> 16) & 0xFF
) )
hiscore_array[hiscore_byte_pos + 1] = hiscore_array[
hiscore_byte_pos + 1
] | ((hiscore_value >> 8) & 0xFF)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[
hiscore_byte_pos + 2
] | ((hiscore_value >> 16) & 0xFF)
hiscore = bytes(hiscore_array) hiscore = bytes(hiscore_array)
friend.add_child(Node.u16_array("clear_medal", clear_medal)) friend.add_child(Node.u16_array("clear_medal", clear_medal))

View File

@ -227,9 +227,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
# Format Scores # Format Scores
hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 7) * 17) + 7) / 8) hiscore_array = [0] * int((((self.GAME_MAX_MUSIC_ID * 7) * 17) + 7) / 8)
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.music_version, userid)
self.game, self.music_version, userid
)
for score in scores: for score in scores:
if score.id > self.GAME_MAX_MUSIC_ID: if score.id > self.GAME_MAX_MUSIC_ID:
continue continue
@ -245,12 +243,8 @@ class PopnMusicTuneStreet(PopnMusicBase):
flags = self.__format_flags_for_score(score) flags = self.__format_flags_for_score(score)
flags_index = score.id * 2 flags_index = score.id * 2
binary_profile[108 + flags_index] = binary_profile[108 + flags_index] | ( binary_profile[108 + flags_index] = binary_profile[108 + flags_index] | (flags & 0xFF)
flags & 0xFF binary_profile[109 + flags_index] = binary_profile[109 + flags_index] | ((flags >> 8) & 0xFF)
)
binary_profile[109 + flags_index] = binary_profile[109 + flags_index] | (
(flags >> 8) & 0xFF
)
if score.chart in [ if score.chart in [
self.CHART_TYPE_ENJOY_5_BUTTON, self.CHART_TYPE_ENJOY_5_BUTTON,
@ -272,23 +266,12 @@ class PopnMusicTuneStreet(PopnMusicBase):
hiscore_byte_pos = int((hiscore_index * 17) / 8) hiscore_byte_pos = int((hiscore_index * 17) / 8)
hiscore_bit_pos = int((hiscore_index * 17) % 8) hiscore_bit_pos = int((hiscore_index * 17) % 8)
hiscore_value = score.points << hiscore_bit_pos hiscore_value = score.points << hiscore_bit_pos
hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | ( hiscore_array[hiscore_byte_pos] = hiscore_array[hiscore_byte_pos] | (hiscore_value & 0xFF)
hiscore_value & 0xFF hiscore_array[hiscore_byte_pos + 1] = hiscore_array[hiscore_byte_pos + 1] | ((hiscore_value >> 8) & 0xFF)
) hiscore_array[hiscore_byte_pos + 2] = hiscore_array[hiscore_byte_pos + 2] | ((hiscore_value >> 16) & 0xFF)
hiscore_array[hiscore_byte_pos + 1] = hiscore_array[
hiscore_byte_pos + 1
] | ((hiscore_value >> 8) & 0xFF)
hiscore_array[hiscore_byte_pos + 2] = hiscore_array[
hiscore_byte_pos + 2
] | ((hiscore_value >> 16) & 0xFF)
# Format most played # Format most played
most_played = [ most_played = [x[0] for x in self.data.local.music.get_most_played(self.game, self.music_version, userid, 20)]
x[0]
for x in self.data.local.music.get_most_played(
self.game, self.music_version, userid, 20
)
]
while len(most_played) < 20: while len(most_played) < 20:
most_played.append(-1) most_played.append(-1)
profile_pos = 68 profile_pos = 68
@ -322,9 +305,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
bought_flg = town.get_int_array("bought_flg", 3) bought_flg = town.get_int_array("bought_flg", 3)
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")
force_unlock_customizations = game_config.get_bool( force_unlock_customizations = game_config.get_bool("force_unlock_customizations")
"force_unlock_customizations"
)
if force_unlock_songs: if force_unlock_songs:
bought_flg[0] = 0xFFFFFFFF bought_flg[0] = 0xFFFFFFFF
@ -390,9 +371,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Extract the playmode, important for scores later # Extract the playmode, important for scores later
@ -404,13 +383,9 @@ class PopnMusicTuneStreet(PopnMusicBase):
if "option" in request.attributes: if "option" in request.attributes:
newprofile.replace_int("option", int(request.attribute("option"))) newprofile.replace_int("option", int(request.attribute("option")))
if "last_play_flag" in request.attributes: if "last_play_flag" in request.attributes:
newprofile.replace_int( newprofile.replace_int("last_play_flag", int(request.attribute("last_play_flag")))
"last_play_flag", int(request.attribute("last_play_flag"))
)
if "medal_and_friend" in request.attributes: if "medal_and_friend" in request.attributes:
newprofile.replace_int( newprofile.replace_int("medal_and_friend", int(request.attribute("medal_and_friend")))
"medal_and_friend", int(request.attribute("medal_and_friend"))
)
if "music_num" in request.attributes: if "music_num" in request.attributes:
newprofile.replace_int("music", int(request.attribute("music_num"))) newprofile.replace_int("music", int(request.attribute("music_num")))
if "sheet_num" in request.attributes: if "sheet_num" in request.attributes:
@ -418,23 +393,15 @@ class PopnMusicTuneStreet(PopnMusicBase):
if "category_num" in request.attributes: if "category_num" in request.attributes:
newprofile.replace_int("category", int(request.attribute("category_num"))) newprofile.replace_int("category", int(request.attribute("category_num")))
if "read_news_no_max" in request.attributes: if "read_news_no_max" in request.attributes:
newprofile.replace_int( newprofile.replace_int("read_news", int(request.attribute("read_news_no_max")))
"read_news", int(request.attribute("read_news_no_max"))
)
if "jubeat_collabo" in request.attributes: if "jubeat_collabo" in request.attributes:
newprofile.replace_int( newprofile.replace_int("jubeat_collabo", int(request.attribute("jubeat_collabo")))
"jubeat_collabo", int(request.attribute("jubeat_collabo"))
)
if "norma_point" in request.attributes: if "norma_point" in request.attributes:
newprofile.replace_int("norma_point", int(request.attribute("norma_point"))) newprofile.replace_int("norma_point", int(request.attribute("norma_point")))
if "skin_tex_note" in request.attributes: if "skin_tex_note" in request.attributes:
newprofile.replace_int( newprofile.replace_int("skin_tex_note", int(request.attribute("skin_tex_note")))
"skin_tex_note", int(request.attribute("skin_tex_note"))
)
if "skin_tex_cmn" in request.attributes: if "skin_tex_cmn" in request.attributes:
newprofile.replace_int( newprofile.replace_int("skin_tex_cmn", int(request.attribute("skin_tex_cmn")))
"skin_tex_cmn", int(request.attribute("skin_tex_cmn"))
)
if "skin_sd_bgm" in request.attributes: if "skin_sd_bgm" in request.attributes:
newprofile.replace_int("skin_sd_bgm", int(request.attribute("skin_sd_bgm"))) newprofile.replace_int("skin_sd_bgm", int(request.attribute("skin_sd_bgm")))
if "skin_sd_se" in request.attributes: if "skin_sd_se" in request.attributes:
@ -532,19 +499,13 @@ class PopnMusicTuneStreet(PopnMusicBase):
if "play_type" in townnode.attributes: if "play_type" in townnode.attributes:
town.replace_int("play_type", int(townnode.attribute("play_type"))) town.replace_int("play_type", int(townnode.attribute("play_type")))
if "base" in townnode.attributes: if "base" in townnode.attributes:
town.replace_int_array( town.replace_int_array("base", 4, [int(x) for x in townnode.attribute("base").split(",")])
"base", 4, [int(x) for x in townnode.attribute("base").split(",")]
)
if "bought_flg" in townnode.attributes: if "bought_flg" in townnode.attributes:
bought_array = [ bought_array = [int(x) for x in townnode.attribute("bought_flg").split(",")]
int(x) for x in townnode.attribute("bought_flg").split(",")
]
if len(bought_array) == 3: if len(bought_array) == 3:
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")
force_unlock_customizations = game_config.get_bool( force_unlock_customizations = game_config.get_bool("force_unlock_customizations")
"force_unlock_customizations"
)
old_bought_array = town.get_int_array("bought_flg", 3) old_bought_array = town.get_int_array("bought_flg", 3)
if force_unlock_songs: if force_unlock_songs:
@ -578,10 +539,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
town.replace_int_array( town.replace_int_array(
f"building_{bid}", f"building_{bid}",
8, 8,
[ [int(x) for x in townnode.attribute(f"building_{bid}").split(",")],
int(x)
for x in townnode.attribute(f"building_{bid}").split(",")
],
) )
newprofile.replace_dict("town", town) newprofile.replace_dict("town", town)
@ -594,23 +552,17 @@ class PopnMusicTuneStreet(PopnMusicBase):
town_phase = game_config.get_int("town_phase") town_phase = game_config.get_int("town_phase")
root = Node.void("game") root = Node.void("game")
root.set_attribute( root.set_attribute("game_phase", str(game_phase)) # Phase unlocks, for song availability.
"game_phase", str(game_phase)
) # Phase unlocks, for song availability.
root.set_attribute("boss_battle_point", "1") root.set_attribute("boss_battle_point", "1")
root.set_attribute("boss_diff", "100,100,100,100,100,100,100,100,100,100") root.set_attribute("boss_diff", "100,100,100,100,100,100,100,100,100,100")
root.set_attribute("card_phase", "3") root.set_attribute("card_phase", "3")
root.set_attribute( root.set_attribute("event_phase", str(town_phase)) # Town mode, for the main event.
"event_phase", str(town_phase)
) # Town mode, for the main event.
root.set_attribute("gfdm_phase", "2") root.set_attribute("gfdm_phase", "2")
root.set_attribute("ir_phase", "14") root.set_attribute("ir_phase", "14")
root.set_attribute("jubeat_phase", "2") root.set_attribute("jubeat_phase", "2")
root.set_attribute("local_matching_enable", "1") root.set_attribute("local_matching_enable", "1")
root.set_attribute("matching_sec", "120") root.set_attribute("matching_sec", "120")
root.set_attribute( root.set_attribute("netvs_phase", "0") # Net taisen mode phase, maximum 18 (no lobby support).
"netvs_phase", "0"
) # Net taisen mode phase, maximum 18 (no lobby support).
return root return root
def handle_game_active_request(self, request: Node) -> Node: def handle_game_active_request(self, request: Node) -> Node:
@ -696,9 +648,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
if userid is None: if userid is None:
return root return root
oldprofile = self.get_profile(userid) or Profile( oldprofile = self.get_profile(userid) or Profile(self.game, self.version, refid, 0)
self.game, self.version, refid, 0
)
newprofile = self.unformat_profile(userid, request, oldprofile) newprofile = self.unformat_profile(userid, request, oldprofile)
if newprofile is not None: if newprofile is not None:

View File

@ -26,22 +26,14 @@ class ReflecBeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
CLEAR_TYPE_NO_PLAY: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY CLEAR_TYPE_NO_PLAY: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY
CLEAR_TYPE_FAILED: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED CLEAR_TYPE_FAILED: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED
CLEAR_TYPE_CLEARED: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_CLEARED CLEAR_TYPE_CLEARED: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_CLEARED
CLEAR_TYPE_HARD_CLEARED: Final[ CLEAR_TYPE_HARD_CLEARED: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_HARD_CLEARED
int CLEAR_TYPE_S_HARD_CLEARED: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_S_HARD_CLEARED
] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_HARD_CLEARED
CLEAR_TYPE_S_HARD_CLEARED: Final[
int
] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_S_HARD_CLEARED
# Combo types, as saved/loaded from the DB # Combo types, as saved/loaded from the DB
COMBO_TYPE_NONE: Final[int] = DBConstants.REFLEC_BEAT_COMBO_TYPE_NONE COMBO_TYPE_NONE: Final[int] = DBConstants.REFLEC_BEAT_COMBO_TYPE_NONE
COMBO_TYPE_ALMOST_COMBO: Final[ COMBO_TYPE_ALMOST_COMBO: Final[int] = DBConstants.REFLEC_BEAT_COMBO_TYPE_ALMOST_COMBO
int
] = DBConstants.REFLEC_BEAT_COMBO_TYPE_ALMOST_COMBO
COMBO_TYPE_FULL_COMBO: Final[int] = DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO COMBO_TYPE_FULL_COMBO: Final[int] = DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO
COMBO_TYPE_FULL_COMBO_ALL_JUST: Final[ COMBO_TYPE_FULL_COMBO_ALL_JUST: Final[int] = DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO_ALL_JUST
int
] = DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO_ALL_JUST
# Return the local2 and lobby2 service so that matching will work on newer # Return the local2 and lobby2 service so that matching will work on newer
# Reflec Beat games. # Reflec Beat games.
@ -64,9 +56,7 @@ class ReflecBeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
return Node.void("pc") return Node.void("pc")
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
""" """
Base handler for profile parsing. Given a request and an old profile, Base handler for profile parsing. Given a request and an old profile,
return a new profile that's been updated with the contents of the request. return a new profile that's been updated with the contents of the request.
@ -94,9 +84,7 @@ class ReflecBeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
return None return None
return self.format_profile(userid, profile) return self.format_profile(userid, profile)
def put_profile_by_refid( def put_profile_by_refid(self, refid: Optional[str], request: Node) -> Optional[Profile]:
self, refid: Optional[str], request: Node
) -> Optional[Profile]:
""" """
Given a RefID and a request node, unformat the profile and save it. Given a RefID and a request node, unformat the profile and save it.
""" """
@ -192,17 +180,13 @@ class ReflecBeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# Replace clear type with highest value and timestamps # Replace clear type with highest value and timestamps
if clear_type >= scoredata.get_int("clear_type"): if clear_type >= scoredata.get_int("clear_type"):
scoredata.replace_int( scoredata.replace_int("clear_type", max(scoredata.get_int("clear_type"), clear_type))
"clear_type", max(scoredata.get_int("clear_type"), clear_type)
)
scoredata.replace_int("best_clear_type_time", now) scoredata.replace_int("best_clear_type_time", now)
history.replace_int("clear_type", clear_type) history.replace_int("clear_type", clear_type)
# Replace combo type with highest value and timestamps # Replace combo type with highest value and timestamps
if combo_type >= scoredata.get_int("combo_type"): if combo_type >= scoredata.get_int("combo_type"):
scoredata.replace_int( scoredata.replace_int("combo_type", max(scoredata.get_int("combo_type"), combo_type))
"combo_type", max(scoredata.get_int("combo_type"), combo_type)
)
scoredata.replace_int("best_clear_type_time", now) scoredata.replace_int("best_clear_type_time", now)
history.replace_int("combo_type", combo_type) history.replace_int("combo_type", combo_type)
@ -238,10 +222,7 @@ class ReflecBeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# Update the miss count with timestamps, either if it was lowered, or if the old value was blank. # Update the miss count with timestamps, either if it was lowered, or if the old value was blank.
# If the new value is -1 (we didn't get a miss count this time), never update the old value. # If the new value is -1 (we didn't get a miss count this time), never update the old value.
if miss_count >= 0: if miss_count >= 0:
if ( if miss_count <= scoredata.get_int("miss_count", 999999) or scoredata.get_int("miss_count") == -1:
miss_count <= scoredata.get_int("miss_count", 999999)
or scoredata.get_int("miss_count") == -1
):
scoredata.replace_int( scoredata.replace_int(
"miss_count", "miss_count",
min(scoredata.get_int("miss_count", 999999), miss_count), min(scoredata.get_int("miss_count", 999999), miss_count),

View File

@ -157,9 +157,7 @@ class ReflecBeatColette(ReflecBeatBase):
ranking = Node.void("ranking") ranking = Node.void("ranking")
root.add_child(ranking) root.add_child(ranking)
def add_hitchart( def add_hitchart(name: str, start: int, end: int, hitchart: List[Tuple[int, int]]) -> None:
name: str, start: int, end: int, hitchart: List[Tuple[int, int]]
) -> None:
base = Node.void(name) base = Node.void(name)
ranking.add_child(base) ranking.add_child(base)
base.add_child(Node.s32("bt", start)) base.add_child(Node.s32("bt", start))
@ -207,18 +205,12 @@ class ReflecBeatColette(ReflecBeatBase):
comments = [ comments = [
achievement achievement
for achievement in self.data.local.user.get_all_time_based_achievements( for achievement in self.data.local.user.get_all_time_based_achievements(self.game, self.version)
self.game, self.version
)
if achievement[1].type == "puzzle_comment" if achievement[1].type == "puzzle_comment"
] ]
comments.sort(key=lambda x: x[1].timestamp, reverse=True) comments.sort(key=lambda x: x[1].timestamp, reverse=True)
favorites = [comment for comment in comments if comment[0] == userid] favorites = [comment for comment in comments if comment[0] == userid]
teamcomments = [ teamcomments = [comment for comment in comments if comment[1].data.get_int("teamid") == teamid]
comment
for comment in comments
if comment[1].data.get_int("teamid") == teamid
]
# Cap all comment blocks to the limit # Cap all comment blocks to the limit
if limit >= 0: if limit >= 0:
@ -232,9 +224,7 @@ class ReflecBeatColette(ReflecBeatBase):
comment.add_child(Node.s32("time", Time.now())) comment.add_child(Node.s32("time", Time.now()))
# Mapping of profiles to userIDs # Mapping of profiles to userIDs
uid_mapping = { uid_mapping = {uid: prof for (uid, prof) in self.get_any_profiles([c[0] for c in comments])}
uid: prof for (uid, prof) in self.get_any_profiles([c[0] for c in comments])
}
# Handle anonymous comments by returning a default profile # Handle anonymous comments by returning a default profile
uid_mapping[UserID(0)] = Profile( uid_mapping[UserID(0)] = Profile(
@ -622,9 +612,7 @@ class ReflecBeatColette(ReflecBeatBase):
) )
if lobby is not None: if lobby is not None:
self.data.local.lobby.destroy_lobby(lobby.get_int("id")) self.data.local.lobby.destroy_lobby(lobby.get_int("id"))
self.data.local.lobby.destroy_play_session_info( self.data.local.lobby.destroy_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
return Node.void("player") return Node.void("player")
@ -637,9 +625,7 @@ class ReflecBeatColette(ReflecBeatBase):
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(
previous_version.game, previous_version.version, userid previous_version.game, previous_version.version, userid
) )
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(previous_version.game, previous_version.version, userid)
previous_version.game, previous_version.version, userid
)
else: else:
profile = None profile = None
@ -715,9 +701,7 @@ class ReflecBeatColette(ReflecBeatBase):
def format_profile(self, userid: UserID, profile: Profile) -> Node: def format_profile(self, userid: UserID, profile: Profile) -> Node:
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
scores = self.data.remote.music.get_scores(self.game, self.version, userid) scores = self.data.remote.music.get_scores(self.game, self.version, userid)
links = self.data.local.user.get_links(self.game, self.version, userid) links = self.data.local.user.get_links(self.game, self.version, userid)
root = Node.void("player") root = Node.void("player")
@ -749,9 +733,7 @@ class ReflecBeatColette(ReflecBeatBase):
base.add_child(Node.string("tname", profile.get_str("team_name", ""))) base.add_child(Node.string("tname", profile.get_str("team_name", "")))
base.add_child(Node.string("cmnt", "")) base.add_child(Node.string("cmnt", ""))
base.add_child(Node.s32("uattr", profile.get_int("uattr"))) base.add_child(Node.s32("uattr", profile.get_int("uattr")))
base.add_child( base.add_child(Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 50)))
Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 50))
)
base.add_child(Node.s32("tbs", -1)) base.add_child(Node.s32("tbs", -1))
base.add_child(Node.s32("tbs_r", -1)) base.add_child(Node.s32("tbs_r", -1))
@ -793,73 +775,41 @@ class ReflecBeatColette(ReflecBeatBase):
custom.add_child(Node.u8("st_jdg_disp", customdict.get_int("st_jdg_disp"))) custom.add_child(Node.u8("st_jdg_disp", customdict.get_int("st_jdg_disp")))
custom.add_child(Node.u8("st_tm_disp", customdict.get_int("st_tm_disp"))) custom.add_child(Node.u8("st_tm_disp", customdict.get_int("st_tm_disp")))
custom.add_child(Node.u8("st_rnd", customdict.get_int("st_rnd"))) custom.add_child(Node.u8("st_rnd", customdict.get_int("st_rnd")))
custom.add_child( custom.add_child(Node.s16_array("schat_0", customdict.get_int_array("schat_0", 9)))
Node.s16_array("schat_0", customdict.get_int_array("schat_0", 9)) custom.add_child(Node.s16_array("schat_1", customdict.get_int_array("schat_1", 9)))
) custom.add_child(Node.s16_array("ichat_0", customdict.get_int_array("ichat_0", 6)))
custom.add_child( custom.add_child(Node.s16_array("ichat_1", customdict.get_int_array("ichat_1", 6)))
Node.s16_array("schat_1", customdict.get_int_array("schat_1", 9))
)
custom.add_child(
Node.s16_array("ichat_0", customdict.get_int_array("ichat_0", 6))
)
custom.add_child(
Node.s16_array("ichat_1", customdict.get_int_array("ichat_1", 6))
)
# Player external config # Player external config
config = Node.void("config") config = Node.void("config")
configdict = profile.get_dict("config") configdict = profile.get_dict("config")
pdata.add_child(config) pdata.add_child(config)
config.add_child(Node.u8("msel_bgm", configdict.get_int("msel_bgm"))) config.add_child(Node.u8("msel_bgm", configdict.get_int("msel_bgm")))
config.add_child( config.add_child(Node.u8("narrowdown_type", configdict.get_int("narrowdown_type")))
Node.u8("narrowdown_type", configdict.get_int("narrowdown_type"))
)
config.add_child(Node.s16("icon_id", configdict.get_int("icon_id"))) config.add_child(Node.s16("icon_id", configdict.get_int("icon_id")))
config.add_child(Node.s16("byword_0", configdict.get_int("byword_0"))) config.add_child(Node.s16("byword_0", configdict.get_int("byword_0")))
config.add_child(Node.s16("byword_1", configdict.get_int("byword_1"))) config.add_child(Node.s16("byword_1", configdict.get_int("byword_1")))
config.add_child( config.add_child(Node.bool("is_auto_byword_0", configdict.get_bool("is_auto_byword_0")))
Node.bool("is_auto_byword_0", configdict.get_bool("is_auto_byword_0")) config.add_child(Node.bool("is_auto_byword_1", configdict.get_bool("is_auto_byword_1")))
)
config.add_child(
Node.bool("is_auto_byword_1", configdict.get_bool("is_auto_byword_1"))
)
config.add_child(Node.u8("mrec_type", configdict.get_int("mrec_type"))) config.add_child(Node.u8("mrec_type", configdict.get_int("mrec_type")))
config.add_child(Node.u8("tab_sel", configdict.get_int("tab_sel"))) config.add_child(Node.u8("tab_sel", configdict.get_int("tab_sel")))
config.add_child(Node.u8("card_disp", configdict.get_int("card_disp"))) config.add_child(Node.u8("card_disp", configdict.get_int("card_disp")))
config.add_child( config.add_child(Node.u8("score_tab_disp", configdict.get_int("score_tab_disp")))
Node.u8("score_tab_disp", configdict.get_int("score_tab_disp")) config.add_child(Node.s16("last_music_id", configdict.get_int("last_music_id", -1)))
) config.add_child(Node.u8("last_note_grade", configdict.get_int("last_note_grade")))
config.add_child(
Node.s16("last_music_id", configdict.get_int("last_music_id", -1))
)
config.add_child(
Node.u8("last_note_grade", configdict.get_int("last_note_grade"))
)
config.add_child(Node.u8("sort_type", configdict.get_int("sort_type"))) config.add_child(Node.u8("sort_type", configdict.get_int("sort_type")))
config.add_child( config.add_child(Node.u8("rival_panel_type", configdict.get_int("rival_panel_type")))
Node.u8("rival_panel_type", configdict.get_int("rival_panel_type")) config.add_child(Node.u64("random_entry_work", configdict.get_int("random_entry_work")))
) config.add_child(Node.u8("folder_lamp_type", configdict.get_int("folder_lamp_type")))
config.add_child(
Node.u64("random_entry_work", configdict.get_int("random_entry_work"))
)
config.add_child(
Node.u8("folder_lamp_type", configdict.get_int("folder_lamp_type"))
)
config.add_child(Node.bool("is_tweet", configdict.get_bool("is_tweet"))) config.add_child(Node.bool("is_tweet", configdict.get_bool("is_tweet")))
config.add_child( config.add_child(Node.bool("is_link_twitter", configdict.get_bool("is_link_twitter")))
Node.bool("is_link_twitter", configdict.get_bool("is_link_twitter"))
)
# Stamps # Stamps
stamp = Node.void("stamp") stamp = Node.void("stamp")
stampdict = profile.get_dict("stamp") stampdict = profile.get_dict("stamp")
pdata.add_child(stamp) pdata.add_child(stamp)
stamp.add_child( stamp.add_child(Node.s32_array("stmpcnt", stampdict.get_int_array("stmpcnt", 5)))
Node.s32_array("stmpcnt", stampdict.get_int_array("stmpcnt", 5)) stamp.add_child(Node.s32_array("tcktcnt", stampdict.get_int_array("tcktcnt", 5)))
)
stamp.add_child(
Node.s32_array("tcktcnt", stampdict.get_int_array("tcktcnt", 5))
)
stamp.add_child(Node.s64("area", stampdict.get_int("area"))) stamp.add_child(Node.s64("area", stampdict.get_int("area")))
stamp.add_child(Node.s64("prfvst", stampdict.get_int("prfvst"))) stamp.add_child(Node.s64("prfvst", stampdict.get_int("prfvst")))
stamp.add_child(Node.s32("reserve", stampdict.get_int("reserve"))) stamp.add_child(Node.s32("reserve", stampdict.get_int("reserve")))
@ -993,73 +943,47 @@ class ReflecBeatColette(ReflecBeatBase):
rec.add_child(Node.s16("cmb", score.data.get_int("combo"))) rec.add_child(Node.s16("cmb", score.data.get_int("combo")))
rec.add_child(Node.s16("ms", score.data.get_int("miss_count"))) rec.add_child(Node.s16("ms", score.data.get_int("miss_count")))
rec.add_child(Node.s32("bscrt", score.timestamp)) rec.add_child(Node.s32("bscrt", score.timestamp))
rec.add_child( rec.add_child(Node.s32("bart", score.data.get_int("best_achievement_rate_time")))
Node.s32("bart", score.data.get_int("best_achievement_rate_time"))
)
rec.add_child(Node.s32("bctt", score.data.get_int("best_clear_type_time"))) rec.add_child(Node.s32("bctt", score.data.get_int("best_clear_type_time")))
rec.add_child(Node.s32("bmst", score.data.get_int("best_miss_count_time"))) rec.add_child(Node.s32("bmst", score.data.get_int("best_miss_count_time")))
rec.add_child(Node.s32("time", score.data.get_int("last_played_time"))) rec.add_child(Node.s32("time", score.data.get_int("last_played_time")))
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
game_config = self.get_game_config() game_config = self.get_game_config()
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
newprofile.replace_int( newprofile.replace_int("lid", ID.parse_machine_id(request.child_value("pdata/account/lid")))
"lid", ID.parse_machine_id(request.child_value("pdata/account/lid"))
)
newprofile.replace_str("name", request.child_value("pdata/base/name")) newprofile.replace_str("name", request.child_value("pdata/base/name"))
newprofile.replace_int("exp", request.child_value("pdata/base/exp")) newprofile.replace_int("exp", request.child_value("pdata/base/exp"))
newprofile.replace_int("lvl", request.child_value("pdata/base/lvl")) newprofile.replace_int("lvl", request.child_value("pdata/base/lvl"))
newprofile.replace_int("mg", request.child_value("pdata/base/mg")) newprofile.replace_int("mg", request.child_value("pdata/base/mg"))
newprofile.replace_int("ap", request.child_value("pdata/base/ap")) newprofile.replace_int("ap", request.child_value("pdata/base/ap"))
newprofile.replace_int_array( newprofile.replace_int_array("hidden_param", 50, request.child_value("pdata/base/hidden_param"))
"hidden_param", 50, request.child_value("pdata/base/hidden_param")
)
configdict = newprofile.get_dict("config") configdict = newprofile.get_dict("config")
config = request.child("pdata/config") config = request.child("pdata/config")
if config: if config:
configdict.replace_int("msel_bgm", config.child_value("msel_bgm")) configdict.replace_int("msel_bgm", config.child_value("msel_bgm"))
configdict.replace_int( configdict.replace_int("narrowdown_type", config.child_value("narrowdown_type"))
"narrowdown_type", config.child_value("narrowdown_type")
)
configdict.replace_int("icon_id", config.child_value("icon_id")) configdict.replace_int("icon_id", config.child_value("icon_id"))
configdict.replace_int("byword_0", config.child_value("byword_0")) configdict.replace_int("byword_0", config.child_value("byword_0"))
configdict.replace_int("byword_1", config.child_value("byword_1")) configdict.replace_int("byword_1", config.child_value("byword_1"))
configdict.replace_bool( configdict.replace_bool("is_auto_byword_0", config.child_value("is_auto_byword_0"))
"is_auto_byword_0", config.child_value("is_auto_byword_0") configdict.replace_bool("is_auto_byword_1", config.child_value("is_auto_byword_1"))
)
configdict.replace_bool(
"is_auto_byword_1", config.child_value("is_auto_byword_1")
)
configdict.replace_int("mrec_type", config.child_value("mrec_type")) configdict.replace_int("mrec_type", config.child_value("mrec_type"))
configdict.replace_int("tab_sel", config.child_value("tab_sel")) configdict.replace_int("tab_sel", config.child_value("tab_sel"))
configdict.replace_int("card_disp", config.child_value("card_disp")) configdict.replace_int("card_disp", config.child_value("card_disp"))
configdict.replace_int( configdict.replace_int("score_tab_disp", config.child_value("score_tab_disp"))
"score_tab_disp", config.child_value("score_tab_disp")
)
configdict.replace_int("last_music_id", config.child_value("last_music_id")) configdict.replace_int("last_music_id", config.child_value("last_music_id"))
configdict.replace_int( configdict.replace_int("last_note_grade", config.child_value("last_note_grade"))
"last_note_grade", config.child_value("last_note_grade")
)
configdict.replace_int("sort_type", config.child_value("sort_type")) configdict.replace_int("sort_type", config.child_value("sort_type"))
configdict.replace_int( configdict.replace_int("rival_panel_type", config.child_value("rival_panel_type"))
"rival_panel_type", config.child_value("rival_panel_type") configdict.replace_int("random_entry_work", config.child_value("random_entry_work"))
) configdict.replace_int("folder_lamp_type", config.child_value("folder_lamp_type"))
configdict.replace_int(
"random_entry_work", config.child_value("random_entry_work")
)
configdict.replace_int(
"folder_lamp_type", config.child_value("folder_lamp_type")
)
configdict.replace_bool("is_tweet", config.child_value("is_tweet")) configdict.replace_bool("is_tweet", config.child_value("is_tweet"))
configdict.replace_bool( configdict.replace_bool("is_link_twitter", config.child_value("is_link_twitter"))
"is_link_twitter", config.child_value("is_link_twitter")
)
newprofile.replace_dict("config", configdict) newprofile.replace_dict("config", configdict)
customdict = newprofile.get_dict("custom") customdict = newprofile.get_dict("custom")

View File

@ -131,9 +131,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
profile = self.get_profile(userid) profile = self.get_profile(userid)
info = self.data.local.lobby.get_play_session_info( info = self.data.local.lobby.get_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
if profile is None or info is None: if profile is None or info is None:
return root return root
@ -214,9 +212,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
continue continue
profile = self.get_profile(user) profile = self.get_profile(user)
info = self.data.local.lobby.get_play_session_info( info = self.data.local.lobby.get_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
if profile is None or info is None: if profile is None or info is None:
# No profile info, don't return this lobby # No profile info, don't return this lobby
return root return root
@ -306,16 +302,11 @@ class ReflecBeatGroovin(ReflecBeatBase):
) )
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
lids = [ lids = [machine.id for machine in self.data.local.machine.get_all_machines(machine.arcade)]
machine.id
for machine in self.data.local.machine.get_all_machines(machine.arcade)
]
else: else:
lids = [machine.id] lids = [machine.id]
relevant_profiles = [ relevant_profiles = [profile for profile in all_profiles if profile[1].get_int("lid", -1) in lids]
profile for profile in all_profiles if profile[1].get_int("lid", -1) in lids
]
for rootnode, timeoffset in [ for rootnode, timeoffset in [
(today, 0), (today, 0),
@ -343,10 +334,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
scores_by_user[userid][attempt.id][attempt.chart] = attempt scores_by_user[userid][attempt.id][attempt.chart] = attempt
else: else:
# If this attempt is better than the stored one, replace it # If this attempt is better than the stored one, replace it
if ( if scores_by_user[userid][attempt.id][attempt.chart].points < attempt.points:
scores_by_user[userid][attempt.id][attempt.chart].points
< attempt.points
):
scores_by_user[userid][attempt.id][attempt.chart] = attempt scores_by_user[userid][attempt.id][attempt.chart] = attempt
# Calculate points earned by user in the day # Calculate points earned by user in the day
@ -355,33 +343,20 @@ class ReflecBeatGroovin(ReflecBeatBase):
points_by_user[userid] = 0 points_by_user[userid] = 0
for mid in scores_by_user[userid]: for mid in scores_by_user[userid]:
for chart in scores_by_user[userid][mid]: for chart in scores_by_user[userid][mid]:
points_by_user[userid] = ( points_by_user[userid] = points_by_user[userid] + scores_by_user[userid][mid][chart].points
points_by_user[userid]
+ scores_by_user[userid][mid][chart].points
)
# Output that day's earned points # Output that day's earned points
for userid, profile in relevant_profiles: for userid, profile in relevant_profiles:
data = Node.void("data") data = Node.void("data")
rootnode.add_child(data) rootnode.add_child(data)
data.add_child( data.add_child(Node.s16("day_id", int((Time.now() - timeoffset) / Time.SECONDS_IN_DAY)))
Node.s16(
"day_id", int((Time.now() - timeoffset) / Time.SECONDS_IN_DAY)
)
)
data.add_child(Node.s32("user_id", profile.extid)) data.add_child(Node.s32("user_id", profile.extid))
data.add_child( data.add_child(Node.s16("icon_id", profile.get_dict("config").get_int("icon_id")))
Node.s16("icon_id", profile.get_dict("config").get_int("icon_id")) data.add_child(Node.s16("point", min(points_by_user.get(userid, 0), 32767)))
)
data.add_child(
Node.s16("point", min(points_by_user.get(userid, 0), 32767))
)
data.add_child(Node.s32("update_time", Time.now())) data.add_child(Node.s32("update_time", Time.now()))
data.add_child(Node.string("name", profile.get_str("name"))) data.add_child(Node.string("name", profile.get_str("name")))
rootnode.add_child( rootnode.add_child(Node.s32("timestamp", Time.beginning_of_today() - timeoffset))
Node.s32("timestamp", Time.beginning_of_today() - timeoffset)
)
def handle_info_rb4common_request(self, request: Node) -> Node: def handle_info_rb4common_request(self, request: Node) -> Node:
root = Node.void("info") root = Node.void("info")
@ -398,9 +373,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
ranking = Node.void("ranking") ranking = Node.void("ranking")
root.add_child(ranking) root.add_child(ranking)
def add_hitchart( def add_hitchart(name: str, start: int, end: int, hitchart: List[Tuple[int, int]]) -> None:
name: str, start: int, end: int, hitchart: List[Tuple[int, int]]
) -> None:
base = Node.void(name) base = Node.void(name)
ranking.add_child(base) ranking.add_child(base)
base.add_child(Node.s32("bt", start)) base.add_child(Node.s32("bt", start))
@ -483,17 +456,11 @@ class ReflecBeatGroovin(ReflecBeatBase):
data.add_child( data.add_child(
Node.s8( Node.s8(
"clear_type", "clear_type",
self.__db_to_game_clear_type( self.__db_to_game_clear_type(score.data.get_int("clear_type")),
score.data.get_int("clear_type")
),
) )
) )
data.add_child(Node.s32("user_id", profile.extid)) data.add_child(Node.s32("user_id", profile.extid))
data.add_child( data.add_child(Node.s16("icon_id", profile.get_dict("config").get_int("icon_id")))
Node.s16(
"icon_id", profile.get_dict("config").get_int("icon_id")
)
)
data.add_child(Node.s32("score", score.points)) data.add_child(Node.s32("score", score.points))
data.add_child(Node.s32("time", score.timestamp)) data.add_child(Node.s32("time", score.timestamp))
data.add_child(Node.string("name", profile.get_str("name"))) data.add_child(Node.string("name", profile.get_str("name")))
@ -508,16 +475,12 @@ class ReflecBeatGroovin(ReflecBeatBase):
comments = [ comments = [
achievement achievement
for achievement in self.data.local.user.get_all_time_based_achievements( for achievement in self.data.local.user.get_all_time_based_achievements(self.game, self.version)
self.game, self.version
)
if achievement[1].type == "puzzle_comment" if achievement[1].type == "puzzle_comment"
] ]
comments.sort(key=lambda x: x[1].timestamp, reverse=True) comments.sort(key=lambda x: x[1].timestamp, reverse=True)
favorites = [comment for comment in comments if comment[0] == userid] favorites = [comment for comment in comments if comment[0] == userid]
locationcomments = [ locationcomments = [comment for comment in comments if comment[1].data.get_int("locid") == locid]
comment for comment in comments if comment[1].data.get_int("locid") == locid
]
# Cap all comment blocks to the limit # Cap all comment blocks to the limit
if limit >= 0: if limit >= 0:
@ -531,9 +494,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
comment.add_child(Node.s32("time", Time.now())) comment.add_child(Node.s32("time", Time.now()))
# Mapping of profiles to userIDs # Mapping of profiles to userIDs
uid_mapping = { uid_mapping = {uid: prof for (uid, prof) in self.get_any_profiles([c[0] for c in comments])}
uid: prof for (uid, prof) in self.get_any_profiles([c[0] for c in comments])
}
# Handle anonymous comments by returning a default profile # Handle anonymous comments by returning a default profile
uid_mapping[UserID(0)] = Profile( uid_mapping[UserID(0)] = Profile(
@ -552,9 +513,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
cmnt.add_child(Node.string("name", uid_mapping[uid].get_str("name"))) cmnt.add_child(Node.string("name", uid_mapping[uid].get_str("name")))
cmnt.add_child(Node.s16("icon", ach.data.get_int("icon"))) cmnt.add_child(Node.s16("icon", ach.data.get_int("icon")))
cmnt.add_child(Node.s8("bln", ach.data.get_int("bln"))) cmnt.add_child(Node.s8("bln", ach.data.get_int("bln")))
cmnt.add_child( cmnt.add_child(Node.string("lid", ID.format_machine_id(ach.data.get_int("locid"))))
Node.string("lid", ID.format_machine_id(ach.data.get_int("locid")))
)
cmnt.add_child(Node.s8("pref", ach.data.get_int("prefecture"))) cmnt.add_child(Node.s8("pref", ach.data.get_int("prefecture")))
cmnt.add_child(Node.s32("time", ach.timestamp)) cmnt.add_child(Node.s32("time", ach.timestamp))
cmnt.add_child(Node.string("comment", ach.data.get_str("comment"))) cmnt.add_child(Node.string("comment", ach.data.get_str("comment")))
@ -654,9 +613,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
) )
if lobby is not None: if lobby is not None:
self.data.local.lobby.destroy_lobby(lobby.get_int("id")) self.data.local.lobby.destroy_lobby(lobby.get_int("id"))
self.data.local.lobby.destroy_play_session_info( self.data.local.lobby.destroy_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
return Node.void("player") return Node.void("player")
@ -664,9 +621,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
extid = request.child_value("user_id") extid = request.child_value("user_id")
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
else: else:
achievements = [] achievements = []
@ -714,25 +669,18 @@ class ReflecBeatGroovin(ReflecBeatBase):
rec.add_child(Node.s16("mid", score.id)) rec.add_child(Node.s16("mid", score.id))
rec.add_child(Node.s8("ntgrd", score.chart)) rec.add_child(Node.s8("ntgrd", score.chart))
rec.add_child(Node.s32("pc", score.plays)) rec.add_child(Node.s32("pc", score.plays))
rec.add_child( rec.add_child(Node.s8("ct", self.__db_to_game_clear_type(score.data.get_int("clear_type"))))
Node.s8(
"ct", self.__db_to_game_clear_type(score.data.get_int("clear_type"))
)
)
rec.add_child(Node.s16("ar", score.data.get_int("achievement_rate"))) rec.add_child(Node.s16("ar", score.data.get_int("achievement_rate")))
rec.add_child(Node.s16("scr", score.points)) rec.add_child(Node.s16("scr", score.points))
rec.add_child(Node.s16("ms", score.data.get_int("miss_count"))) rec.add_child(Node.s16("ms", score.data.get_int("miss_count")))
rec.add_child( rec.add_child(
Node.s16( Node.s16(
"param", "param",
self.__db_to_game_combo_type(score.data.get_int("combo_type")) self.__db_to_game_combo_type(score.data.get_int("combo_type")) + score.data.get_int("param"),
+ score.data.get_int("param"),
) )
) )
rec.add_child(Node.s32("bscrt", score.timestamp)) rec.add_child(Node.s32("bscrt", score.timestamp))
rec.add_child( rec.add_child(Node.s32("bart", score.data.get_int("best_achievement_rate_time")))
Node.s32("bart", score.data.get_int("best_achievement_rate_time"))
)
rec.add_child(Node.s32("bctt", score.data.get_int("best_clear_type_time"))) rec.add_child(Node.s32("bctt", score.data.get_int("best_clear_type_time")))
rec.add_child(Node.s32("bmst", score.data.get_int("best_miss_count_time"))) rec.add_child(Node.s32("bmst", score.data.get_int("best_miss_count_time")))
rec.add_child(Node.s32("time", score.data.get_int("last_played_time"))) rec.add_child(Node.s32("time", score.data.get_int("last_played_time")))
@ -748,9 +696,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
score = None score = None
profile = None profile = None
else: else:
score = self.data.remote.music.get_score( score = self.data.remote.music.get_score(self.game, self.version, userid, songid, chart)
self.game, self.version, userid, songid, chart
)
profile = self.get_any_profile(userid) profile = self.get_any_profile(userid)
root = Node.void("player") root = Node.void("player")
@ -762,9 +708,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
player_select_score.add_child(Node.string("name", profile.get_str("name"))) player_select_score.add_child(Node.string("name", profile.get_str("name")))
player_select_score.add_child(Node.s32("m_score", score.points)) player_select_score.add_child(Node.s32("m_score", score.points))
player_select_score.add_child(Node.s32("m_scoreTime", score.timestamp)) player_select_score.add_child(Node.s32("m_scoreTime", score.timestamp))
player_select_score.add_child( player_select_score.add_child(Node.s16("m_iconID", profile.get_dict("config").get_int("icon_id")))
Node.s16("m_iconID", profile.get_dict("config").get_int("icon_id"))
)
return root return root
def handle_player_rbsvLinkageSave_request(self, request: Node) -> Node: def handle_player_rbsvLinkageSave_request(self, request: Node) -> Node:
@ -800,11 +744,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
all_songs = self.data.local.music.get_all_songs(self.game, self.version) all_songs = self.data.local.music.get_all_songs(self.game, self.version)
# Figure out what song IDs are new # Figure out what song IDs are new
new_songs = { new_songs = {song.id for song in all_songs if song.data.get_int("folder", 0) == self.version}
song.id
for song in all_songs
if song.data.get_int("folder", 0) == self.version
}
# Now grab all participating users that had scores # Now grab all participating users that had scores
all_users = {userid for (userid, score) in all_scores} all_users = {userid for (userid, score) in all_scores}
@ -815,68 +755,40 @@ class ReflecBeatGroovin(ReflecBeatBase):
userid: [ userid: [
score score
for (uid, score) in all_scores for (uid, score) in all_scores
if uid == userid if uid == userid and score.data.get_int("clear_type") >= self.CLEAR_TYPE_CLEARED
and score.data.get_int("clear_type") >= self.CLEAR_TYPE_CLEARED
] ]
for userid in all_users for userid in all_users
} }
# Now, sum up the scores into the six categories that the game expects. # Now, sum up the scores into the six categories that the game expects.
total_scores = sorted( total_scores = sorted(
[ [sum([score.points for score in scores]) for userid, scores in scores_by_user.items()],
sum([score.points for score in scores])
for userid, scores in scores_by_user.items()
],
reverse=True, reverse=True,
) )
basic_scores = sorted( basic_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_BASIC])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_BASIC
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
medium_scores = sorted( medium_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_MEDIUM])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_MEDIUM
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
hard_scores = sorted( hard_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_HARD])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_HARD
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
special_scores = sorted( special_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_SPECIAL])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_SPECIAL
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
@ -943,9 +855,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(
previous_version.game, previous_version.version, userid previous_version.game, previous_version.version, userid
) )
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(previous_version.game, previous_version.version, userid)
previous_version.game, previous_version.version, userid
)
else: else:
profile = None profile = None
@ -997,15 +907,9 @@ class ReflecBeatGroovin(ReflecBeatBase):
mrec.add_child(Node.s16("ms", score.data.get_int("miss_count"))) mrec.add_child(Node.s16("ms", score.data.get_int("miss_count")))
mrec.add_child(Node.u16("ver", 0)) mrec.add_child(Node.u16("ver", 0))
mrec.add_child(Node.s32("bst", score.timestamp)) mrec.add_child(Node.s32("bst", score.timestamp))
mrec.add_child( mrec.add_child(Node.s32("bat", score.data.get_int("best_achievement_rate_time")))
Node.s32("bat", score.data.get_int("best_achievement_rate_time")) mrec.add_child(Node.s32("bct", score.data.get_int("best_clear_type_time")))
) mrec.add_child(Node.s32("bmt", score.data.get_int("best_miss_count_time")))
mrec.add_child(
Node.s32("bct", score.data.get_int("best_clear_type_time"))
)
mrec.add_child(
Node.s32("bmt", score.data.get_int("best_miss_count_time"))
)
return root return root
@ -1023,9 +927,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
def format_profile(self, userid: UserID, profile: Profile) -> Node: def format_profile(self, userid: UserID, profile: Profile) -> Node:
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
links = self.data.local.user.get_links(self.game, self.version, userid) links = self.data.local.user.get_links(self.game, self.version, userid)
root = Node.void("player") root = Node.void("player")
pdata = Node.void("pdata") pdata = Node.void("pdata")
@ -1086,9 +988,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
rprofile = self.get_profile(link.other_userid) rprofile = self.get_profile(link.other_userid)
if rprofile is None: if rprofile is None:
continue continue
lobbyinfo = self.data.local.lobby.get_play_session_info( lobbyinfo = self.data.local.lobby.get_play_session_info(self.game, self.version, link.other_userid)
self.game, self.version, link.other_userid
)
if lobbyinfo is None: if lobbyinfo is None:
lobbyinfo = ValidatedDict() lobbyinfo = ValidatedDict()
@ -1114,9 +1014,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
stamp = Node.void("stamp") stamp = Node.void("stamp")
stampdict = profile.get_dict("stamp") stampdict = profile.get_dict("stamp")
pdata.add_child(stamp) pdata.add_child(stamp)
stamp.add_child( stamp.add_child(Node.s32_array("stmpcnt", stampdict.get_int_array("stmpcnt", 10)))
Node.s32_array("stmpcnt", stampdict.get_int_array("stmpcnt", 10))
)
stamp.add_child(Node.s64("area", stampdict.get_int("area"))) stamp.add_child(Node.s64("area", stampdict.get_int("area")))
stamp.add_child(Node.s64("prfvst", stampdict.get_int("prfvst"))) stamp.add_child(Node.s64("prfvst", stampdict.get_int("prfvst")))
@ -1125,48 +1023,26 @@ class ReflecBeatGroovin(ReflecBeatBase):
config = Node.void("config") config = Node.void("config")
pdata.add_child(config) pdata.add_child(config)
config.add_child(Node.u8("msel_bgm", configdict.get_int("msel_bgm"))) config.add_child(Node.u8("msel_bgm", configdict.get_int("msel_bgm")))
config.add_child( config.add_child(Node.u8("narrowdown_type", configdict.get_int("narrowdown_type")))
Node.u8("narrowdown_type", configdict.get_int("narrowdown_type"))
)
config.add_child(Node.s16("icon_id", configdict.get_int("icon_id"))) config.add_child(Node.s16("icon_id", configdict.get_int("icon_id")))
config.add_child(Node.s16("byword_0", configdict.get_int("byword_0"))) config.add_child(Node.s16("byword_0", configdict.get_int("byword_0")))
config.add_child(Node.s16("byword_1", configdict.get_int("byword_1"))) config.add_child(Node.s16("byword_1", configdict.get_int("byword_1")))
config.add_child( config.add_child(Node.bool("is_auto_byword_0", configdict.get_bool("is_auto_byword_0")))
Node.bool("is_auto_byword_0", configdict.get_bool("is_auto_byword_0")) config.add_child(Node.bool("is_auto_byword_1", configdict.get_bool("is_auto_byword_1")))
)
config.add_child(
Node.bool("is_auto_byword_1", configdict.get_bool("is_auto_byword_1"))
)
config.add_child(Node.u8("mrec_type", configdict.get_int("mrec_type"))) config.add_child(Node.u8("mrec_type", configdict.get_int("mrec_type")))
config.add_child(Node.u8("tab_sel", configdict.get_int("tab_sel"))) config.add_child(Node.u8("tab_sel", configdict.get_int("tab_sel")))
config.add_child(Node.u8("card_disp", configdict.get_int("card_disp"))) config.add_child(Node.u8("card_disp", configdict.get_int("card_disp")))
config.add_child( config.add_child(Node.u8("score_tab_disp", configdict.get_int("score_tab_disp")))
Node.u8("score_tab_disp", configdict.get_int("score_tab_disp")) config.add_child(Node.s16("last_music_id", configdict.get_int("last_music_id", -1)))
) config.add_child(Node.u8("last_note_grade", configdict.get_int("last_note_grade")))
config.add_child(
Node.s16("last_music_id", configdict.get_int("last_music_id", -1))
)
config.add_child(
Node.u8("last_note_grade", configdict.get_int("last_note_grade"))
)
config.add_child(Node.u8("sort_type", configdict.get_int("sort_type"))) config.add_child(Node.u8("sort_type", configdict.get_int("sort_type")))
config.add_child( config.add_child(Node.u8("rival_panel_type", configdict.get_int("rival_panel_type")))
Node.u8("rival_panel_type", configdict.get_int("rival_panel_type")) config.add_child(Node.u64("random_entry_work", configdict.get_int("random_entry_work")))
) config.add_child(Node.u64("custom_folder_work", configdict.get_int("custom_folder_work")))
config.add_child(
Node.u64("random_entry_work", configdict.get_int("random_entry_work"))
)
config.add_child(
Node.u64("custom_folder_work", configdict.get_int("custom_folder_work"))
)
config.add_child(Node.u8("folder_type", configdict.get_int("folder_type"))) config.add_child(Node.u8("folder_type", configdict.get_int("folder_type")))
config.add_child( config.add_child(Node.u8("folder_lamp_type", configdict.get_int("folder_lamp_type")))
Node.u8("folder_lamp_type", configdict.get_int("folder_lamp_type"))
)
config.add_child(Node.bool("is_tweet", configdict.get_bool("is_tweet"))) config.add_child(Node.bool("is_tweet", configdict.get_bool("is_tweet")))
config.add_child( config.add_child(Node.bool("is_link_twitter", configdict.get_bool("is_link_twitter")))
Node.bool("is_link_twitter", configdict.get_bool("is_link_twitter"))
)
# Customizations # Customizations
customdict = profile.get_dict("custom") customdict = profile.get_dict("custom")
@ -1186,16 +1062,10 @@ class ReflecBeatGroovin(ReflecBeatBase):
custom.add_child(Node.u8("st_rnd", customdict.get_int("st_rnd"))) custom.add_child(Node.u8("st_rnd", customdict.get_int("st_rnd")))
custom.add_child(Node.u8("st_hazard", customdict.get_int("st_hazard"))) custom.add_child(Node.u8("st_hazard", customdict.get_int("st_hazard")))
custom.add_child(Node.u8("st_clr_cond", customdict.get_int("st_clr_cond"))) custom.add_child(Node.u8("st_clr_cond", customdict.get_int("st_clr_cond")))
custom.add_child( custom.add_child(Node.s16_array("schat_0", customdict.get_int_array("schat_0", 10)))
Node.s16_array("schat_0", customdict.get_int_array("schat_0", 10)) custom.add_child(Node.s16_array("schat_1", customdict.get_int_array("schat_1", 10)))
)
custom.add_child(
Node.s16_array("schat_1", customdict.get_int_array("schat_1", 10))
)
custom.add_child(Node.u8("cheer_voice", customdict.get_int("cheer_voice"))) custom.add_child(Node.u8("cheer_voice", customdict.get_int("cheer_voice")))
custom.add_child( custom.add_child(Node.u8("same_time_note_disp", customdict.get_int("same_time_note_disp")))
Node.u8("same_time_note_disp", customdict.get_int("same_time_note_disp"))
)
# Unlocks # Unlocks
released = Node.void("released") released = Node.void("released")
@ -1249,9 +1119,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
info.add_child(Node.u8("type", announcementtype)) info.add_child(Node.u8("type", announcementtype))
info.add_child(Node.u16("id", announcement.id)) info.add_child(Node.u16("id", announcement.id))
info.add_child(Node.u16("param", announcement.data.get_int("param"))) info.add_child(Node.u16("param", announcement.data.get_int("param")))
info.add_child( info.add_child(Node.bool("bneedannounce", announcement.data.get_bool("need")))
Node.bool("bneedannounce", announcement.data.get_bool("need"))
)
# Dojo ranking return # Dojo ranking return
dojo = Node.void("dojo") dojo = Node.void("dojo")
@ -1268,12 +1136,8 @@ class ReflecBeatGroovin(ReflecBeatBase):
rec.add_child(Node.s32("total_ar", entry.data.get_int("ar"))) rec.add_child(Node.s32("total_ar", entry.data.get_int("ar")))
rec.add_child(Node.s32("total_score", entry.data.get_int("score"))) rec.add_child(Node.s32("total_score", entry.data.get_int("score")))
rec.add_child(Node.s32("play_count", entry.data.get_int("plays"))) rec.add_child(Node.s32("play_count", entry.data.get_int("plays")))
rec.add_child( rec.add_child(Node.s32("last_play_time", entry.data.get_int("play_timestamp")))
Node.s32("last_play_time", entry.data.get_int("play_timestamp")) rec.add_child(Node.s32("record_update_time", entry.data.get_int("record_timestamp")))
)
rec.add_child(
Node.s32("record_update_time", entry.data.get_int("record_timestamp"))
)
rec.add_child(Node.s32("rank", 0)) rec.add_child(Node.s32("rank", 0))
# Player Parameters # Player Parameters
@ -1289,9 +1153,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
player_param.add_child(itemnode) player_param.add_child(itemnode)
itemnode.add_child(Node.s32("type", itemtype)) itemnode.add_child(Node.s32("type", itemtype))
itemnode.add_child(Node.s32("bank", param.id)) itemnode.add_child(Node.s32("bank", param.id))
itemnode.add_child( itemnode.add_child(Node.s32_array("data", param.data.get_int_array("data", 256)))
Node.s32_array("data", param.data.get_int_array("data", 256))
)
# Shop score for players # Shop score for players
self.__add_shop_score(pdata) self.__add_shop_score(pdata)
@ -1349,16 +1211,12 @@ class ReflecBeatGroovin(ReflecBeatBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
game_config = self.get_game_config() game_config = self.get_game_config()
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Save base player profile info # Save base player profile info
newprofile.replace_int( newprofile.replace_int("lid", ID.parse_machine_id(request.child_value("pdata/account/lid")))
"lid", ID.parse_machine_id(request.child_value("pdata/account/lid"))
)
newprofile.replace_str("name", request.child_value("pdata/base/name")) newprofile.replace_str("name", request.child_value("pdata/base/name"))
newprofile.replace_int("exp", request.child_value("pdata/base/exp")) newprofile.replace_int("exp", request.child_value("pdata/base/exp"))
newprofile.replace_int("lvl", request.child_value("pdata/base/lvl")) newprofile.replace_int("lvl", request.child_value("pdata/base/lvl"))
@ -1442,46 +1300,26 @@ class ReflecBeatGroovin(ReflecBeatBase):
config = request.child("pdata/config") config = request.child("pdata/config")
if config: if config:
configdict.replace_int("msel_bgm", config.child_value("msel_bgm")) configdict.replace_int("msel_bgm", config.child_value("msel_bgm"))
configdict.replace_int( configdict.replace_int("narrowdown_type", config.child_value("narrowdown_type"))
"narrowdown_type", config.child_value("narrowdown_type")
)
configdict.replace_int("icon_id", config.child_value("icon_id")) configdict.replace_int("icon_id", config.child_value("icon_id"))
configdict.replace_int("byword_0", config.child_value("byword_0")) configdict.replace_int("byword_0", config.child_value("byword_0"))
configdict.replace_int("byword_1", config.child_value("byword_1")) configdict.replace_int("byword_1", config.child_value("byword_1"))
configdict.replace_bool( configdict.replace_bool("is_auto_byword_0", config.child_value("is_auto_byword_0"))
"is_auto_byword_0", config.child_value("is_auto_byword_0") configdict.replace_bool("is_auto_byword_1", config.child_value("is_auto_byword_1"))
)
configdict.replace_bool(
"is_auto_byword_1", config.child_value("is_auto_byword_1")
)
configdict.replace_int("mrec_type", config.child_value("mrec_type")) configdict.replace_int("mrec_type", config.child_value("mrec_type"))
configdict.replace_int("tab_sel", config.child_value("tab_sel")) configdict.replace_int("tab_sel", config.child_value("tab_sel"))
configdict.replace_int("card_disp", config.child_value("card_disp")) configdict.replace_int("card_disp", config.child_value("card_disp"))
configdict.replace_int( configdict.replace_int("score_tab_disp", config.child_value("score_tab_disp"))
"score_tab_disp", config.child_value("score_tab_disp")
)
configdict.replace_int("last_music_id", config.child_value("last_music_id")) configdict.replace_int("last_music_id", config.child_value("last_music_id"))
configdict.replace_int( configdict.replace_int("last_note_grade", config.child_value("last_note_grade"))
"last_note_grade", config.child_value("last_note_grade")
)
configdict.replace_int("sort_type", config.child_value("sort_type")) configdict.replace_int("sort_type", config.child_value("sort_type"))
configdict.replace_int( configdict.replace_int("rival_panel_type", config.child_value("rival_panel_type"))
"rival_panel_type", config.child_value("rival_panel_type") configdict.replace_int("random_entry_work", config.child_value("random_entry_work"))
) configdict.replace_int("custom_folder_work", config.child_value("custom_folder_work"))
configdict.replace_int(
"random_entry_work", config.child_value("random_entry_work")
)
configdict.replace_int(
"custom_folder_work", config.child_value("custom_folder_work")
)
configdict.replace_int("folder_type", config.child_value("folder_type")) configdict.replace_int("folder_type", config.child_value("folder_type"))
configdict.replace_int( configdict.replace_int("folder_lamp_type", config.child_value("folder_lamp_type"))
"folder_lamp_type", config.child_value("folder_lamp_type")
)
configdict.replace_bool("is_tweet", config.child_value("is_tweet")) configdict.replace_bool("is_tweet", config.child_value("is_tweet"))
configdict.replace_bool( configdict.replace_bool("is_link_twitter", config.child_value("is_link_twitter"))
"is_link_twitter", config.child_value("is_link_twitter")
)
newprofile.replace_dict("config", configdict) newprofile.replace_dict("config", configdict)
# Save player custom settings # Save player custom settings
@ -1505,9 +1343,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
customdict.replace_int_array("schat_0", 10, custom.child_value("schat_0")) customdict.replace_int_array("schat_0", 10, custom.child_value("schat_0"))
customdict.replace_int_array("schat_1", 10, custom.child_value("schat_1")) customdict.replace_int_array("schat_1", 10, custom.child_value("schat_1"))
customdict.replace_int("cheer_voice", custom.child_value("cheer_voice")) customdict.replace_int("cheer_voice", custom.child_value("cheer_voice"))
customdict.replace_int( customdict.replace_int("same_time_note_disp", custom.child_value("same_time_note_disp"))
"same_time_note_disp", custom.child_value("same_time_note_disp")
)
newprofile.replace_dict("custom", customdict) newprofile.replace_dict("custom", customdict)
# Save player parameter info # Save player parameter info
@ -1543,9 +1379,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
# I assume this is copypasta, but I want to be sure # I assume this is copypasta, but I want to be sure
extid = child.child_value("user_id") extid = child.child_value("user_id")
if extid != newprofile.extid: if extid != newprofile.extid:
raise Exception( raise Exception(f"Unexpected user ID, got {extid} expecting {newprofile.extid}")
f"Unexpected user ID, got {extid} expecting {newprofile.extid}"
)
episode_type = child.child_value("type") episode_type = child.child_value("type")
episode_value0 = child.child_value("value0") episode_value0 = child.child_value("value0")
@ -1622,9 +1456,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
continue continue
extid = child.child_value("id") extid = child.child_value("id")
other_userid = self.data.remote.user.from_extid( other_userid = self.data.remote.user.from_extid(self.game, self.version, extid)
self.game, self.version, extid
)
if other_userid is None: if other_userid is None:
continue continue

View File

@ -176,15 +176,11 @@ class ReflecBeatLimelight(ReflecBeatBase):
comments = [ comments = [
achievement achievement
for achievement in self.data.local.user.get_all_time_based_achievements( for achievement in self.data.local.user.get_all_time_based_achievements(self.game, self.version)
self.game, self.version
)
if achievement[1].type == "puzzle_comment" if achievement[1].type == "puzzle_comment"
] ]
comments.sort(key=lambda x: x[1].timestamp, reverse=True) comments.sort(key=lambda x: x[1].timestamp, reverse=True)
statuses = self.data.local.lobby.get_all_play_session_infos( statuses = self.data.local.lobby.get_all_play_session_infos(self.game, self.version)
self.game, self.version
)
statuses.sort(key=lambda x: x[1]["time"], reverse=True) statuses.sort(key=lambda x: x[1]["time"], reverse=True)
# Cap all comment blocks to the limit # Cap all comment blocks to the limit
@ -194,10 +190,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
# Mapping of profiles to userIDs # Mapping of profiles to userIDs
uid_mapping = { uid_mapping = {
uid: prof uid: prof for (uid, prof) in self.get_any_profiles([c[0] for c in comments] + [s[0] for s in statuses])
for (uid, prof) in self.get_any_profiles(
[c[0] for c in comments] + [s[0] for s in statuses]
)
} }
# Mapping of location ID to machine name # Mapping of location ID to machine name
@ -254,9 +247,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
s.add_child(Node.s32("exp", uid_mapping[uid].get_int("exp"))) s.add_child(Node.s32("exp", uid_mapping[uid].get_int("exp")))
s.add_child(Node.s32("customize", status.get_int("customize"))) s.add_child(Node.s32("customize", status.get_int("customize")))
s.add_child(Node.s32("tid", uid_mapping[uid].get_int("team_id", -1))) s.add_child(Node.s32("tid", uid_mapping[uid].get_int("team_id", -1)))
s.add_child( s.add_child(Node.string("t_name", uid_mapping[uid].get_str("team_name", "")))
Node.string("t_name", uid_mapping[uid].get_str("team_name", ""))
)
s.add_child(Node.string("lid", status.get_str("lid"))) s.add_child(Node.string("lid", status.get_str("lid")))
s.add_child(Node.string("s_name", lid_mapping[lid])) s.add_child(Node.string("s_name", lid_mapping[lid]))
s.add_child(Node.s8("pref", status.get_int("prefecture"))) s.add_child(Node.s8("pref", status.get_int("prefecture")))
@ -457,9 +448,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
refid = request.child_value("rid") refid = request.child_value("rid")
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is not None: if userid is not None:
self.data.local.lobby.put_play_session_info( self.data.local.lobby.put_play_session_info(self.game, self.version, userid, {})
self.game, self.version, userid, {}
)
root = Node.void("player") root = Node.void("player")
root.add_child(Node.bool("is_suc", True)) root.add_child(Node.bool("is_suc", True))
@ -525,9 +514,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
) )
if lobby is not None: if lobby is not None:
self.data.local.lobby.destroy_lobby(lobby.get_int("id")) self.data.local.lobby.destroy_lobby(lobby.get_int("id"))
self.data.local.lobby.destroy_play_session_info( self.data.local.lobby.destroy_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
return Node.void("player") return Node.void("player")
@ -559,9 +546,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(
previous_version.game, previous_version.version, userid previous_version.game, previous_version.version, userid
) )
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(previous_version.game, previous_version.version, userid)
previous_version.game, previous_version.version, userid
)
else: else:
profile = None profile = None
@ -598,15 +583,9 @@ class ReflecBeatLimelight(ReflecBeatBase):
mrecord.add_child(mrec) mrecord.add_child(mrec)
mrec.add_child(Node.s32("mid", score.id)) mrec.add_child(Node.s32("mid", score.id))
mrec.add_child(Node.s32("ctype", score.chart)) mrec.add_child(Node.s32("ctype", score.chart))
mrec.add_child( mrec.add_child(Node.s32("win", score.data.get_dict("stats").get_int("win")))
Node.s32("win", score.data.get_dict("stats").get_int("win")) mrec.add_child(Node.s32("lose", score.data.get_dict("stats").get_int("win")))
) mrec.add_child(Node.s32("draw", score.data.get_dict("stats").get_int("win")))
mrec.add_child(
Node.s32("lose", score.data.get_dict("stats").get_int("win"))
)
mrec.add_child(
Node.s32("draw", score.data.get_dict("stats").get_int("win"))
)
mrec.add_child(Node.s32("score", score.points)) mrec.add_child(Node.s32("score", score.points))
mrec.add_child(Node.s32("combo", score.data.get_int("combo"))) mrec.add_child(Node.s32("combo", score.data.get_int("combo")))
mrec.add_child(Node.s32("miss", score.data.get_int("miss_count"))) mrec.add_child(Node.s32("miss", score.data.get_int("miss_count")))
@ -626,9 +605,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
def format_profile(self, userid: UserID, profile: Profile) -> Node: def format_profile(self, userid: UserID, profile: Profile) -> Node:
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
scores = self.data.remote.music.get_scores(self.game, self.version, userid) scores = self.data.remote.music.get_scores(self.game, self.version, userid)
links = self.data.local.user.get_links(self.game, self.version, userid) links = self.data.local.user.get_links(self.game, self.version, userid)
root = Node.void("player") root = Node.void("player")
@ -672,50 +649,24 @@ class ReflecBeatLimelight(ReflecBeatBase):
custom.add_child(Node.u8("se_s", customdict.get_int("se_s"))) custom.add_child(Node.u8("se_s", customdict.get_int("se_s")))
custom.add_child(Node.u8("se_s_v", customdict.get_int("se_s_v"))) custom.add_child(Node.u8("se_s_v", customdict.get_int("se_s_v")))
custom.add_child(Node.s16("last_music_id", customdict.get_int("last_music_id"))) custom.add_child(Node.s16("last_music_id", customdict.get_int("last_music_id")))
custom.add_child( custom.add_child(Node.u8("last_note_grade", customdict.get_int("last_note_grade")))
Node.u8("last_note_grade", customdict.get_int("last_note_grade"))
)
custom.add_child(Node.u8("sort_type", customdict.get_int("sort_type"))) custom.add_child(Node.u8("sort_type", customdict.get_int("sort_type")))
custom.add_child( custom.add_child(Node.u8("narrowdown_type", customdict.get_int("narrowdown_type")))
Node.u8("narrowdown_type", customdict.get_int("narrowdown_type")) custom.add_child(Node.bool("is_begginer", customdict.get_bool("is_begginer"))) # Yes, this is spelled right
)
custom.add_child(
Node.bool("is_begginer", customdict.get_bool("is_begginer"))
) # Yes, this is spelled right
custom.add_child(Node.bool("is_tut", customdict.get_bool("is_tut"))) custom.add_child(Node.bool("is_tut", customdict.get_bool("is_tut")))
custom.add_child( custom.add_child(Node.s16_array("symbol_chat_0", customdict.get_int_array("symbol_chat_0", 6)))
Node.s16_array( custom.add_child(Node.s16_array("symbol_chat_1", customdict.get_int_array("symbol_chat_1", 6)))
"symbol_chat_0", customdict.get_int_array("symbol_chat_0", 6)
)
)
custom.add_child(
Node.s16_array(
"symbol_chat_1", customdict.get_int_array("symbol_chat_1", 6)
)
)
custom.add_child(Node.u8("gauge_style", customdict.get_int("gauge_style"))) custom.add_child(Node.u8("gauge_style", customdict.get_int("gauge_style")))
custom.add_child(Node.u8("obj_shade", customdict.get_int("obj_shade"))) custom.add_child(Node.u8("obj_shade", customdict.get_int("obj_shade")))
custom.add_child(Node.u8("obj_size", customdict.get_int("obj_size"))) custom.add_child(Node.u8("obj_size", customdict.get_int("obj_size")))
custom.add_child( custom.add_child(Node.s16_array("byword", customdict.get_int_array("byword", 2)))
Node.s16_array("byword", customdict.get_int_array("byword", 2)) custom.add_child(Node.bool_array("is_auto_byword", customdict.get_bool_array("is_auto_byword", 2)))
)
custom.add_child(
Node.bool_array(
"is_auto_byword", customdict.get_bool_array("is_auto_byword", 2)
)
)
custom.add_child(Node.bool("is_tweet", customdict.get_bool("is_tweet"))) custom.add_child(Node.bool("is_tweet", customdict.get_bool("is_tweet")))
custom.add_child( custom.add_child(Node.bool("is_link_twitter", customdict.get_bool("is_link_twitter")))
Node.bool("is_link_twitter", customdict.get_bool("is_link_twitter"))
)
custom.add_child(Node.s16("mrec_type", customdict.get_int("mrec_type"))) custom.add_child(Node.s16("mrec_type", customdict.get_int("mrec_type")))
custom.add_child( custom.add_child(Node.s16("card_disp_type", customdict.get_int("card_disp_type")))
Node.s16("card_disp_type", customdict.get_int("card_disp_type"))
)
custom.add_child(Node.s16("tab_sel", customdict.get_int("tab_sel"))) custom.add_child(Node.s16("tab_sel", customdict.get_int("tab_sel")))
custom.add_child( custom.add_child(Node.s32_array("hidden_param", customdict.get_int_array("hidden_param", 20)))
Node.s32_array("hidden_param", customdict.get_int_array("hidden_param", 20))
)
released = Node.void("released") released = Node.void("released")
pdata.add_child(released) pdata.add_child(released)
@ -763,22 +714,14 @@ class ReflecBeatLimelight(ReflecBeatBase):
record.add_child(rec) record.add_child(rec)
rec.add_child(Node.u16("mid", score.id)) rec.add_child(Node.u16("mid", score.id))
rec.add_child(Node.u8("ng", score.chart)) rec.add_child(Node.u8("ng", score.chart))
rec.add_child( rec.add_child(Node.s32("point", score.data.get_dict("stats").get_int("earned_points")))
Node.s32("point", score.data.get_dict("stats").get_int("earned_points"))
)
rec.add_child(Node.s32("played_time", score.timestamp)) rec.add_child(Node.s32("played_time", score.timestamp))
mrec_0 = Node.void("mrec_0") mrec_0 = Node.void("mrec_0")
rec.add_child(mrec_0) rec.add_child(mrec_0)
mrec_0.add_child( mrec_0.add_child(Node.s32("win", score.data.get_dict("stats").get_int("win")))
Node.s32("win", score.data.get_dict("stats").get_int("win")) mrec_0.add_child(Node.s32("lose", score.data.get_dict("stats").get_int("lose")))
) mrec_0.add_child(Node.s32("draw", score.data.get_dict("stats").get_int("draw")))
mrec_0.add_child(
Node.s32("lose", score.data.get_dict("stats").get_int("lose"))
)
mrec_0.add_child(
Node.s32("draw", score.data.get_dict("stats").get_int("draw"))
)
mrec_0.add_child( mrec_0.add_child(
Node.u8( Node.u8(
"ct", "ct",
@ -788,9 +731,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
), ),
) )
) )
mrec_0.add_child( mrec_0.add_child(Node.s16("ar", int(score.data.get_int("achievement_rate") / 10)))
Node.s16("ar", int(score.data.get_int("achievement_rate") / 10))
)
mrec_0.add_child(Node.s32("bs", score.points)) mrec_0.add_child(Node.s32("bs", score.points))
mrec_0.add_child(Node.s16("mc", score.data.get_int("combo"))) mrec_0.add_child(Node.s16("mc", score.data.get_int("combo")))
mrec_0.add_child(Node.s16("bmc", score.data.get_int("miss_count"))) mrec_0.add_child(Node.s16("bmc", score.data.get_int("miss_count")))
@ -888,9 +829,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
game_config = self.get_game_config() game_config = self.get_game_config()
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
@ -916,42 +855,24 @@ class ReflecBeatLimelight(ReflecBeatBase):
customdict.replace_int("se_s", custom.child_value("se_s")) customdict.replace_int("se_s", custom.child_value("se_s"))
customdict.replace_int("se_s_v", custom.child_value("se_s_v")) customdict.replace_int("se_s_v", custom.child_value("se_s_v"))
customdict.replace_int("last_music_id", custom.child_value("last_music_id")) customdict.replace_int("last_music_id", custom.child_value("last_music_id"))
customdict.replace_int( customdict.replace_int("last_note_grade", custom.child_value("last_note_grade"))
"last_note_grade", custom.child_value("last_note_grade")
)
customdict.replace_int("sort_type", custom.child_value("sort_type")) customdict.replace_int("sort_type", custom.child_value("sort_type"))
customdict.replace_int( customdict.replace_int("narrowdown_type", custom.child_value("narrowdown_type"))
"narrowdown_type", custom.child_value("narrowdown_type") customdict.replace_bool("is_begginer", custom.child_value("is_begginer")) # Yes, this is spelled right
)
customdict.replace_bool(
"is_begginer", custom.child_value("is_begginer")
) # Yes, this is spelled right
customdict.replace_bool("is_tut", custom.child_value("is_tut")) customdict.replace_bool("is_tut", custom.child_value("is_tut"))
customdict.replace_int_array( customdict.replace_int_array("symbol_chat_0", 6, custom.child_value("symbol_chat_0"))
"symbol_chat_0", 6, custom.child_value("symbol_chat_0") customdict.replace_int_array("symbol_chat_1", 6, custom.child_value("symbol_chat_1"))
)
customdict.replace_int_array(
"symbol_chat_1", 6, custom.child_value("symbol_chat_1")
)
customdict.replace_int("gauge_style", custom.child_value("gauge_style")) customdict.replace_int("gauge_style", custom.child_value("gauge_style"))
customdict.replace_int("obj_shade", custom.child_value("obj_shade")) customdict.replace_int("obj_shade", custom.child_value("obj_shade"))
customdict.replace_int("obj_size", custom.child_value("obj_size")) customdict.replace_int("obj_size", custom.child_value("obj_size"))
customdict.replace_int_array("byword", 2, custom.child_value("byword")) customdict.replace_int_array("byword", 2, custom.child_value("byword"))
customdict.replace_bool_array( customdict.replace_bool_array("is_auto_byword", 2, custom.child_value("is_auto_byword"))
"is_auto_byword", 2, custom.child_value("is_auto_byword")
)
customdict.replace_bool("is_tweet", custom.child_value("is_tweet")) customdict.replace_bool("is_tweet", custom.child_value("is_tweet"))
customdict.replace_bool( customdict.replace_bool("is_link_twitter", custom.child_value("is_link_twitter"))
"is_link_twitter", custom.child_value("is_link_twitter")
)
customdict.replace_int("mrec_type", custom.child_value("mrec_type")) customdict.replace_int("mrec_type", custom.child_value("mrec_type"))
customdict.replace_int( customdict.replace_int("card_disp_type", custom.child_value("card_disp_type"))
"card_disp_type", custom.child_value("card_disp_type")
)
customdict.replace_int("tab_sel", custom.child_value("tab_sel")) customdict.replace_int("tab_sel", custom.child_value("tab_sel"))
customdict.replace_int_array( customdict.replace_int_array("hidden_param", 20, custom.child_value("hidden_param"))
"hidden_param", 20, custom.child_value("hidden_param")
)
newprofile.replace_dict("custom", customdict) newprofile.replace_dict("custom", customdict)
# Music unlocks and other stuff # Music unlocks and other stuff
@ -1036,10 +957,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
if chart in savedrecords[songid]: if chart in savedrecords[songid]:
data = savedrecords[songid][chart] data = savedrecords[songid][chart]
if ( if data["achievement_rate"] == achievement_rate and data["points"] == points:
data["achievement_rate"] == achievement_rate
and data["points"] == points
):
# This is the same record! Use the stats from it to update our # This is the same record! Use the stats from it to update our
# internal representation. # internal representation.
combo = data["combo"] combo = data["combo"]

View File

@ -61,9 +61,7 @@ class ReflecBeat(ReflecBeatBase):
raise Exception(f"Invalid db_combo_type {db_combo_type}") raise Exception(f"Invalid db_combo_type {db_combo_type}")
raise Exception(f"Invalid db_clear_type {db_clear_type}") raise Exception(f"Invalid db_clear_type {db_clear_type}")
def __game_to_db_clear_type( def __game_to_db_clear_type(self, game_clear_type: int, game_achievement_rate: int) -> Tuple[int, int]:
self, game_clear_type: int, game_achievement_rate: int
) -> Tuple[int, int]:
if game_clear_type == self.GAME_CLEAR_TYPE_NO_PLAY: if game_clear_type == self.GAME_CLEAR_TYPE_NO_PLAY:
return (self.CLEAR_TYPE_NO_PLAY, self.COMBO_TYPE_NONE) return (self.CLEAR_TYPE_NO_PLAY, self.COMBO_TYPE_NONE)
if game_clear_type == self.GAME_CLEAR_TYPE_PLAYED: if game_clear_type == self.GAME_CLEAR_TYPE_PLAYED:
@ -254,9 +252,7 @@ class ReflecBeat(ReflecBeatBase):
refid = request.child_value("rid") refid = request.child_value("rid")
userid = self.data.remote.user.from_refid(self.game, self.version, refid) userid = self.data.remote.user.from_refid(self.game, self.version, refid)
if userid is not None: if userid is not None:
self.data.local.lobby.put_play_session_info( self.data.local.lobby.put_play_session_info(self.game, self.version, userid, {})
self.game, self.version, userid, {}
)
root = Node.void("player") root = Node.void("player")
root.add_child(Node.bool("is_suc", True)) root.add_child(Node.bool("is_suc", True))
@ -282,9 +278,7 @@ class ReflecBeat(ReflecBeatBase):
) )
if lobby is not None: if lobby is not None:
self.data.local.lobby.destroy_lobby(lobby.get_int("id")) self.data.local.lobby.destroy_lobby(lobby.get_int("id"))
self.data.local.lobby.destroy_play_session_info( self.data.local.lobby.destroy_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
return Node.void("player") return Node.void("player")
@ -310,9 +304,7 @@ class ReflecBeat(ReflecBeatBase):
def format_profile(self, userid: UserID, profile: Profile) -> Node: def format_profile(self, userid: UserID, profile: Profile) -> Node:
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
scores = self.data.remote.music.get_scores(self.game, self.version, userid) scores = self.data.remote.music.get_scores(self.game, self.version, userid)
root = Node.void("player") root = Node.void("player")
pdata = Node.void("pdata") pdata = Node.void("pdata")
@ -368,10 +360,7 @@ class ReflecBeat(ReflecBeatBase):
info.add_child(Node.u16("id", item.id)) info.add_child(Node.u16("id", item.id))
if game_config.get_bool("force_unlock_songs"): if game_config.get_bool("force_unlock_songs"):
songs = { songs = {song.id for song in self.data.local.music.get_all_songs(self.game, self.version)}
song.id
for song in self.data.local.music.get_all_songs(self.game, self.version)
}
for songid in songs: for songid in songs:
info = Node.void("info") info = Node.void("info")
@ -389,12 +378,8 @@ class ReflecBeat(ReflecBeatBase):
rec.add_child(Node.u16("mid", score.id)) rec.add_child(Node.u16("mid", score.id))
rec.add_child(Node.u8("ng", score.chart)) rec.add_child(Node.u8("ng", score.chart))
rec.add_child(Node.s32("win", score.data.get_dict("stats").get_int("win"))) rec.add_child(Node.s32("win", score.data.get_dict("stats").get_int("win")))
rec.add_child( rec.add_child(Node.s32("lose", score.data.get_dict("stats").get_int("lose")))
Node.s32("lose", score.data.get_dict("stats").get_int("lose")) rec.add_child(Node.s32("draw", score.data.get_dict("stats").get_int("draw")))
)
rec.add_child(
Node.s32("draw", score.data.get_dict("stats").get_int("draw"))
)
rec.add_child( rec.add_child(
Node.u8( Node.u8(
"ct", "ct",
@ -404,9 +389,7 @@ class ReflecBeat(ReflecBeatBase):
), ),
) )
) )
rec.add_child( rec.add_child(Node.s16("ar", int(score.data.get_int("achievement_rate") / 10)))
Node.s16("ar", int(score.data.get_int("achievement_rate") / 10))
)
rec.add_child(Node.s16("bs", score.points)) rec.add_child(Node.s16("bs", score.points))
rec.add_child(Node.s16("mc", score.data.get_int("combo"))) rec.add_child(Node.s16("mc", score.data.get_int("combo")))
rec.add_child(Node.s16("bmc", score.data.get_int("miss_count"))) rec.add_child(Node.s16("bmc", score.data.get_int("miss_count")))
@ -421,9 +404,7 @@ class ReflecBeat(ReflecBeatBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
game_config = self.get_game_config() game_config = self.get_game_config()
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
@ -515,9 +496,7 @@ class ReflecBeat(ReflecBeatBase):
achievement_rate = child.child_value("myself/ar") * 10 achievement_rate = child.child_value("myself/ar") * 10
points = child.child_value("myself/s") points = child.child_value("myself/s")
clear_type, combo_type = self.__game_to_db_clear_type( clear_type, combo_type = self.__game_to_db_clear_type(clear_type, achievement_rate)
clear_type, achievement_rate
)
combo = None combo = None
miss_count = -1 miss_count = -1
@ -527,10 +506,7 @@ class ReflecBeat(ReflecBeatBase):
if chart in savedrecords[songid]: if chart in savedrecords[songid]:
data = savedrecords[songid][chart] data = savedrecords[songid][chart]
if ( if data["achievement_rate"] == achievement_rate and data["points"] == points:
data["achievement_rate"] == achievement_rate
and data["points"] == points
):
# This is the same record! Use the stats from it to update our # This is the same record! Use the stats from it to update our
# internal representation. # internal representation.
combo = data["combo"] combo = data["combo"]

View File

@ -76,25 +76,18 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
rec.add_child(Node.s16("mid", score.id)) rec.add_child(Node.s16("mid", score.id))
rec.add_child(Node.s8("ntgrd", score.chart)) rec.add_child(Node.s8("ntgrd", score.chart))
rec.add_child(Node.s32("pc", score.plays)) rec.add_child(Node.s32("pc", score.plays))
rec.add_child( rec.add_child(Node.s8("ct", self._db_to_game_clear_type(score.data.get_int("clear_type"))))
Node.s8(
"ct", self._db_to_game_clear_type(score.data.get_int("clear_type"))
)
)
rec.add_child(Node.s16("ar", score.data.get_int("achievement_rate"))) rec.add_child(Node.s16("ar", score.data.get_int("achievement_rate")))
rec.add_child(Node.s16("scr", score.points)) rec.add_child(Node.s16("scr", score.points))
rec.add_child(Node.s16("ms", score.data.get_int("miss_count"))) rec.add_child(Node.s16("ms", score.data.get_int("miss_count")))
rec.add_child( rec.add_child(
Node.s16( Node.s16(
"param", "param",
self._db_to_game_combo_type(score.data.get_int("combo_type")) self._db_to_game_combo_type(score.data.get_int("combo_type")) + score.data.get_int("param"),
+ score.data.get_int("param"),
) )
) )
rec.add_child(Node.s32("bscrt", score.timestamp)) rec.add_child(Node.s32("bscrt", score.timestamp))
rec.add_child( rec.add_child(Node.s32("bart", score.data.get_int("best_achievement_rate_time")))
Node.s32("bart", score.data.get_int("best_achievement_rate_time"))
)
rec.add_child(Node.s32("bctt", score.data.get_int("best_clear_type_time"))) rec.add_child(Node.s32("bctt", score.data.get_int("best_clear_type_time")))
rec.add_child(Node.s32("bmst", score.data.get_int("best_miss_count_time"))) rec.add_child(Node.s32("bmst", score.data.get_int("best_miss_count_time")))
rec.add_child(Node.s32("time", score.data.get_int("last_played_time"))) rec.add_child(Node.s32("time", score.data.get_int("last_played_time")))
@ -111,9 +104,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
score = None score = None
profile = None profile = None
else: else:
score = self.data.remote.music.get_score( score = self.data.remote.music.get_score(self.game, self.version, userid, songid, chart)
self.game, self.version, userid, songid, chart
)
profile = self.get_any_profile(userid) profile = self.get_any_profile(userid)
root = Node.void("player") root = Node.void("player")
@ -125,14 +116,10 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
player_select_score.add_child(Node.string("name", profile.get_str("name"))) player_select_score.add_child(Node.string("name", profile.get_str("name")))
player_select_score.add_child(Node.s32("m_score", score.points)) player_select_score.add_child(Node.s32("m_score", score.points))
player_select_score.add_child(Node.s32("m_scoreTime", score.timestamp)) player_select_score.add_child(Node.s32("m_scoreTime", score.timestamp))
player_select_score.add_child( player_select_score.add_child(Node.s16("m_iconID", profile.get_dict("config").get_int("icon_id")))
Node.s16("m_iconID", profile.get_dict("config").get_int("icon_id"))
)
return root return root
def handle_player_rb5_player_read_rival_ranking_data_request( def handle_player_rb5_player_read_rival_ranking_data_request(self, request: Node) -> Node:
self, request: Node
) -> Node:
extid = request.child_value("uid") extid = request.child_value("uid")
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
@ -154,13 +141,9 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
rival_data.add_child(rl) rival_data.add_child(rl)
rl.add_child(Node.s32("uid", rprofile.extid)) rl.add_child(Node.s32("uid", rprofile.extid))
rl.add_child(Node.string("nm", rprofile.get_str("name"))) rl.add_child(Node.string("nm", rprofile.get_str("name")))
rl.add_child( rl.add_child(Node.s16("ic", rprofile.get_dict("config").get_int("icon_id")))
Node.s16("ic", rprofile.get_dict("config").get_int("icon_id"))
)
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.version, link.other_userid)
self.game, self.version, link.other_userid
)
scores_by_musicid: Dict[int, List[Score]] = {} scores_by_musicid: Dict[int, List[Score]] = {}
for score in scores: for score in scores:
if score.id not in scores_by_musicid: if score.id not in scores_by_musicid:
@ -168,13 +151,8 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
scores_by_musicid[score.id][score.chart] = score scores_by_musicid[score.id][score.chart] = score
for mid, scores in scores_by_musicid.items(): for mid, scores in scores_by_musicid.items():
points = [ points = [score.points << 32 if score is not None else 0 for score in scores]
score.points << 32 if score is not None else 0 timestamps = [score.timestamp if score is not None else 0 for score in scores]
for score in scores
]
timestamps = [
score.timestamp if score is not None else 0 for score in scores
]
sl = Node.void("sl") sl = Node.void("sl")
rl.add_child(sl) rl.add_child(sl)
@ -206,86 +184,50 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
userid: [ userid: [
score score
for (uid, score) in all_scores for (uid, score) in all_scores
if uid == userid if uid == userid and score.data.get_int("clear_type") >= self.CLEAR_TYPE_CLEARED
and score.data.get_int("clear_type") >= self.CLEAR_TYPE_CLEARED
] ]
for userid in all_users for userid in all_users
} }
# Now grab all user profiles for this game # Now grab all user profiles for this game
all_profiles = { all_profiles = {
profile[0]: profile[1] profile[0]: profile[1] for profile in self.data.remote.user.get_all_profiles(self.game, self.version)
for profile in self.data.remote.user.get_all_profiles(
self.game, self.version
)
} }
# Now, sum up the scores into the five categories that the game expects. # Now, sum up the scores into the five categories that the game expects.
total_scores = sorted( total_scores = sorted(
[ [sum([score.points for score in scores]) for userid, scores in scores_by_user.items()],
sum([score.points for score in scores])
for userid, scores in scores_by_user.items()
],
reverse=True, reverse=True,
) )
basic_scores = sorted( basic_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_BASIC])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_BASIC
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
medium_scores = sorted( medium_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_MEDIUM])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_MEDIUM
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
hard_scores = sorted( hard_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_HARD])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_HARD
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
) )
special_scores = sorted( special_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_SPECIAL])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_SPECIAL
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
minigame_scores = sorted( minigame_scores = sorted(
[ [all_profiles.get(userid, Profile(self.game, self.version, "", 0)).get_int("mgsc") for userid in all_users],
all_profiles.get(
userid, Profile(self.game, self.version, "", 0)
).get_int("mgsc")
for userid in all_users
],
reverse=True, reverse=True,
) )
@ -351,9 +293,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
def format_profile(self, userid: UserID, profile: Profile) -> Node: def format_profile(self, userid: UserID, profile: Profile) -> Node:
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
links = self.data.local.user.get_links(self.game, self.version, userid) links = self.data.local.user.get_links(self.game, self.version, userid)
root = Node.void("player") root = Node.void("player")
pdata = Node.void("pdata") pdata = Node.void("pdata")
@ -436,9 +376,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
rprofile = self.get_profile(link.other_userid) rprofile = self.get_profile(link.other_userid)
if rprofile is None: if rprofile is None:
continue continue
lobbyinfo = self.data.local.lobby.get_play_session_info( lobbyinfo = self.data.local.lobby.get_play_session_info(self.game, self.version, link.other_userid)
self.game, self.version, link.other_userid
)
if lobbyinfo is None: if lobbyinfo is None:
lobbyinfo = ValidatedDict() lobbyinfo = ValidatedDict()
@ -447,9 +385,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
r.add_child(Node.s32("slot_id", slotid)) r.add_child(Node.s32("slot_id", slotid))
r.add_child(Node.s32("id", rprofile.extid)) r.add_child(Node.s32("id", rprofile.extid))
r.add_child(Node.string("name", rprofile.get_str("name"))) r.add_child(Node.string("name", rprofile.get_str("name")))
r.add_child( r.add_child(Node.s32("icon", rprofile.get_dict("config").get_int("icon_id")))
Node.s32("icon", rprofile.get_dict("config").get_int("icon_id"))
)
r.add_child(Node.s32("class", rprofile.get_int("class"))) r.add_child(Node.s32("class", rprofile.get_int("class")))
r.add_child(Node.s32("class_ar", rprofile.get_int("class_ar"))) r.add_child(Node.s32("class_ar", rprofile.get_int("class_ar")))
r.add_child(Node.bool("friend", True)) r.add_child(Node.bool("friend", True))
@ -466,48 +402,26 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
config = Node.void("config") config = Node.void("config")
pdata.add_child(config) pdata.add_child(config)
config.add_child(Node.u8("msel_bgm", configdict.get_int("msel_bgm"))) config.add_child(Node.u8("msel_bgm", configdict.get_int("msel_bgm")))
config.add_child( config.add_child(Node.u8("narrowdown_type", configdict.get_int("narrowdown_type")))
Node.u8("narrowdown_type", configdict.get_int("narrowdown_type"))
)
config.add_child(Node.s16("icon_id", configdict.get_int("icon_id"))) config.add_child(Node.s16("icon_id", configdict.get_int("icon_id")))
config.add_child(Node.s16("byword_0", configdict.get_int("byword_0"))) config.add_child(Node.s16("byword_0", configdict.get_int("byword_0")))
config.add_child(Node.s16("byword_1", configdict.get_int("byword_1"))) config.add_child(Node.s16("byword_1", configdict.get_int("byword_1")))
config.add_child( config.add_child(Node.bool("is_auto_byword_0", configdict.get_bool("is_auto_byword_0")))
Node.bool("is_auto_byword_0", configdict.get_bool("is_auto_byword_0")) config.add_child(Node.bool("is_auto_byword_1", configdict.get_bool("is_auto_byword_1")))
)
config.add_child(
Node.bool("is_auto_byword_1", configdict.get_bool("is_auto_byword_1"))
)
config.add_child(Node.u8("mrec_type", configdict.get_int("mrec_type"))) config.add_child(Node.u8("mrec_type", configdict.get_int("mrec_type")))
config.add_child(Node.u8("tab_sel", configdict.get_int("tab_sel"))) config.add_child(Node.u8("tab_sel", configdict.get_int("tab_sel")))
config.add_child(Node.u8("card_disp", configdict.get_int("card_disp"))) config.add_child(Node.u8("card_disp", configdict.get_int("card_disp")))
config.add_child( config.add_child(Node.u8("score_tab_disp", configdict.get_int("score_tab_disp")))
Node.u8("score_tab_disp", configdict.get_int("score_tab_disp")) config.add_child(Node.s16("last_music_id", configdict.get_int("last_music_id", -1)))
) config.add_child(Node.u8("last_note_grade", configdict.get_int("last_note_grade")))
config.add_child(
Node.s16("last_music_id", configdict.get_int("last_music_id", -1))
)
config.add_child(
Node.u8("last_note_grade", configdict.get_int("last_note_grade"))
)
config.add_child(Node.u8("sort_type", configdict.get_int("sort_type"))) config.add_child(Node.u8("sort_type", configdict.get_int("sort_type")))
config.add_child( config.add_child(Node.u8("rival_panel_type", configdict.get_int("rival_panel_type")))
Node.u8("rival_panel_type", configdict.get_int("rival_panel_type")) config.add_child(Node.u64("random_entry_work", configdict.get_int("random_entry_work")))
) config.add_child(Node.u64("custom_folder_work", configdict.get_int("custom_folder_work")))
config.add_child(
Node.u64("random_entry_work", configdict.get_int("random_entry_work"))
)
config.add_child(
Node.u64("custom_folder_work", configdict.get_int("custom_folder_work"))
)
config.add_child(Node.u8("folder_type", configdict.get_int("folder_type"))) config.add_child(Node.u8("folder_type", configdict.get_int("folder_type")))
config.add_child( config.add_child(Node.u8("folder_lamp_type", configdict.get_int("folder_lamp_type")))
Node.u8("folder_lamp_type", configdict.get_int("folder_lamp_type"))
)
config.add_child(Node.bool("is_tweet", configdict.get_bool("is_tweet"))) config.add_child(Node.bool("is_tweet", configdict.get_bool("is_tweet")))
config.add_child( config.add_child(Node.bool("is_link_twitter", configdict.get_bool("is_link_twitter")))
Node.bool("is_link_twitter", configdict.get_bool("is_link_twitter"))
)
# Customizations # Customizations
customdict = profile.get_dict("custom") customdict = profile.get_dict("custom")
@ -526,18 +440,10 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
custom.add_child(Node.u8("st_rnd", customdict.get_int("st_rnd"))) custom.add_child(Node.u8("st_rnd", customdict.get_int("st_rnd")))
custom.add_child(Node.u8("st_hazard", customdict.get_int("st_hazard"))) custom.add_child(Node.u8("st_hazard", customdict.get_int("st_hazard")))
custom.add_child(Node.u8("st_clr_cond", customdict.get_int("st_clr_cond"))) custom.add_child(Node.u8("st_clr_cond", customdict.get_int("st_clr_cond")))
custom.add_child( custom.add_child(Node.u8("same_time_note_disp", customdict.get_int("same_time_note_disp")))
Node.u8("same_time_note_disp", customdict.get_int("same_time_note_disp")) custom.add_child(Node.u8("st_gr_gauge_type", customdict.get_int("st_gr_gauge_type")))
) custom.add_child(Node.s16("voice_message_set", customdict.get_int("voice_message_set", -1)))
custom.add_child( custom.add_child(Node.u8("voice_message_volume", customdict.get_int("voice_message_volume")))
Node.u8("st_gr_gauge_type", customdict.get_int("st_gr_gauge_type"))
)
custom.add_child(
Node.s16("voice_message_set", customdict.get_int("voice_message_set", -1))
)
custom.add_child(
Node.u8("voice_message_volume", customdict.get_int("voice_message_volume"))
)
# Unlocks # Unlocks
released = Node.void("released") released = Node.void("released")
@ -591,9 +497,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
info.add_child(Node.u8("type", announcementtype)) info.add_child(Node.u8("type", announcementtype))
info.add_child(Node.u16("id", announcement.id)) info.add_child(Node.u16("id", announcement.id))
info.add_child(Node.u16("param", announcement.data.get_int("param"))) info.add_child(Node.u16("param", announcement.data.get_int("param")))
info.add_child( info.add_child(Node.bool("bneedannounce", announcement.data.get_bool("need")))
Node.bool("bneedannounce", announcement.data.get_bool("need"))
)
# Dojo ranking return # Dojo ranking return
dojo = Node.void("dojo") dojo = Node.void("dojo")
@ -610,12 +514,8 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
rec.add_child(Node.s32("total_ar", entry.data.get_int("ar"))) rec.add_child(Node.s32("total_ar", entry.data.get_int("ar")))
rec.add_child(Node.s32("total_score", entry.data.get_int("score"))) rec.add_child(Node.s32("total_score", entry.data.get_int("score")))
rec.add_child(Node.s32("play_count", entry.data.get_int("plays"))) rec.add_child(Node.s32("play_count", entry.data.get_int("plays")))
rec.add_child( rec.add_child(Node.s32("last_play_time", entry.data.get_int("play_timestamp")))
Node.s32("last_play_time", entry.data.get_int("play_timestamp")) rec.add_child(Node.s32("record_update_time", entry.data.get_int("record_timestamp")))
)
rec.add_child(
Node.s32("record_update_time", entry.data.get_int("record_timestamp"))
)
rec.add_child(Node.s32("rank", 0)) rec.add_child(Node.s32("rank", 0))
# Player Parameters # Player Parameters
@ -631,9 +531,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
player_param.add_child(itemnode) player_param.add_child(itemnode)
itemnode.add_child(Node.s32("type", itemtype)) itemnode.add_child(Node.s32("type", itemtype))
itemnode.add_child(Node.s32("bank", param.id)) itemnode.add_child(Node.s32("bank", param.id))
itemnode.add_child( itemnode.add_child(Node.s32_array("data", param.data.get_int_array("data", 256)))
Node.s32_array("data", param.data.get_int_array("data", 256))
)
# Shop score for players # Shop score for players
self._add_shop_score(pdata) self._add_shop_score(pdata)
@ -644,9 +542,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
listdata = Node.void("list") listdata = Node.void("list")
mylist.add_child(listdata) mylist.add_child(listdata)
listdata.add_child(Node.s16("idx", 0)) listdata.add_child(Node.s16("idx", 0))
listdata.add_child( listdata.add_child(Node.s16_array("mlst", profile.get_int_array("favorites", 30, [-1] * 30)))
Node.s16_array("mlst", profile.get_int_array("favorites", 30, [-1] * 30))
)
# Minigame settings # Minigame settings
minigame = Node.void("minigame") minigame = Node.void("minigame")
@ -661,16 +557,12 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
game_config = self.get_game_config() game_config = self.get_game_config()
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Save base player profile info # Save base player profile info
newprofile.replace_int( newprofile.replace_int("lid", ID.parse_machine_id(request.child_value("pdata/account/lid")))
"lid", ID.parse_machine_id(request.child_value("pdata/account/lid"))
)
newprofile.replace_str("name", request.child_value("pdata/base/name")) newprofile.replace_str("name", request.child_value("pdata/base/name"))
newprofile.replace_int("mg", request.child_value("pdata/base/mg")) newprofile.replace_int("mg", request.child_value("pdata/base/mg"))
newprofile.replace_int("ap", request.child_value("pdata/base/ap")) newprofile.replace_int("ap", request.child_value("pdata/base/ap"))
@ -680,55 +572,33 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
newprofile.replace_int("class_ar", request.child_value("pdata/base/class_ar")) newprofile.replace_int("class_ar", request.child_value("pdata/base/class_ar"))
newprofile.replace_int("mgid", request.child_value("pdata/minigame/mgid")) newprofile.replace_int("mgid", request.child_value("pdata/minigame/mgid"))
newprofile.replace_int("mgsc", request.child_value("pdata/minigame/sc")) newprofile.replace_int("mgsc", request.child_value("pdata/minigame/sc"))
newprofile.replace_int_array( newprofile.replace_int_array("favorites", 30, request.child_value("pdata/mylist/list/mlst"))
"favorites", 30, request.child_value("pdata/mylist/list/mlst")
)
# Save player config # Save player config
configdict = newprofile.get_dict("config") configdict = newprofile.get_dict("config")
config = request.child("pdata/config") config = request.child("pdata/config")
if config: if config:
configdict.replace_int("msel_bgm", config.child_value("msel_bgm")) configdict.replace_int("msel_bgm", config.child_value("msel_bgm"))
configdict.replace_int( configdict.replace_int("narrowdown_type", config.child_value("narrowdown_type"))
"narrowdown_type", config.child_value("narrowdown_type")
)
configdict.replace_int("icon_id", config.child_value("icon_id")) configdict.replace_int("icon_id", config.child_value("icon_id"))
configdict.replace_int("byword_0", config.child_value("byword_0")) configdict.replace_int("byword_0", config.child_value("byword_0"))
configdict.replace_int("byword_1", config.child_value("byword_1")) configdict.replace_int("byword_1", config.child_value("byword_1"))
configdict.replace_bool( configdict.replace_bool("is_auto_byword_0", config.child_value("is_auto_byword_0"))
"is_auto_byword_0", config.child_value("is_auto_byword_0") configdict.replace_bool("is_auto_byword_1", config.child_value("is_auto_byword_1"))
)
configdict.replace_bool(
"is_auto_byword_1", config.child_value("is_auto_byword_1")
)
configdict.replace_int("mrec_type", config.child_value("mrec_type")) configdict.replace_int("mrec_type", config.child_value("mrec_type"))
configdict.replace_int("tab_sel", config.child_value("tab_sel")) configdict.replace_int("tab_sel", config.child_value("tab_sel"))
configdict.replace_int("card_disp", config.child_value("card_disp")) configdict.replace_int("card_disp", config.child_value("card_disp"))
configdict.replace_int( configdict.replace_int("score_tab_disp", config.child_value("score_tab_disp"))
"score_tab_disp", config.child_value("score_tab_disp")
)
configdict.replace_int("last_music_id", config.child_value("last_music_id")) configdict.replace_int("last_music_id", config.child_value("last_music_id"))
configdict.replace_int( configdict.replace_int("last_note_grade", config.child_value("last_note_grade"))
"last_note_grade", config.child_value("last_note_grade")
)
configdict.replace_int("sort_type", config.child_value("sort_type")) configdict.replace_int("sort_type", config.child_value("sort_type"))
configdict.replace_int( configdict.replace_int("rival_panel_type", config.child_value("rival_panel_type"))
"rival_panel_type", config.child_value("rival_panel_type") configdict.replace_int("random_entry_work", config.child_value("random_entry_work"))
) configdict.replace_int("custom_folder_work", config.child_value("custom_folder_work"))
configdict.replace_int(
"random_entry_work", config.child_value("random_entry_work")
)
configdict.replace_int(
"custom_folder_work", config.child_value("custom_folder_work")
)
configdict.replace_int("folder_type", config.child_value("folder_type")) configdict.replace_int("folder_type", config.child_value("folder_type"))
configdict.replace_int( configdict.replace_int("folder_lamp_type", config.child_value("folder_lamp_type"))
"folder_lamp_type", config.child_value("folder_lamp_type")
)
configdict.replace_bool("is_tweet", config.child_value("is_tweet")) configdict.replace_bool("is_tweet", config.child_value("is_tweet"))
configdict.replace_bool( configdict.replace_bool("is_link_twitter", config.child_value("is_link_twitter"))
"is_link_twitter", config.child_value("is_link_twitter")
)
newprofile.replace_dict("config", configdict) newprofile.replace_dict("config", configdict)
# Save player custom settings # Save player custom settings
@ -747,18 +617,10 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
customdict.replace_int("st_rnd", custom.child_value("st_rnd")) customdict.replace_int("st_rnd", custom.child_value("st_rnd"))
customdict.replace_int("st_hazard", custom.child_value("st_hazard")) customdict.replace_int("st_hazard", custom.child_value("st_hazard"))
customdict.replace_int("st_clr_cond", custom.child_value("st_clr_cond")) customdict.replace_int("st_clr_cond", custom.child_value("st_clr_cond"))
customdict.replace_int( customdict.replace_int("same_time_note_disp", custom.child_value("same_time_note_disp"))
"same_time_note_disp", custom.child_value("same_time_note_disp") customdict.replace_int("st_gr_gauge_type", custom.child_value("st_gr_gauge_type"))
) customdict.replace_int("voice_message_set", custom.child_value("voice_message_set"))
customdict.replace_int( customdict.replace_int("voice_message_volume", custom.child_value("voice_message_volume"))
"st_gr_gauge_type", custom.child_value("st_gr_gauge_type")
)
customdict.replace_int(
"voice_message_set", custom.child_value("voice_message_set")
)
customdict.replace_int(
"voice_message_volume", custom.child_value("voice_message_volume")
)
newprofile.replace_dict("custom", customdict) newprofile.replace_dict("custom", customdict)
# Save player parameter info # Save player parameter info
@ -794,9 +656,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
# I assume this is copypasta, but I want to be sure # I assume this is copypasta, but I want to be sure
extid = child.child_value("user_id") extid = child.child_value("user_id")
if extid != newprofile.extid: if extid != newprofile.extid:
raise Exception( raise Exception(f"Unexpected user ID, got {extid} expecting {newprofile.extid}")
f"Unexpected user ID, got {extid} expecting {newprofile.extid}"
)
episode_type = child.child_value("type") episode_type = child.child_value("type")
episode_value0 = child.child_value("value0") episode_value0 = child.child_value("value0")
@ -923,9 +783,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
continue continue
extid = child.child_value("id") extid = child.child_value("id")
other_userid = self.data.remote.user.from_extid( other_userid = self.data.remote.user.from_extid(self.game, self.version, extid)
self.game, self.version, extid
)
if other_userid is None: if other_userid is None:
continue continue

View File

@ -57,10 +57,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
mycourse_ctrl = Node.void("mycourse_ctrl") mycourse_ctrl = Node.void("mycourse_ctrl")
root.add_child(mycourse_ctrl) root.add_child(mycourse_ctrl)
songs = { songs = {song.id for song in self.data.local.music.get_all_songs(self.game, self.version)}
song.id
for song in self.data.local.music.get_all_songs(self.game, self.version)
}
for song in songs: for song in songs:
data = Node.void("data") data = Node.void("data")
mycourse_ctrl.add_child(data) mycourse_ctrl.add_child(data)
@ -98,25 +95,18 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
rec.add_child(Node.s16("mid", score.id)) rec.add_child(Node.s16("mid", score.id))
rec.add_child(Node.s8("ntgrd", score.chart)) rec.add_child(Node.s8("ntgrd", score.chart))
rec.add_child(Node.s32("pc", score.plays)) rec.add_child(Node.s32("pc", score.plays))
rec.add_child( rec.add_child(Node.s8("ct", self._db_to_game_clear_type(score.data.get_int("clear_type"))))
Node.s8(
"ct", self._db_to_game_clear_type(score.data.get_int("clear_type"))
)
)
rec.add_child(Node.s16("ar", score.data.get_int("achievement_rate"))) rec.add_child(Node.s16("ar", score.data.get_int("achievement_rate")))
rec.add_child(Node.s16("scr", score.points)) rec.add_child(Node.s16("scr", score.points))
rec.add_child(Node.s16("ms", score.data.get_int("miss_count"))) rec.add_child(Node.s16("ms", score.data.get_int("miss_count")))
rec.add_child( rec.add_child(
Node.s16( Node.s16(
"param", "param",
self._db_to_game_combo_type(score.data.get_int("combo_type")) self._db_to_game_combo_type(score.data.get_int("combo_type")) + score.data.get_int("param"),
+ score.data.get_int("param"),
) )
) )
rec.add_child(Node.s32("bscrt", score.timestamp)) rec.add_child(Node.s32("bscrt", score.timestamp))
rec.add_child( rec.add_child(Node.s32("bart", score.data.get_int("best_achievement_rate_time")))
Node.s32("bart", score.data.get_int("best_achievement_rate_time"))
)
rec.add_child(Node.s32("bctt", score.data.get_int("best_clear_type_time"))) rec.add_child(Node.s32("bctt", score.data.get_int("best_clear_type_time")))
rec.add_child(Node.s32("bmst", score.data.get_int("best_miss_count_time"))) rec.add_child(Node.s32("bmst", score.data.get_int("best_miss_count_time")))
rec.add_child(Node.s32("time", score.data.get_int("last_played_time"))) rec.add_child(Node.s32("time", score.data.get_int("last_played_time")))
@ -124,9 +114,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
return root return root
def handle_player_rb5_player_read_rival_score_5_request( def handle_player_rb5_player_read_rival_score_5_request(self, request: Node) -> Node:
self, request: Node
) -> Node:
extid = request.child_value("uid") extid = request.child_value("uid")
songid = request.child_value("music_id") songid = request.child_value("music_id")
chart = request.child_value("note_grade") chart = request.child_value("note_grade")
@ -135,9 +123,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
score = None score = None
profile = None profile = None
else: else:
score = self.data.remote.music.get_score( score = self.data.remote.music.get_score(self.game, self.version, userid, songid, chart)
self.game, self.version, userid, songid, chart
)
profile = self.get_any_profile(userid) profile = self.get_any_profile(userid)
root = Node.void("player") root = Node.void("player")
@ -149,14 +135,10 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
player_select_score.add_child(Node.string("name", profile.get_str("name"))) player_select_score.add_child(Node.string("name", profile.get_str("name")))
player_select_score.add_child(Node.s32("m_score", score.points)) player_select_score.add_child(Node.s32("m_score", score.points))
player_select_score.add_child(Node.s32("m_scoreTime", score.timestamp)) player_select_score.add_child(Node.s32("m_scoreTime", score.timestamp))
player_select_score.add_child( player_select_score.add_child(Node.s16("m_iconID", profile.get_dict("config").get_int("icon_id")))
Node.s16("m_iconID", profile.get_dict("config").get_int("icon_id"))
)
return root return root
def handle_player_rb5_player_read_rival_ranking_data_5_request( def handle_player_rb5_player_read_rival_ranking_data_5_request(self, request: Node) -> Node:
self, request: Node
) -> Node:
extid = request.child_value("uid") extid = request.child_value("uid")
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
@ -178,13 +160,9 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
rival_data.add_child(rl) rival_data.add_child(rl)
rl.add_child(Node.s32("uid", rprofile.extid)) rl.add_child(Node.s32("uid", rprofile.extid))
rl.add_child(Node.string("nm", rprofile.get_str("name"))) rl.add_child(Node.string("nm", rprofile.get_str("name")))
rl.add_child( rl.add_child(Node.s16("ic", rprofile.get_dict("config").get_int("icon_id")))
Node.s16("ic", rprofile.get_dict("config").get_int("icon_id"))
)
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.version, link.other_userid)
self.game, self.version, link.other_userid
)
scores_by_musicid: Dict[int, List[Score]] = {} scores_by_musicid: Dict[int, List[Score]] = {}
for score in scores: for score in scores:
if score.id not in scores_by_musicid: if score.id not in scores_by_musicid:
@ -192,13 +170,8 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
scores_by_musicid[score.id][score.chart] = score scores_by_musicid[score.id][score.chart] = score
for mid, scores in scores_by_musicid.items(): for mid, scores in scores_by_musicid.items():
points = [ points = [score.points << 32 if score is not None else 0 for score in scores]
score.points << 32 if score is not None else 0 timestamps = [score.timestamp if score is not None else 0 for score in scores]
for score in scores
]
timestamps = [
score.timestamp if score is not None else 0 for score in scores
]
sl = Node.void("sl") sl = Node.void("sl")
rl.add_child(sl) rl.add_child(sl)
@ -230,86 +203,50 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
userid: [ userid: [
score score
for (uid, score) in all_scores for (uid, score) in all_scores
if uid == userid if uid == userid and score.data.get_int("clear_type") >= self.CLEAR_TYPE_CLEARED
and score.data.get_int("clear_type") >= self.CLEAR_TYPE_CLEARED
] ]
for userid in all_users for userid in all_users
} }
# Now grab all user profiles for this game # Now grab all user profiles for this game
all_profiles = { all_profiles = {
profile[0]: profile[1] profile[0]: profile[1] for profile in self.data.remote.user.get_all_profiles(self.game, self.version)
for profile in self.data.remote.user.get_all_profiles(
self.game, self.version
)
} }
# Now, sum up the scores into the five categories that the game expects. # Now, sum up the scores into the five categories that the game expects.
total_scores = sorted( total_scores = sorted(
[ [sum([score.points for score in scores]) for userid, scores in scores_by_user.items()],
sum([score.points for score in scores])
for userid, scores in scores_by_user.items()
],
reverse=True, reverse=True,
) )
basic_scores = sorted( basic_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_BASIC])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_BASIC
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
medium_scores = sorted( medium_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_MEDIUM])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_MEDIUM
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
hard_scores = sorted( hard_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_HARD])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_HARD
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
) )
special_scores = sorted( special_scores = sorted(
[ [
sum( sum([score.points for score in scores if score.chart == self.CHART_TYPE_SPECIAL])
[
score.points
for score in scores
if score.chart == self.CHART_TYPE_SPECIAL
]
)
for userid, scores in scores_by_user.items() for userid, scores in scores_by_user.items()
], ],
reverse=True, reverse=True,
) )
minigame_scores = sorted( minigame_scores = sorted(
[ [all_profiles.get(userid, Profile(self.game, self.version, "", 0)).get_int("mgsc") for userid in all_users],
all_profiles.get(
userid, Profile(self.game, self.version, "", 0)
).get_int("mgsc")
for userid in all_users
],
reverse=True, reverse=True,
) )
@ -375,9 +312,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
def format_profile(self, userid: UserID, profile: Profile) -> Node: def format_profile(self, userid: UserID, profile: Profile) -> Node:
statistics = self.get_play_statistics(userid) statistics = self.get_play_statistics(userid)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
links = self.data.local.user.get_links(self.game, self.version, userid) links = self.data.local.user.get_links(self.game, self.version, userid)
rprofiles: Dict[UserID, Profile] = {} rprofiles: Dict[UserID, Profile] = {}
root = Node.void("player") root = Node.void("player")
@ -468,9 +403,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
rprofiles[link.other_userid] = rprofile rprofiles[link.other_userid] = rprofile
else: else:
rprofile = rprofiles[link.other_userid] rprofile = rprofiles[link.other_userid]
lobbyinfo = self.data.local.lobby.get_play_session_info( lobbyinfo = self.data.local.lobby.get_play_session_info(self.game, self.version, link.other_userid)
self.game, self.version, link.other_userid
)
if lobbyinfo is None: if lobbyinfo is None:
lobbyinfo = ValidatedDict() lobbyinfo = ValidatedDict()
@ -479,9 +412,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
r.add_child(Node.s32("slot_id", slotid)) r.add_child(Node.s32("slot_id", slotid))
r.add_child(Node.s32("id", rprofile.extid)) r.add_child(Node.s32("id", rprofile.extid))
r.add_child(Node.string("name", rprofile.get_str("name"))) r.add_child(Node.string("name", rprofile.get_str("name")))
r.add_child( r.add_child(Node.s32("icon", rprofile.get_dict("config").get_int("icon_id")))
Node.s32("icon", rprofile.get_dict("config").get_int("icon_id"))
)
r.add_child(Node.s32("class", rprofile.get_int("class"))) r.add_child(Node.s32("class", rprofile.get_int("class")))
r.add_child(Node.s32("class_ar", rprofile.get_int("class_ar"))) r.add_child(Node.s32("class_ar", rprofile.get_int("class_ar")))
r.add_child(Node.bool("friend", True)) r.add_child(Node.bool("friend", True))
@ -498,48 +429,26 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
config = Node.void("config") config = Node.void("config")
pdata.add_child(config) pdata.add_child(config)
config.add_child(Node.u8("msel_bgm", configdict.get_int("msel_bgm"))) config.add_child(Node.u8("msel_bgm", configdict.get_int("msel_bgm")))
config.add_child( config.add_child(Node.u8("narrowdown_type", configdict.get_int("narrowdown_type")))
Node.u8("narrowdown_type", configdict.get_int("narrowdown_type"))
)
config.add_child(Node.s16("icon_id", configdict.get_int("icon_id"))) config.add_child(Node.s16("icon_id", configdict.get_int("icon_id")))
config.add_child(Node.s16("byword_0", configdict.get_int("byword_0"))) config.add_child(Node.s16("byword_0", configdict.get_int("byword_0")))
config.add_child(Node.s16("byword_1", configdict.get_int("byword_1"))) config.add_child(Node.s16("byword_1", configdict.get_int("byword_1")))
config.add_child( config.add_child(Node.bool("is_auto_byword_0", configdict.get_bool("is_auto_byword_0")))
Node.bool("is_auto_byword_0", configdict.get_bool("is_auto_byword_0")) config.add_child(Node.bool("is_auto_byword_1", configdict.get_bool("is_auto_byword_1")))
)
config.add_child(
Node.bool("is_auto_byword_1", configdict.get_bool("is_auto_byword_1"))
)
config.add_child(Node.u8("mrec_type", configdict.get_int("mrec_type"))) config.add_child(Node.u8("mrec_type", configdict.get_int("mrec_type")))
config.add_child(Node.u8("tab_sel", configdict.get_int("tab_sel"))) config.add_child(Node.u8("tab_sel", configdict.get_int("tab_sel")))
config.add_child(Node.u8("card_disp", configdict.get_int("card_disp"))) config.add_child(Node.u8("card_disp", configdict.get_int("card_disp")))
config.add_child( config.add_child(Node.u8("score_tab_disp", configdict.get_int("score_tab_disp")))
Node.u8("score_tab_disp", configdict.get_int("score_tab_disp")) config.add_child(Node.s16("last_music_id", configdict.get_int("last_music_id", -1)))
) config.add_child(Node.u8("last_note_grade", configdict.get_int("last_note_grade")))
config.add_child(
Node.s16("last_music_id", configdict.get_int("last_music_id", -1))
)
config.add_child(
Node.u8("last_note_grade", configdict.get_int("last_note_grade"))
)
config.add_child(Node.u8("sort_type", configdict.get_int("sort_type"))) config.add_child(Node.u8("sort_type", configdict.get_int("sort_type")))
config.add_child( config.add_child(Node.u8("rival_panel_type", configdict.get_int("rival_panel_type")))
Node.u8("rival_panel_type", configdict.get_int("rival_panel_type")) config.add_child(Node.u64("random_entry_work", configdict.get_int("random_entry_work")))
) config.add_child(Node.u64("custom_folder_work", configdict.get_int("custom_folder_work")))
config.add_child(
Node.u64("random_entry_work", configdict.get_int("random_entry_work"))
)
config.add_child(
Node.u64("custom_folder_work", configdict.get_int("custom_folder_work"))
)
config.add_child(Node.u8("folder_type", configdict.get_int("folder_type"))) config.add_child(Node.u8("folder_type", configdict.get_int("folder_type")))
config.add_child( config.add_child(Node.u8("folder_lamp_type", configdict.get_int("folder_lamp_type")))
Node.u8("folder_lamp_type", configdict.get_int("folder_lamp_type"))
)
config.add_child(Node.bool("is_tweet", configdict.get_bool("is_tweet"))) config.add_child(Node.bool("is_tweet", configdict.get_bool("is_tweet")))
config.add_child( config.add_child(Node.bool("is_link_twitter", configdict.get_bool("is_link_twitter")))
Node.bool("is_link_twitter", configdict.get_bool("is_link_twitter"))
)
# Customizations # Customizations
customdict = profile.get_dict("custom") customdict = profile.get_dict("custom")
@ -555,31 +464,17 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
custom.add_child(Node.u8("st_jr_gauge", customdict.get_int("st_jr_gauge"))) custom.add_child(Node.u8("st_jr_gauge", customdict.get_int("st_jr_gauge")))
custom.add_child(Node.u8("st_clr_gauge", customdict.get_int("st_clr_gauge"))) custom.add_child(Node.u8("st_clr_gauge", customdict.get_int("st_clr_gauge")))
custom.add_child(Node.u8("st_rnd", customdict.get_int("st_rnd"))) custom.add_child(Node.u8("st_rnd", customdict.get_int("st_rnd")))
custom.add_child( custom.add_child(Node.u8("st_gr_gauge_type", customdict.get_int("st_gr_gauge_type")))
Node.u8("st_gr_gauge_type", customdict.get_int("st_gr_gauge_type")) custom.add_child(Node.s16("voice_message_set", customdict.get_int("voice_message_set", -1)))
) custom.add_child(Node.u8("same_time_note_disp", customdict.get_int("same_time_note_disp")))
custom.add_child( custom.add_child(Node.u8("st_score_disp_type", customdict.get_int("st_score_disp_type")))
Node.s16("voice_message_set", customdict.get_int("voice_message_set", -1))
)
custom.add_child(
Node.u8("same_time_note_disp", customdict.get_int("same_time_note_disp"))
)
custom.add_child(
Node.u8("st_score_disp_type", customdict.get_int("st_score_disp_type"))
)
custom.add_child(Node.u8("st_bonus_type", customdict.get_int("st_bonus_type"))) custom.add_child(Node.u8("st_bonus_type", customdict.get_int("st_bonus_type")))
custom.add_child( custom.add_child(Node.u8("st_rivalnote_type", customdict.get_int("st_rivalnote_type")))
Node.u8("st_rivalnote_type", customdict.get_int("st_rivalnote_type")) custom.add_child(Node.u8("st_topassist_type", customdict.get_int("st_topassist_type")))
)
custom.add_child(
Node.u8("st_topassist_type", customdict.get_int("st_topassist_type"))
)
custom.add_child(Node.u8("high_speed", customdict.get_int("high_speed"))) custom.add_child(Node.u8("high_speed", customdict.get_int("high_speed")))
custom.add_child(Node.u8("st_hazard", customdict.get_int("st_hazard"))) custom.add_child(Node.u8("st_hazard", customdict.get_int("st_hazard")))
custom.add_child(Node.u8("st_clr_cond", customdict.get_int("st_clr_cond"))) custom.add_child(Node.u8("st_clr_cond", customdict.get_int("st_clr_cond")))
custom.add_child( custom.add_child(Node.u8("voice_message_volume", customdict.get_int("voice_message_volume")))
Node.u8("voice_message_volume", customdict.get_int("voice_message_volume"))
)
# Unlocks # Unlocks
released = Node.void("released") released = Node.void("released")
@ -635,9 +530,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
info.add_child(Node.u8("type", announcementtype)) info.add_child(Node.u8("type", announcementtype))
info.add_child(Node.u16("id", announcement.id)) info.add_child(Node.u16("id", announcement.id))
info.add_child(Node.u16("param", announcement.data.get_int("param"))) info.add_child(Node.u16("param", announcement.data.get_int("param")))
info.add_child( info.add_child(Node.bool("bneedannounce", announcement.data.get_bool("need")))
Node.bool("bneedannounce", announcement.data.get_bool("need"))
)
# Dojo ranking return # Dojo ranking return
dojo = Node.void("dojo") dojo = Node.void("dojo")
@ -654,12 +547,8 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
rec.add_child(Node.s32("total_ar", entry.data.get_int("ar"))) rec.add_child(Node.s32("total_ar", entry.data.get_int("ar")))
rec.add_child(Node.s32("total_score", entry.data.get_int("score"))) rec.add_child(Node.s32("total_score", entry.data.get_int("score")))
rec.add_child(Node.s32("play_count", entry.data.get_int("plays"))) rec.add_child(Node.s32("play_count", entry.data.get_int("plays")))
rec.add_child( rec.add_child(Node.s32("last_play_time", entry.data.get_int("play_timestamp")))
Node.s32("last_play_time", entry.data.get_int("play_timestamp")) rec.add_child(Node.s32("record_update_time", entry.data.get_int("record_timestamp")))
)
rec.add_child(
Node.s32("record_update_time", entry.data.get_int("record_timestamp"))
)
rec.add_child(Node.s32("rank", 0)) rec.add_child(Node.s32("rank", 0))
# Player Parameters # Player Parameters
@ -675,9 +564,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
player_param.add_child(itemnode) player_param.add_child(itemnode)
itemnode.add_child(Node.s32("type", itemtype)) itemnode.add_child(Node.s32("type", itemtype))
itemnode.add_child(Node.s32("bank", param.id)) itemnode.add_child(Node.s32("bank", param.id))
itemnode.add_child( itemnode.add_child(Node.s32_array("data", param.data.get_int_array("data", 256)))
Node.s32_array("data", param.data.get_int_array("data", 256))
)
# Shop score for players # Shop score for players
self._add_shop_score(pdata) self._add_shop_score(pdata)
@ -688,9 +575,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
listdata = Node.void("list") listdata = Node.void("list")
mylist.add_child(listdata) mylist.add_child(listdata)
listdata.add_child(Node.s16("idx", 0)) listdata.add_child(Node.s16("idx", 0))
listdata.add_child( listdata.add_child(Node.s16_array("mlst", profile.get_int_array("favorites", 30, [-1] * 30)))
Node.s16_array("mlst", profile.get_int_array("favorites", 30, [-1] * 30))
)
# Minigame settings # Minigame settings
minigame = Node.void("minigame") minigame = Node.void("minigame")
@ -724,37 +609,19 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
mycoursedict = profile.get_dict("mycourse") mycoursedict = profile.get_dict("mycourse")
pdata.add_child(mycourse) pdata.add_child(mycourse)
mycourse.add_child(Node.s16("mycourse_id", 1)) mycourse.add_child(Node.s16("mycourse_id", 1))
mycourse.add_child( mycourse.add_child(Node.s32("music_id_1", mycoursedict.get_int("music_id_1", -1)))
Node.s32("music_id_1", mycoursedict.get_int("music_id_1", -1)) mycourse.add_child(Node.s16("note_grade_1", mycoursedict.get_int("note_grade_1", -1)))
)
mycourse.add_child(
Node.s16("note_grade_1", mycoursedict.get_int("note_grade_1", -1))
)
mycourse.add_child(Node.s32("score_1", mycoursedict.get_int("score_1", -1))) mycourse.add_child(Node.s32("score_1", mycoursedict.get_int("score_1", -1)))
mycourse.add_child( mycourse.add_child(Node.s32("music_id_2", mycoursedict.get_int("music_id_2", -1)))
Node.s32("music_id_2", mycoursedict.get_int("music_id_2", -1)) mycourse.add_child(Node.s16("note_grade_2", mycoursedict.get_int("note_grade_2", -1)))
)
mycourse.add_child(
Node.s16("note_grade_2", mycoursedict.get_int("note_grade_2", -1))
)
mycourse.add_child(Node.s32("score_2", mycoursedict.get_int("score_2", -1))) mycourse.add_child(Node.s32("score_2", mycoursedict.get_int("score_2", -1)))
mycourse.add_child( mycourse.add_child(Node.s32("music_id_3", mycoursedict.get_int("music_id_3", -1)))
Node.s32("music_id_3", mycoursedict.get_int("music_id_3", -1)) mycourse.add_child(Node.s16("note_grade_3", mycoursedict.get_int("note_grade_3", -1)))
)
mycourse.add_child(
Node.s16("note_grade_3", mycoursedict.get_int("note_grade_3", -1))
)
mycourse.add_child(Node.s32("score_3", mycoursedict.get_int("score_3", -1))) mycourse.add_child(Node.s32("score_3", mycoursedict.get_int("score_3", -1)))
mycourse.add_child( mycourse.add_child(Node.s32("music_id_4", mycoursedict.get_int("music_id_4", -1)))
Node.s32("music_id_4", mycoursedict.get_int("music_id_4", -1)) mycourse.add_child(Node.s16("note_grade_4", mycoursedict.get_int("note_grade_4", -1)))
)
mycourse.add_child(
Node.s16("note_grade_4", mycoursedict.get_int("note_grade_4", -1))
)
mycourse.add_child(Node.s32("score_4", mycoursedict.get_int("score_4", -1))) mycourse.add_child(Node.s32("score_4", mycoursedict.get_int("score_4", -1)))
mycourse.add_child( mycourse.add_child(Node.s32("insert_time", mycoursedict.get_int("insert_time", -1)))
Node.s32("insert_time", mycoursedict.get_int("insert_time", -1))
)
mycourse.add_child(Node.s32("def_music_id_1", -1)) mycourse.add_child(Node.s32("def_music_id_1", -1))
mycourse.add_child(Node.s16("def_note_grade_1", -1)) mycourse.add_child(Node.s16("def_note_grade_1", -1))
mycourse.add_child(Node.s32("def_music_id_2", -1)) mycourse.add_child(Node.s32("def_music_id_2", -1))
@ -785,50 +652,28 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
mycourse_f.add_child(rec) mycourse_f.add_child(rec)
rec.add_child(Node.s32("rival_id", rprofile.extid)) rec.add_child(Node.s32("rival_id", rprofile.extid))
rec.add_child(Node.s16("mycourse_id", 1)) rec.add_child(Node.s16("mycourse_id", 1))
rec.add_child( rec.add_child(Node.s32("music_id_1", mycoursedict.get_int("music_id_1", -1)))
Node.s32("music_id_1", mycoursedict.get_int("music_id_1", -1)) rec.add_child(Node.s16("note_grade_1", mycoursedict.get_int("note_grade_1", -1)))
)
rec.add_child(
Node.s16("note_grade_1", mycoursedict.get_int("note_grade_1", -1))
)
rec.add_child(Node.s32("score_1", mycoursedict.get_int("score_1", -1))) rec.add_child(Node.s32("score_1", mycoursedict.get_int("score_1", -1)))
rec.add_child( rec.add_child(Node.s32("music_id_2", mycoursedict.get_int("music_id_2", -1)))
Node.s32("music_id_2", mycoursedict.get_int("music_id_2", -1)) rec.add_child(Node.s16("note_grade_2", mycoursedict.get_int("note_grade_2", -1)))
)
rec.add_child(
Node.s16("note_grade_2", mycoursedict.get_int("note_grade_2", -1))
)
rec.add_child(Node.s32("score_2", mycoursedict.get_int("score_2", -1))) rec.add_child(Node.s32("score_2", mycoursedict.get_int("score_2", -1)))
rec.add_child( rec.add_child(Node.s32("music_id_3", mycoursedict.get_int("music_id_3", -1)))
Node.s32("music_id_3", mycoursedict.get_int("music_id_3", -1)) rec.add_child(Node.s16("note_grade_3", mycoursedict.get_int("note_grade_3", -1)))
)
rec.add_child(
Node.s16("note_grade_3", mycoursedict.get_int("note_grade_3", -1))
)
rec.add_child(Node.s32("score_3", mycoursedict.get_int("score_3", -1))) rec.add_child(Node.s32("score_3", mycoursedict.get_int("score_3", -1)))
rec.add_child( rec.add_child(Node.s32("music_id_4", mycoursedict.get_int("music_id_4", -1)))
Node.s32("music_id_4", mycoursedict.get_int("music_id_4", -1)) rec.add_child(Node.s16("note_grade_4", mycoursedict.get_int("note_grade_4", -1)))
)
rec.add_child(
Node.s16("note_grade_4", mycoursedict.get_int("note_grade_4", -1))
)
rec.add_child(Node.s32("score_4", mycoursedict.get_int("score_4", -1))) rec.add_child(Node.s32("score_4", mycoursedict.get_int("score_4", -1)))
rec.add_child( rec.add_child(Node.s32("insert_time", mycoursedict.get_int("insert_time", -1)))
Node.s32("insert_time", mycoursedict.get_int("insert_time", -1))
)
return root return root
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
game_config = self.get_game_config() game_config = self.get_game_config()
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Save base player profile info # Save base player profile info
newprofile.replace_int( newprofile.replace_int("lid", ID.parse_machine_id(request.child_value("pdata/account/lid")))
"lid", ID.parse_machine_id(request.child_value("pdata/account/lid"))
)
newprofile.replace_str("name", request.child_value("pdata/base/name")) newprofile.replace_str("name", request.child_value("pdata/base/name"))
newprofile.replace_int("mg", request.child_value("pdata/base/mg")) newprofile.replace_int("mg", request.child_value("pdata/base/mg"))
newprofile.replace_int("ap", request.child_value("pdata/base/ap")) newprofile.replace_int("ap", request.child_value("pdata/base/ap"))
@ -836,60 +681,36 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
newprofile.replace_int("money", request.child_value("pdata/base/money")) newprofile.replace_int("money", request.child_value("pdata/base/money"))
newprofile.replace_int("class", request.child_value("pdata/base/class")) newprofile.replace_int("class", request.child_value("pdata/base/class"))
newprofile.replace_int("class_ar", request.child_value("pdata/base/class_ar")) newprofile.replace_int("class_ar", request.child_value("pdata/base/class_ar"))
newprofile.replace_int( newprofile.replace_int("skill_point", request.child_value("pdata/base/skill_point"))
"skill_point", request.child_value("pdata/base/skill_point")
)
newprofile.replace_int("mgid", request.child_value("pdata/minigame/mgid")) newprofile.replace_int("mgid", request.child_value("pdata/minigame/mgid"))
newprofile.replace_int("mgsc", request.child_value("pdata/minigame/sc")) newprofile.replace_int("mgsc", request.child_value("pdata/minigame/sc"))
newprofile.replace_int_array( newprofile.replace_int_array("favorites", 30, request.child_value("pdata/mylist/list/mlst"))
"favorites", 30, request.child_value("pdata/mylist/list/mlst")
)
# Save player config # Save player config
configdict = newprofile.get_dict("config") configdict = newprofile.get_dict("config")
config = request.child("pdata/config") config = request.child("pdata/config")
if config: if config:
configdict.replace_int("msel_bgm", config.child_value("msel_bgm")) configdict.replace_int("msel_bgm", config.child_value("msel_bgm"))
configdict.replace_int( configdict.replace_int("narrowdown_type", config.child_value("narrowdown_type"))
"narrowdown_type", config.child_value("narrowdown_type")
)
configdict.replace_int("icon_id", config.child_value("icon_id")) configdict.replace_int("icon_id", config.child_value("icon_id"))
configdict.replace_int("byword_0", config.child_value("byword_0")) configdict.replace_int("byword_0", config.child_value("byword_0"))
configdict.replace_int("byword_1", config.child_value("byword_1")) configdict.replace_int("byword_1", config.child_value("byword_1"))
configdict.replace_bool( configdict.replace_bool("is_auto_byword_0", config.child_value("is_auto_byword_0"))
"is_auto_byword_0", config.child_value("is_auto_byword_0") configdict.replace_bool("is_auto_byword_1", config.child_value("is_auto_byword_1"))
)
configdict.replace_bool(
"is_auto_byword_1", config.child_value("is_auto_byword_1")
)
configdict.replace_int("mrec_type", config.child_value("mrec_type")) configdict.replace_int("mrec_type", config.child_value("mrec_type"))
configdict.replace_int("tab_sel", config.child_value("tab_sel")) configdict.replace_int("tab_sel", config.child_value("tab_sel"))
configdict.replace_int("card_disp", config.child_value("card_disp")) configdict.replace_int("card_disp", config.child_value("card_disp"))
configdict.replace_int( configdict.replace_int("score_tab_disp", config.child_value("score_tab_disp"))
"score_tab_disp", config.child_value("score_tab_disp")
)
configdict.replace_int("last_music_id", config.child_value("last_music_id")) configdict.replace_int("last_music_id", config.child_value("last_music_id"))
configdict.replace_int( configdict.replace_int("last_note_grade", config.child_value("last_note_grade"))
"last_note_grade", config.child_value("last_note_grade")
)
configdict.replace_int("sort_type", config.child_value("sort_type")) configdict.replace_int("sort_type", config.child_value("sort_type"))
configdict.replace_int( configdict.replace_int("rival_panel_type", config.child_value("rival_panel_type"))
"rival_panel_type", config.child_value("rival_panel_type") configdict.replace_int("random_entry_work", config.child_value("random_entry_work"))
) configdict.replace_int("custom_folder_work", config.child_value("custom_folder_work"))
configdict.replace_int(
"random_entry_work", config.child_value("random_entry_work")
)
configdict.replace_int(
"custom_folder_work", config.child_value("custom_folder_work")
)
configdict.replace_int("folder_type", config.child_value("folder_type")) configdict.replace_int("folder_type", config.child_value("folder_type"))
configdict.replace_int( configdict.replace_int("folder_lamp_type", config.child_value("folder_lamp_type"))
"folder_lamp_type", config.child_value("folder_lamp_type")
)
configdict.replace_bool("is_tweet", config.child_value("is_tweet")) configdict.replace_bool("is_tweet", config.child_value("is_tweet"))
configdict.replace_bool( configdict.replace_bool("is_link_twitter", config.child_value("is_link_twitter"))
"is_link_twitter", config.child_value("is_link_twitter")
)
newprofile.replace_dict("config", configdict) newprofile.replace_dict("config", configdict)
# Save player custom settings # Save player custom settings
@ -905,31 +726,17 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
customdict.replace_int("st_obj_size", custom.child_value("st_obj_size")) customdict.replace_int("st_obj_size", custom.child_value("st_obj_size"))
customdict.replace_int("st_jr_gauge", custom.child_value("st_jr_gauge")) customdict.replace_int("st_jr_gauge", custom.child_value("st_jr_gauge"))
customdict.replace_int("st_clr_gauge", custom.child_value("st_clr_gauge")) customdict.replace_int("st_clr_gauge", custom.child_value("st_clr_gauge"))
customdict.replace_int( customdict.replace_int("st_gr_gauge_type", custom.child_value("st_gr_gauge_type"))
"st_gr_gauge_type", custom.child_value("st_gr_gauge_type") customdict.replace_int("voice_message_set", custom.child_value("voice_message_set"))
) customdict.replace_int("same_time_note_disp", custom.child_value("same_time_note_disp"))
customdict.replace_int( customdict.replace_int("st_score_disp_type", custom.child_value("st_score_disp_type"))
"voice_message_set", custom.child_value("voice_message_set")
)
customdict.replace_int(
"same_time_note_disp", custom.child_value("same_time_note_disp")
)
customdict.replace_int(
"st_score_disp_type", custom.child_value("st_score_disp_type")
)
customdict.replace_int("st_bonus_type", custom.child_value("st_bonus_type")) customdict.replace_int("st_bonus_type", custom.child_value("st_bonus_type"))
customdict.replace_int( customdict.replace_int("st_rivalnote_type", custom.child_value("st_rivalnote_type"))
"st_rivalnote_type", custom.child_value("st_rivalnote_type") customdict.replace_int("st_topassist_type", custom.child_value("st_topassist_type"))
)
customdict.replace_int(
"st_topassist_type", custom.child_value("st_topassist_type")
)
customdict.replace_int("high_speed", custom.child_value("high_speed")) customdict.replace_int("high_speed", custom.child_value("high_speed"))
customdict.replace_int("st_hazard", custom.child_value("st_hazard")) customdict.replace_int("st_hazard", custom.child_value("st_hazard"))
customdict.replace_int("st_clr_cond", custom.child_value("st_clr_cond")) customdict.replace_int("st_clr_cond", custom.child_value("st_clr_cond"))
customdict.replace_int( customdict.replace_int("voice_message_volume", custom.child_value("voice_message_volume"))
"voice_message_volume", custom.child_value("voice_message_volume")
)
newprofile.replace_dict("custom", customdict) newprofile.replace_dict("custom", customdict)
# Save player parameter info # Save player parameter info
@ -965,9 +772,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
# I assume this is copypasta, but I want to be sure # I assume this is copypasta, but I want to be sure
extid = child.child_value("user_id") extid = child.child_value("user_id")
if extid != newprofile.extid: if extid != newprofile.extid:
raise Exception( raise Exception(f"Unexpected user ID, got {extid} expecting {newprofile.extid}")
f"Unexpected user ID, got {extid} expecting {newprofile.extid}"
)
episode_type = child.child_value("type") episode_type = child.child_value("type")
episode_value0 = child.child_value("value0") episode_value0 = child.child_value("value0")
@ -1085,9 +890,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
continue continue
extid = child.child_value("id") extid = child.child_value("id")
other_userid = self.data.remote.user.from_extid( other_userid = self.data.remote.user.from_extid(self.game, self.version, extid)
self.game, self.version, extid
)
if other_userid is None: if other_userid is None:
continue continue
@ -1189,33 +992,17 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
) )
if total >= oldtotal: if total >= oldtotal:
mycoursedict.replace_int( mycoursedict.replace_int("music_id_1", mycourse.child_value("music_id_1"))
"music_id_1", mycourse.child_value("music_id_1") mycoursedict.replace_int("note_grade_1", mycourse.child_value("note_grade_1"))
)
mycoursedict.replace_int(
"note_grade_1", mycourse.child_value("note_grade_1")
)
mycoursedict.replace_int("score_1", score_1) mycoursedict.replace_int("score_1", score_1)
mycoursedict.replace_int( mycoursedict.replace_int("music_id_2", mycourse.child_value("music_id_2"))
"music_id_2", mycourse.child_value("music_id_2") mycoursedict.replace_int("note_grade_2", mycourse.child_value("note_grade_2"))
)
mycoursedict.replace_int(
"note_grade_2", mycourse.child_value("note_grade_2")
)
mycoursedict.replace_int("score_2", score_2) mycoursedict.replace_int("score_2", score_2)
mycoursedict.replace_int( mycoursedict.replace_int("music_id_3", mycourse.child_value("music_id_3"))
"music_id_3", mycourse.child_value("music_id_3") mycoursedict.replace_int("note_grade_3", mycourse.child_value("note_grade_3"))
)
mycoursedict.replace_int(
"note_grade_3", mycourse.child_value("note_grade_3")
)
mycoursedict.replace_int("score_3", score_3) mycoursedict.replace_int("score_3", score_3)
mycoursedict.replace_int( mycoursedict.replace_int("music_id_4", mycourse.child_value("music_id_4"))
"music_id_4", mycourse.child_value("music_id_4") mycoursedict.replace_int("note_grade_4", mycourse.child_value("note_grade_4"))
)
mycoursedict.replace_int(
"note_grade_4", mycourse.child_value("note_grade_4")
)
mycoursedict.replace_int("score_4", score_4) mycoursedict.replace_int("score_4", score_4)
mycoursedict.replace_int("insert_time", Time.now()) mycoursedict.replace_int("insert_time", Time.now())
newprofile.replace_dict("mycourse", mycoursedict) newprofile.replace_dict("mycourse", mycoursedict)

View File

@ -87,16 +87,11 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
) )
machine = self.data.local.machine.get_machine(self.config.machine.pcbid) machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None: if machine.arcade is not None:
lids = [ lids = [machine.id for machine in self.data.local.machine.get_all_machines(machine.arcade)]
machine.id
for machine in self.data.local.machine.get_all_machines(machine.arcade)
]
else: else:
lids = [machine.id] lids = [machine.id]
relevant_profiles = [ relevant_profiles = [profile for profile in all_profiles if profile[1].get_int("lid", -1) in lids]
profile for profile in all_profiles if profile[1].get_int("lid", -1) in lids
]
for rootnode, timeoffset in [ for rootnode, timeoffset in [
(today, 0), (today, 0),
@ -124,10 +119,7 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
scores_by_user[userid][attempt.id][attempt.chart] = attempt scores_by_user[userid][attempt.id][attempt.chart] = attempt
else: else:
# If this attempt is better than the stored one, replace it # If this attempt is better than the stored one, replace it
if ( if scores_by_user[userid][attempt.id][attempt.chart].points < attempt.points:
scores_by_user[userid][attempt.id][attempt.chart].points
< attempt.points
):
scores_by_user[userid][attempt.id][attempt.chart] = attempt scores_by_user[userid][attempt.id][attempt.chart] = attempt
# Calculate points earned by user in the day # Calculate points earned by user in the day
@ -136,27 +128,16 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
points_by_user[userid] = 0 points_by_user[userid] = 0
for mid in scores_by_user[userid]: for mid in scores_by_user[userid]:
for chart in scores_by_user[userid][mid]: for chart in scores_by_user[userid][mid]:
points_by_user[userid] = ( points_by_user[userid] = points_by_user[userid] + scores_by_user[userid][mid][chart].points
points_by_user[userid]
+ scores_by_user[userid][mid][chart].points
)
# Output that day's earned points # Output that day's earned points
for userid, profile in relevant_profiles: for userid, profile in relevant_profiles:
data = Node.void("data") data = Node.void("data")
rootnode.add_child(data) rootnode.add_child(data)
data.add_child( data.add_child(Node.s16("day_id", int((Time.now() - timeoffset) / Time.SECONDS_IN_DAY)))
Node.s16(
"day_id", int((Time.now() - timeoffset) / Time.SECONDS_IN_DAY)
)
)
data.add_child(Node.s32("user_id", profile.extid)) data.add_child(Node.s32("user_id", profile.extid))
data.add_child( data.add_child(Node.s16("icon_id", profile.get_dict("config").get_int("icon_id")))
Node.s16("icon_id", profile.get_dict("config").get_int("icon_id")) data.add_child(Node.s16("point", min(points_by_user.get(userid, 0), 32767)))
)
data.add_child(
Node.s16("point", min(points_by_user.get(userid, 0), 32767))
)
data.add_child(Node.s32("update_time", Time.now())) data.add_child(Node.s32("update_time", Time.now()))
data.add_child(Node.string("name", profile.get_str("name"))) data.add_child(Node.string("name", profile.get_str("name")))
@ -176,9 +157,7 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
ranking = Node.void("ranking") ranking = Node.void("ranking")
root.add_child(ranking) root.add_child(ranking)
def add_hitchart( def add_hitchart(name: str, start: int, end: int, hitchart: List[Tuple[int, int]]) -> None:
name: str, start: int, end: int, hitchart: List[Tuple[int, int]]
) -> None:
base = Node.void(name) base = Node.void(name)
ranking.add_child(base) ranking.add_child(base)
base.add_child(Node.s32("bt", start)) base.add_child(Node.s32("bt", start))
@ -261,17 +240,11 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
data.add_child( data.add_child(
Node.s8( Node.s8(
"clear_type", "clear_type",
self._db_to_game_clear_type( self._db_to_game_clear_type(score.data.get_int("clear_type")),
score.data.get_int("clear_type")
),
) )
) )
data.add_child(Node.s32("user_id", profile.extid)) data.add_child(Node.s32("user_id", profile.extid))
data.add_child( data.add_child(Node.s16("icon_id", profile.get_dict("config").get_int("icon_id")))
Node.s16(
"icon_id", profile.get_dict("config").get_int("icon_id")
)
)
data.add_child(Node.s32("score", score.points)) data.add_child(Node.s32("score", score.points))
data.add_child(Node.s32("time", score.timestamp)) data.add_child(Node.s32("time", score.timestamp))
data.add_child(Node.string("name", profile.get_str("name"))) data.add_child(Node.string("name", profile.get_str("name")))
@ -288,9 +261,7 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
userid = self.data.remote.user.from_extid(self.game, self.version, extid) userid = self.data.remote.user.from_extid(self.game, self.version, extid)
if userid is not None: if userid is not None:
profile = self.get_profile(userid) profile = self.get_profile(userid)
info = self.data.local.lobby.get_play_session_info( info = self.data.local.lobby.get_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
if profile is None or info is None: if profile is None or info is None:
return root return root
@ -369,9 +340,7 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
continue continue
profile = self.get_profile(user) profile = self.get_profile(user)
info = self.data.local.lobby.get_play_session_info( info = self.data.local.lobby.get_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
if profile is None or info is None: if profile is None or info is None:
# No profile info, don't return this lobby # No profile info, don't return this lobby
return root return root
@ -502,9 +471,7 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
) )
if lobby is not None: if lobby is not None:
self.data.local.lobby.destroy_lobby(lobby.get_int("id")) self.data.local.lobby.destroy_lobby(lobby.get_int("id"))
self.data.local.lobby.destroy_play_session_info( self.data.local.lobby.destroy_play_session_info(self.game, self.version, userid)
self.game, self.version, userid
)
return Node.void("player") return Node.void("player")

View File

@ -21,9 +21,7 @@ class SoundVoltexBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
CLEAR_TYPE_CLEAR: Final[int] = DBConstants.SDVX_CLEAR_TYPE_CLEAR CLEAR_TYPE_CLEAR: Final[int] = DBConstants.SDVX_CLEAR_TYPE_CLEAR
CLEAR_TYPE_HARD_CLEAR: Final[int] = DBConstants.SDVX_CLEAR_TYPE_HARD_CLEAR CLEAR_TYPE_HARD_CLEAR: Final[int] = DBConstants.SDVX_CLEAR_TYPE_HARD_CLEAR
CLEAR_TYPE_ULTIMATE_CHAIN: Final[int] = DBConstants.SDVX_CLEAR_TYPE_ULTIMATE_CHAIN CLEAR_TYPE_ULTIMATE_CHAIN: Final[int] = DBConstants.SDVX_CLEAR_TYPE_ULTIMATE_CHAIN
CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN: Final[ CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN: Final[int] = DBConstants.SDVX_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN
int
] = DBConstants.SDVX_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN
GRADE_NO_PLAY: Final[int] = DBConstants.SDVX_GRADE_NO_PLAY GRADE_NO_PLAY: Final[int] = DBConstants.SDVX_GRADE_NO_PLAY
GRADE_D: Final[int] = DBConstants.SDVX_GRADE_D GRADE_D: Final[int] = DBConstants.SDVX_GRADE_D
@ -68,9 +66,7 @@ class SoundVoltexBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# Now, return it # Now, return it
return self.format_profile(userid, profile) return self.format_profile(userid, profile)
def new_profile_by_refid( def new_profile_by_refid(self, refid: Optional[str], name: Optional[str], locid: Optional[int]) -> Node:
self, refid: Optional[str], name: Optional[str], locid: Optional[int]
) -> Node:
""" """
Given a RefID and an optional name, create a profile and then return Given a RefID and an optional name, create a profile and then return
a formatted profile node. Similar rationale to get_profile_by_refid. a formatted profile node. Similar rationale to get_profile_by_refid.
@ -103,9 +99,7 @@ class SoundVoltexBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
""" """
return Node.void("game") return Node.void("game")
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
""" """
Base handler for profile parsing. Given a request and an old profile, Base handler for profile parsing. Given a request and an old profile,
return a new profile that's been updated with the contents of the request. return a new profile that's been updated with the contents of the request.
@ -154,10 +148,7 @@ class SoundVoltexBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
# We saw an attempt, keep the total attempts in sync. # We saw an attempt, keep the total attempts in sync.
attempts[attempt.id][attempt.chart]["average"] = int( attempts[attempt.id][attempt.chart]["average"] = int(
( (
( (attempts[attempt.id][attempt.chart]["average"] * attempts[attempt.id][attempt.chart]["total"])
attempts[attempt.id][attempt.chart]["average"]
* attempts[attempt.id][attempt.chart]["total"]
)
+ attempt.points + attempt.points
) )
/ (attempts[attempt.id][attempt.chart]["total"] + 1) / (attempts[attempt.id][attempt.chart]["total"] + 1)
@ -187,12 +178,8 @@ class SoundVoltexBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
"average": 0, "average": 0,
} }
attempts[songid][songchart]["total"] += remote_attempts[songid][ attempts[songid][songchart]["total"] += remote_attempts[songid][songchart]["plays"]
songchart attempts[songid][songchart]["clears"] += remote_attempts[songid][songchart]["clears"]
]["plays"]
attempts[songid][songchart]["clears"] += remote_attempts[songid][
songchart
]["clears"]
return attempts return attempts
@ -267,9 +254,7 @@ class SoundVoltexBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
scoredata = oldscore.data scoredata = oldscore.data
# Replace clear type and grade # Replace clear type and grade
scoredata.replace_int( scoredata.replace_int("clear_type", max(scoredata.get_int("clear_type"), clear_type))
"clear_type", max(scoredata.get_int("clear_type"), clear_type)
)
history.replace_int("clear_type", clear_type) history.replace_int("clear_type", clear_type)
scoredata.replace_int("grade", max(scoredata.get_int("grade"), grade)) scoredata.replace_int("grade", max(scoredata.get_int("grade"), grade))
history.replace_int("grade", grade) history.replace_int("grade", grade)

View File

@ -227,10 +227,7 @@ class SoundVoltexBooth(
records_by_id[score.id][score.chart] = record records_by_id[score.id][score.chart] = record
missing_users.append(userid) missing_users.append(userid)
users = { users = {userid: profile for (userid, profile) in self.get_any_profiles(missing_users)}
userid: profile
for (userid, profile) in self.get_any_profiles(missing_users)
}
# Output records # Output records
for songid in records_by_id: for songid in records_by_id:
@ -492,22 +489,16 @@ class SoundVoltexBooth(
return game return game
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Update experience and in-game currencies # Update experience and in-game currencies
earned_gamecoin_packet = request.child_value("earned_gamecoin_packet") earned_gamecoin_packet = request.child_value("earned_gamecoin_packet")
if earned_gamecoin_packet is not None: if earned_gamecoin_packet is not None:
newprofile.replace_int( newprofile.replace_int("packet", newprofile.get_int("packet") + earned_gamecoin_packet)
"packet", newprofile.get_int("packet") + earned_gamecoin_packet
)
earned_gamecoin_block = request.child_value("earned_gamecoin_block") earned_gamecoin_block = request.child_value("earned_gamecoin_block")
if earned_gamecoin_block is not None: if earned_gamecoin_block is not None:
newprofile.replace_int( newprofile.replace_int("block", newprofile.get_int("block") + earned_gamecoin_block)
"block", newprofile.get_int("block") + earned_gamecoin_block
)
gain_exp = request.child_value("gain_exp") gain_exp = request.child_value("gain_exp")
if gain_exp is not None: if gain_exp is not None:
newprofile.replace_int("exp", newprofile.get_int("exp") + gain_exp) newprofile.replace_int("exp", newprofile.get_int("exp") + gain_exp)
@ -520,15 +511,11 @@ class SoundVoltexBooth(
if not game_config.get_bool("force_unlock_cards"): if not game_config.get_bool("force_unlock_cards"):
have_item = request.child_value("have_item") have_item = request.child_value("have_item")
if have_item is not None: if have_item is not None:
newprofile.replace_int_array( newprofile.replace_int_array("have_item", 512, [1 if x else 0 for x in have_item])
"have_item", 512, [1 if x else 0 for x in have_item]
)
if not game_config.get_bool("force_unlock_songs"): if not game_config.get_bool("force_unlock_songs"):
have_note = request.child_value("have_note") have_note = request.child_value("have_note")
if have_note is not None: if have_note is not None:
newprofile.replace_int_array( newprofile.replace_int_array("have_note", 512, [1 if x else 0 for x in have_note])
"have_note", 512, [1 if x else 0 for x in have_note]
)
# Grab last information. # Grab last information.
lastdict = newprofile.get_dict("last") lastdict = newprofile.get_dict("last")

View File

@ -204,9 +204,7 @@ class SoundVoltexGravityWars(
courses = self._get_skill_analyzer_courses() courses = self._get_skill_analyzer_courses()
max_level: Dict[int, int] = {} max_level: Dict[int, int] = {}
for course in courses: for course in courses:
max_level[course["level"]] = max( max_level[course["level"]] = max(course["season_id"], max_level.get(course["level"], -1))
course["season_id"], max_level.get(course["level"], -1)
)
for course in courses: for course in courses:
info = Node.void("info") info = Node.void("info")
skill_course.add_child(info) skill_course.add_child(info)
@ -214,11 +212,7 @@ class SoundVoltexGravityWars(
info.add_child(Node.s16("level", course["level"])) info.add_child(Node.s16("level", course["level"]))
info.add_child(Node.s32("season_id", course["season_id"])) info.add_child(Node.s32("season_id", course["season_id"]))
info.add_child(Node.string("season_name", seasons[course["season_id"]])) info.add_child(Node.string("season_name", seasons[course["season_id"]]))
info.add_child( info.add_child(Node.bool("season_new_flg", max_level[course["level"]] == course["season_id"]))
Node.bool(
"season_new_flg", max_level[course["level"]] == course["season_id"]
)
)
info.add_child( info.add_child(
Node.string( Node.string(
"course_name", "course_name",
@ -226,14 +220,8 @@ class SoundVoltexGravityWars(
) )
) )
info.add_child(Node.s16("course_type", 0)) info.add_child(Node.s16("course_type", 0))
info.add_child( info.add_child(Node.s16("skill_name_id", course.get("skill_name_id", course["level"])))
Node.s16("skill_name_id", course.get("skill_name_id", course["level"])) info.add_child(Node.bool("matching_assist", course["level"] >= 0 and course["level"] <= 6))
)
info.add_child(
Node.bool(
"matching_assist", course["level"] >= 0 and course["level"] <= 6
)
)
info.add_child(Node.s16("gauge_type", self.GAME_GAUGE_TYPE_SKILL)) info.add_child(Node.s16("gauge_type", self.GAME_GAUGE_TYPE_SKILL))
info.add_child(Node.s16("paseli_type", 0)) info.add_child(Node.s16("paseli_type", 0))
@ -464,11 +452,7 @@ class SoundVoltexGravityWars(
self.__db_to_game_clear_type(score.data.get_int("clear_type")), self.__db_to_game_clear_type(score.data.get_int("clear_type")),
) )
) )
music.add_child( music.add_child(Node.u32("score_grade", self.__db_to_game_grade(score.data.get_int("grade"))))
Node.u32(
"score_grade", self.__db_to_game_grade(score.data.get_int("grade"))
)
)
stats = score.data.get_dict("stats") stats = score.data.get_dict("stats")
music.add_child(Node.u32("btn_rate", stats.get_int("btn_rate"))) music.add_child(Node.u32("btn_rate", stats.get_int("btn_rate")))
music.add_child(Node.u32("long_rate", stats.get_int("long_rate"))) music.add_child(Node.u32("long_rate", stats.get_int("long_rate")))

View File

@ -3063,10 +3063,7 @@ class SoundVoltexGravityWarsSeason1(
# Now, grab user records # Now, grab user records
records = self.data.remote.music.get_all_records(self.game, self.version) records = self.data.remote.music.get_all_records(self.game, self.version)
missing_users = [userid for (userid, _) in records] missing_users = [userid for (userid, _) in records]
users = { users = {userid: profile for (userid, profile) in self.get_any_profiles(missing_users)}
userid: profile
for (userid, profile) in self.get_any_profiles(missing_users)
}
hiscore_allover = Node.void("hiscore_allover") hiscore_allover = Node.void("hiscore_allover")
game.add_child(hiscore_allover) game.add_child(hiscore_allover)
@ -3091,14 +3088,10 @@ class SoundVoltexGravityWarsSeason1(
# Now, grab local records # Now, grab local records
area_users = [ area_users = [
uid uid
for (uid, prof) in self.data.local.user.get_all_profiles( for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version)
self.game, self.version
)
if prof.get_int("loc", -1) == locid if prof.get_int("loc", -1) == locid
] ]
records = self.data.local.music.get_all_records( records = self.data.local.music.get_all_records(self.game, self.version, userlist=area_users)
self.game, self.version, userlist=area_users
)
missing_users = [userid for (userid, _) in records if userid not in users] missing_users = [userid for (userid, _) in records if userid not in users]
for userid, profile in self.get_any_profiles(missing_users): for userid, profile in self.get_any_profiles(missing_users):
users[userid] = profile users[userid] = profile
@ -3131,9 +3124,7 @@ class SoundVoltexGravityWarsSeason1(
for songid in clears: for songid in clears:
for chart in clears[songid]: for chart in clears[songid]:
if clears[songid][chart]["total"] > 0: if clears[songid][chart]["total"] > 0:
rate = float(clears[songid][chart]["clears"]) / float( rate = float(clears[songid][chart]["clears"]) / float(clears[songid][chart]["total"])
clears[songid][chart]["total"]
)
dnode = Node.void("d") dnode = Node.void("d")
clear_rate.add_child(dnode) clear_rate.add_child(dnode)
dnode.add_child(Node.u32("id", songid)) dnode.add_child(Node.u32("id", songid))
@ -3151,9 +3142,7 @@ class SoundVoltexGravityWarsSeason1(
game.add_child(Node.u32("gamecoin_packet", profile.get_int("packet"))) game.add_child(Node.u32("gamecoin_packet", profile.get_int("packet")))
game.add_child(Node.u32("gamecoin_block", profile.get_int("block"))) game.add_child(Node.u32("gamecoin_block", profile.get_int("block")))
game.add_child(Node.s16("skill_name_id", profile.get_int("skill_name_id", -1))) game.add_child(Node.s16("skill_name_id", profile.get_int("skill_name_id", -1)))
game.add_child( game.add_child(Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20)))
Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20))
)
game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy"))) game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy")))
game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count"))) game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count")))
@ -3182,25 +3171,17 @@ class SoundVoltexGravityWarsSeason1(
game.add_child(itemnode) game.add_child(itemnode)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for item in achievements: for item in achievements:
if item.type[:5] != "item_": if item.type[:5] != "item_":
continue continue
itemtype = int(item.type[5:]) itemtype = int(item.type[5:])
if ( if game_config.get_bool("force_unlock_songs") and itemtype == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and itemtype == self.GAME_CATALOG_TYPE_SONG
):
# Don't echo unlocked songs, we will add all of them later # Don't echo unlocked songs, we will add all of them later
continue continue
if ( if game_config.get_bool("force_unlock_cards") and itemtype == self.GAME_CATALOG_TYPE_APPEAL_CARD:
game_config.get_bool("force_unlock_cards")
and itemtype == self.GAME_CATALOG_TYPE_APPEAL_CARD
):
# Don't echo unlocked appeal cards, we will add all of them later # Don't echo unlocked appeal cards, we will add all of them later
continue continue
@ -3274,30 +3255,22 @@ class SoundVoltexGravityWarsSeason1(
storynode.add_child(info) storynode.add_child(info)
info.add_child(Node.s32("story_id", story.id)) info.add_child(Node.s32("story_id", story.id))
info.add_child(Node.s32("progress_id", story.data.get_int("progress_id"))) info.add_child(Node.s32("progress_id", story.data.get_int("progress_id")))
info.add_child( info.add_child(Node.s32("progress_param", story.data.get_int("progress_param")))
Node.s32("progress_param", story.data.get_int("progress_param"))
)
info.add_child(Node.s32("clear_cnt", story.data.get_int("clear_cnt"))) info.add_child(Node.s32("clear_cnt", story.data.get_int("clear_cnt")))
info.add_child(Node.u32("route_flg", story.data.get_int("route_flg"))) info.add_child(Node.u32("route_flg", story.data.get_int("route_flg")))
return game return game
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies # Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value("earned_gamecoin_packet") earned_gamecoin_packet = request.child_value("earned_gamecoin_packet")
if earned_gamecoin_packet is not None: if earned_gamecoin_packet is not None:
newprofile.replace_int( newprofile.replace_int("packet", newprofile.get_int("packet") + earned_gamecoin_packet)
"packet", newprofile.get_int("packet") + earned_gamecoin_packet
)
earned_gamecoin_block = request.child_value("earned_gamecoin_block") earned_gamecoin_block = request.child_value("earned_gamecoin_block")
if earned_gamecoin_block is not None: if earned_gamecoin_block is not None:
newprofile.replace_int( newprofile.replace_int("block", newprofile.get_int("block") + earned_gamecoin_block)
"block", newprofile.get_int("block") + earned_gamecoin_block
)
earned_blaster_energy = request.child_value("earned_blaster_energy") earned_blaster_energy = request.child_value("earned_blaster_energy")
if earned_blaster_energy is not None: if earned_blaster_energy is not None:
newprofile.replace_int( newprofile.replace_int(
@ -3308,9 +3281,7 @@ class SoundVoltexGravityWarsSeason1(
# Miscelaneous stuff # Miscelaneous stuff
newprofile.replace_int("blaster_count", request.child_value("blaster_count")) newprofile.replace_int("blaster_count", request.child_value("blaster_count"))
newprofile.replace_int("skill_name_id", request.child_value("skill_name_id")) newprofile.replace_int("skill_name_id", request.child_value("skill_name_id"))
newprofile.replace_int_array( newprofile.replace_int_array("hidden_param", 20, request.child_value("hidden_param"))
"hidden_param", 20, request.child_value("hidden_param")
)
# Update user's unlock status if we aren't force unlocked # Update user's unlock status if we aren't force unlocked
game_config = self.get_game_config() game_config = self.get_game_config()
@ -3324,22 +3295,13 @@ class SoundVoltexGravityWarsSeason1(
item_type = child.child_value("type") item_type = child.child_value("type")
param = child.child_value("param") param = child.child_value("param")
if ( if game_config.get_bool("force_unlock_cards") and item_type == self.GAME_CATALOG_TYPE_APPEAL_CARD:
game_config.get_bool("force_unlock_cards")
and item_type == self.GAME_CATALOG_TYPE_APPEAL_CARD
):
# Don't save back appeal cards because they were force unlocked # Don't save back appeal cards because they were force unlocked
continue continue
if ( if game_config.get_bool("force_unlock_songs") and item_type == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and item_type == self.GAME_CATALOG_TYPE_SONG
):
# Don't save back songs, because they were force unlocked # Don't save back songs, because they were force unlocked
continue continue
if ( if game_config.get_bool("force_unlock_crew") and item_type == self.GAME_CATALOG_TYPE_CREW:
game_config.get_bool("force_unlock_crew")
and item_type == self.GAME_CATALOG_TYPE_CREW
):
# Don't save back crew, because they were force unlocked # Don't save back crew, because they were force unlocked
continue continue

View File

@ -3850,22 +3850,15 @@ class SoundVoltexGravityWarsSeason2(
# Now, grab global and local scores as well as clear rates # Now, grab global and local scores as well as clear rates
global_records = self.data.remote.music.get_all_records(self.game, self.version) global_records = self.data.remote.music.get_all_records(self.game, self.version)
users = { users = {uid: prof for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version)}
uid: prof
for (uid, prof) in self.data.local.user.get_all_profiles(
self.game, self.version
)
}
area_users = [uid for uid in users if users[uid].get_int("loc", -1) == locid] area_users = [uid for uid in users if users[uid].get_int("loc", -1) == locid]
area_records = self.data.local.music.get_all_records( area_records = self.data.local.music.get_all_records(self.game, self.version, userlist=area_users)
self.game, self.version, userlist=area_users
)
clears = self.get_clear_rates() clears = self.get_clear_rates()
records: Dict[int, Dict[int, Dict[str, Tuple[UserID, Score]]]] = {} records: Dict[int, Dict[int, Dict[str, Tuple[UserID, Score]]]] = {}
missing_users = [ missing_users = [userid for (userid, _) in global_records if userid not in users] + [
userid for (userid, _) in global_records if userid not in users userid for (userid, _) in area_records if userid not in users
] + [userid for (userid, _) in area_records if userid not in users] ]
for userid, profile in self.get_any_profiles(missing_users): for userid, profile in self.get_any_profiles(missing_users):
users[userid] = profile users[userid] = profile
@ -3896,9 +3889,7 @@ class SoundVoltexGravityWarsSeason2(
global_profile = users[globaluserid] global_profile = users[globaluserid]
if clears[musicid][chart]["total"] > 0: if clears[musicid][chart]["total"] > 0:
clear_rate = float(clears[musicid][chart]["clears"]) / float( clear_rate = float(clears[musicid][chart]["clears"]) / float(clears[musicid][chart]["total"])
clears[musicid][chart]["total"]
)
else: else:
clear_rate = 0.0 clear_rate = 0.0
@ -3906,9 +3897,7 @@ class SoundVoltexGravityWarsSeason2(
highscores.add_child(info) highscores.add_child(info)
info.add_child(Node.u32("id", musicid)) info.add_child(Node.u32("id", musicid))
info.add_child(Node.u32("ty", chart)) info.add_child(Node.u32("ty", chart))
info.add_child( info.add_child(Node.string("a_sq", ID.format_extid(global_profile.extid)))
Node.string("a_sq", ID.format_extid(global_profile.extid))
)
info.add_child(Node.string("a_nm", global_profile.get_str("name"))) info.add_child(Node.string("a_nm", global_profile.get_str("name")))
info.add_child(Node.u32("a_sc", globalscore.points)) info.add_child(Node.u32("a_sc", globalscore.points))
info.add_child(Node.s32("cr", int(clear_rate * 10000))) info.add_child(Node.s32("cr", int(clear_rate * 10000)))
@ -3916,9 +3905,7 @@ class SoundVoltexGravityWarsSeason2(
if "area" in records[musicid][chart]: if "area" in records[musicid][chart]:
(localuserid, localscore) = records[musicid][chart]["area"] (localuserid, localscore) = records[musicid][chart]["area"]
local_profile = users[localuserid] local_profile = users[localuserid]
info.add_child( info.add_child(Node.string("l_sq", ID.format_extid(local_profile.extid)))
Node.string("l_sq", ID.format_extid(local_profile.extid))
)
info.add_child(Node.string("l_nm", local_profile.get_str("name"))) info.add_child(Node.string("l_nm", local_profile.get_str("name")))
info.add_child(Node.u32("l_sc", localscore.points)) info.add_child(Node.u32("l_sc", localscore.points))
@ -3946,15 +3933,11 @@ class SoundVoltexGravityWarsSeason2(
rival = Node.void("rival") rival = Node.void("rival")
game.add_child(rival) game.add_child(rival)
rival.add_child(Node.s16("no", index)) rival.add_child(Node.s16("no", index))
rival.add_child( rival.add_child(Node.string("seq", ID.format_extid(other_profile.extid)))
Node.string("seq", ID.format_extid(other_profile.extid))
)
rival.add_child(Node.string("name", other_profile.get_str("name"))) rival.add_child(Node.string("name", other_profile.get_str("name")))
# Return scores for this user on random charts # Return scores for this user on random charts
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.version, link.other_userid)
self.game, self.version, link.other_userid
)
for score in scores: for score in scores:
music = Node.void("music") music = Node.void("music")
rival.add_child(music) rival.add_child(music)
@ -3975,14 +3958,10 @@ class SoundVoltexGravityWarsSeason2(
game.add_child( game.add_child(
Node.s16( Node.s16(
"skill_name_id", "skill_name_id",
profile.get_int( profile.get_int("chosen_skill_id", profile.get_int("skill_name_id", -1)),
"chosen_skill_id", profile.get_int("skill_name_id", -1)
),
) )
) )
game.add_child( game.add_child(Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20)))
Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20))
)
game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy"))) game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy")))
game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count"))) game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count")))
@ -4011,31 +3990,20 @@ class SoundVoltexGravityWarsSeason2(
game.add_child(itemnode) game.add_child(itemnode)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for item in achievements: for item in achievements:
if item.type[:5] != "item_": if item.type[:5] != "item_":
continue continue
itemtype = int(item.type[5:]) itemtype = int(item.type[5:])
if ( if game_config.get_bool("force_unlock_songs") and itemtype == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and itemtype == self.GAME_CATALOG_TYPE_SONG
):
# Don't echo unlocked songs, we will add all of them later # Don't echo unlocked songs, we will add all of them later
continue continue
if ( if game_config.get_bool("force_unlock_cards") and itemtype == self.GAME_CATALOG_TYPE_APPEAL_CARD:
game_config.get_bool("force_unlock_cards")
and itemtype == self.GAME_CATALOG_TYPE_APPEAL_CARD
):
# Don't echo unlocked appeal cards, we will add all of them later # Don't echo unlocked appeal cards, we will add all of them later
continue continue
if ( if game_config.get_bool("force_unlock_crew") and itemtype == self.GAME_CATALOG_TYPE_CREW:
game_config.get_bool("force_unlock_crew")
and itemtype == self.GAME_CATALOG_TYPE_CREW
):
# Don't echo unlocked crew, we will add all of them later # Don't echo unlocked crew, we will add all of them later
continue continue
@ -4104,8 +4072,7 @@ class SoundVoltexGravityWarsSeason2(
courselist = [ courselist = [
c c
for c in self._get_skill_analyzer_courses() for c in self._get_skill_analyzer_courses()
if c.get("id", c["level"]) == course_id if c.get("id", c["level"]) == course_id and c["season_id"] == season_id
and c["season_id"] == season_id
] ]
if len(courselist) > 0: if len(courselist) > 0:
skill_level = max(skill_level, courselist[0]["level"]) skill_level = max(skill_level, courselist[0]["level"])
@ -4132,9 +4099,7 @@ class SoundVoltexGravityWarsSeason2(
storynode.add_child(info) storynode.add_child(info)
info.add_child(Node.s32("story_id", story.id)) info.add_child(Node.s32("story_id", story.id))
info.add_child(Node.s32("progress_id", story.data.get_int("progress_id"))) info.add_child(Node.s32("progress_id", story.data.get_int("progress_id")))
info.add_child( info.add_child(Node.s32("progress_param", story.data.get_int("progress_param")))
Node.s32("progress_param", story.data.get_int("progress_param"))
)
info.add_child(Node.s32("clear_cnt", story.data.get_int("clear_cnt"))) info.add_child(Node.s32("clear_cnt", story.data.get_int("clear_cnt")))
info.add_child(Node.u32("route_flg", story.data.get_int("route_flg"))) info.add_child(Node.u32("route_flg", story.data.get_int("route_flg")))
@ -4157,22 +4122,16 @@ class SoundVoltexGravityWarsSeason2(
return game return game
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies # Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value("earned_gamecoin_packet") earned_gamecoin_packet = request.child_value("earned_gamecoin_packet")
if earned_gamecoin_packet is not None: if earned_gamecoin_packet is not None:
newprofile.replace_int( newprofile.replace_int("packet", newprofile.get_int("packet") + earned_gamecoin_packet)
"packet", newprofile.get_int("packet") + earned_gamecoin_packet
)
earned_gamecoin_block = request.child_value("earned_gamecoin_block") earned_gamecoin_block = request.child_value("earned_gamecoin_block")
if earned_gamecoin_block is not None: if earned_gamecoin_block is not None:
newprofile.replace_int( newprofile.replace_int("block", newprofile.get_int("block") + earned_gamecoin_block)
"block", newprofile.get_int("block") + earned_gamecoin_block
)
earned_blaster_energy = request.child_value("earned_blaster_energy") earned_blaster_energy = request.child_value("earned_blaster_energy")
if earned_blaster_energy is not None: if earned_blaster_energy is not None:
newprofile.replace_int( newprofile.replace_int(
@ -4183,9 +4142,7 @@ class SoundVoltexGravityWarsSeason2(
# Miscelaneous stuff # Miscelaneous stuff
newprofile.replace_int("blaster_count", request.child_value("blaster_count")) newprofile.replace_int("blaster_count", request.child_value("blaster_count"))
newprofile.replace_int("chosen_skill_id", request.child_value("skill_name_id")) newprofile.replace_int("chosen_skill_id", request.child_value("skill_name_id"))
newprofile.replace_int_array( newprofile.replace_int_array("hidden_param", 20, request.child_value("hidden_param"))
"hidden_param", 20, request.child_value("hidden_param")
)
# Update user's unlock status if we aren't force unlocked # Update user's unlock status if we aren't force unlocked
game_config = self.get_game_config() game_config = self.get_game_config()
@ -4199,22 +4156,13 @@ class SoundVoltexGravityWarsSeason2(
item_type = child.child_value("type") item_type = child.child_value("type")
param = child.child_value("param") param = child.child_value("param")
if ( if game_config.get_bool("force_unlock_cards") and item_type == self.GAME_CATALOG_TYPE_APPEAL_CARD:
game_config.get_bool("force_unlock_cards")
and item_type == self.GAME_CATALOG_TYPE_APPEAL_CARD
):
# Don't save back appeal cards because they were force unlocked # Don't save back appeal cards because they were force unlocked
continue continue
if ( if game_config.get_bool("force_unlock_songs") and item_type == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and item_type == self.GAME_CATALOG_TYPE_SONG
):
# Don't save back songs, because they were force unlocked # Don't save back songs, because they were force unlocked
continue continue
if ( if game_config.get_bool("force_unlock_crew") and item_type == self.GAME_CATALOG_TYPE_CREW:
game_config.get_bool("force_unlock_crew")
and item_type == self.GAME_CATALOG_TYPE_CREW
):
# Don't save back crew, because they were force unlocked # Don't save back crew, because they were force unlocked
continue continue

View File

@ -68,9 +68,7 @@ class SoundVoltexHeavenlyHaven(
GAME_SKILL_NAME_ID_BMK2017: Final[int] = 19 GAME_SKILL_NAME_ID_BMK2017: Final[int] = 19
GAME_SKILL_NAME_ID_KAC_7TH_TIGER: Final[int] = 20 GAME_SKILL_NAME_ID_KAC_7TH_TIGER: Final[int] = 20
GAME_SKILL_NAME_ID_KAC_7TH_WOLF: Final[int] = 21 GAME_SKILL_NAME_ID_KAC_7TH_WOLF: Final[int] = 21
GAME_SKILL_NAME_ID_RIKKA: Final[ GAME_SKILL_NAME_ID_RIKKA: Final[int] = 22 # For the course that ran from 1/18/2018-2/18/2018
int
] = 22 # For the course that ran from 1/18/2018-2/18/2018
GAME_SKILL_NAME_ID_KAC_8TH: Final[int] = 23 GAME_SKILL_NAME_ID_KAC_8TH: Final[int] = 23
# Return the local2 service so that SDVX 4 and above will send certain packets. # Return the local2 service so that SDVX 4 and above will send certain packets.
@ -3336,9 +3334,7 @@ class SoundVoltexHeavenlyHaven(
skill_course = Node.void("skill_course") skill_course = Node.void("skill_course")
game.add_child(skill_course) game.add_child(skill_course)
achievements = self.data.local.user.get_all_achievements( achievements = self.data.local.user.get_all_achievements(self.game, self.version, achievementtype="course")
self.game, self.version, achievementtype="course"
)
courserates: Dict[Tuple[int, int], Dict[str, int]] = {} courserates: Dict[Tuple[int, int], Dict[str, int]] = {}
def getrates(season_id: int, course_id: int) -> Dict[str, int]: def getrates(season_id: int, course_id: int) -> Dict[str, int]:
@ -3372,14 +3368,8 @@ class SoundVoltexHeavenlyHaven(
info.add_child(Node.s32("season_id", course["season_id"])) info.add_child(Node.s32("season_id", course["season_id"]))
info.add_child(Node.string("season_name", seasons[course["season_id"]])) info.add_child(Node.string("season_name", seasons[course["season_id"]]))
info.add_child( info.add_child(Node.bool("season_new_flg", course["season_id"] in {10, 11, 12, 22, 23}))
Node.bool("season_new_flg", course["season_id"] in {10, 11, 12, 22, 23}) info.add_child(Node.s16("course_id", course.get("course_id", course.get("skill_level", -1))))
)
info.add_child(
Node.s16(
"course_id", course.get("course_id", course.get("skill_level", -1))
)
)
info.add_child( info.add_child(
Node.string( Node.string(
"course_name", "course_name",
@ -3409,8 +3399,7 @@ class SoundVoltexHeavenlyHaven(
info.add_child( info.add_child(
Node.bool( Node.bool(
"matching_assist", "matching_assist",
course.get("skill_level", -1) >= 1 course.get("skill_level", -1) >= 1 and course.get("skill_level", -1) <= 7,
and course.get("skill_level", -1) <= 7,
) )
) )
@ -3420,14 +3409,8 @@ class SoundVoltexHeavenlyHaven(
course.get("course_id", course.get("skill_level", -1)), course.get("course_id", course.get("skill_level", -1)),
) )
if rate["attempts"] > 0: if rate["attempts"] > 0:
info.add_child( info.add_child(Node.s32("clear_rate", int(100.0 * (rate["clears"] / rate["attempts"]))))
Node.s32( info.add_child(Node.u32("avg_score", rate["total_score"] // rate["attempts"]))
"clear_rate", int(100.0 * (rate["clears"] / rate["attempts"]))
)
)
info.add_child(
Node.u32("avg_score", rate["total_score"] // rate["attempts"])
)
else: else:
info.add_child(Node.s32("clear_rate", 0)) info.add_child(Node.s32("clear_rate", 0))
info.add_child(Node.u32("avg_score", 0)) info.add_child(Node.u32("avg_score", 0))
@ -3461,22 +3444,15 @@ class SoundVoltexHeavenlyHaven(
# Now, grab global and local scores as well as clear rates # Now, grab global and local scores as well as clear rates
global_records = self.data.remote.music.get_all_records(self.game, self.version) global_records = self.data.remote.music.get_all_records(self.game, self.version)
users = { users = {uid: prof for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version)}
uid: prof
for (uid, prof) in self.data.local.user.get_all_profiles(
self.game, self.version
)
}
area_users = [uid for uid in users if users[uid].get_int("loc", -1) == locid] area_users = [uid for uid in users if users[uid].get_int("loc", -1) == locid]
area_records = self.data.local.music.get_all_records( area_records = self.data.local.music.get_all_records(self.game, self.version, userlist=area_users)
self.game, self.version, userlist=area_users
)
clears = self.get_clear_rates() clears = self.get_clear_rates()
records: Dict[int, Dict[int, Dict[str, Tuple[UserID, Score]]]] = {} records: Dict[int, Dict[int, Dict[str, Tuple[UserID, Score]]]] = {}
missing_users = [ missing_users = [userid for (userid, _) in global_records if userid not in users] + [
userid for (userid, _) in global_records if userid not in users userid for (userid, _) in area_records if userid not in users
] + [userid for (userid, _) in area_records if userid not in users] ]
for userid, profile in self.get_any_profiles(missing_users): for userid, profile in self.get_any_profiles(missing_users):
users[userid] = profile users[userid] = profile
@ -3507,9 +3483,7 @@ class SoundVoltexHeavenlyHaven(
global_profile = users[globaluserid] global_profile = users[globaluserid]
if clears[musicid][chart]["total"] > 0: if clears[musicid][chart]["total"] > 0:
clear_rate = float(clears[musicid][chart]["clears"]) / float( clear_rate = float(clears[musicid][chart]["clears"]) / float(clears[musicid][chart]["total"])
clears[musicid][chart]["total"]
)
else: else:
clear_rate = 0.0 clear_rate = 0.0
@ -3517,9 +3491,7 @@ class SoundVoltexHeavenlyHaven(
highscores.add_child(info) highscores.add_child(info)
info.add_child(Node.u32("id", musicid)) info.add_child(Node.u32("id", musicid))
info.add_child(Node.u32("ty", chart)) info.add_child(Node.u32("ty", chart))
info.add_child( info.add_child(Node.string("a_sq", ID.format_extid(global_profile.extid)))
Node.string("a_sq", ID.format_extid(global_profile.extid))
)
info.add_child(Node.string("a_nm", global_profile.get_str("name"))) info.add_child(Node.string("a_nm", global_profile.get_str("name")))
info.add_child(Node.u32("a_sc", globalscore.points)) info.add_child(Node.u32("a_sc", globalscore.points))
info.add_child(Node.s32("cr", int(clear_rate * 10000))) info.add_child(Node.s32("cr", int(clear_rate * 10000)))
@ -3528,9 +3500,7 @@ class SoundVoltexHeavenlyHaven(
if "area" in records[musicid][chart]: if "area" in records[musicid][chart]:
(localuserid, localscore) = records[musicid][chart]["area"] (localuserid, localscore) = records[musicid][chart]["area"]
local_profile = users[localuserid] local_profile = users[localuserid]
info.add_child( info.add_child(Node.string("l_sq", ID.format_extid(local_profile.extid)))
Node.string("l_sq", ID.format_extid(local_profile.extid))
)
info.add_child(Node.string("l_nm", local_profile.get_str("name"))) info.add_child(Node.string("l_nm", local_profile.get_str("name")))
info.add_child(Node.u32("l_sc", localscore.points)) info.add_child(Node.u32("l_sc", localscore.points))
@ -3655,18 +3625,14 @@ class SoundVoltexHeavenlyHaven(
rival = Node.void("rival") rival = Node.void("rival")
game.add_child(rival) game.add_child(rival)
rival.add_child(Node.s16("no", index)) rival.add_child(Node.s16("no", index))
rival.add_child( rival.add_child(Node.string("seq", ID.format_extid(other_profile.extid)))
Node.string("seq", ID.format_extid(other_profile.extid))
)
rival.add_child(Node.string("name", other_profile.get_str("name"))) rival.add_child(Node.string("name", other_profile.get_str("name")))
# Keep track of index # Keep track of index
index = index + 1 index = index + 1
# Return scores for this user on random charts # Return scores for this user on random charts
scores = self.data.remote.music.get_scores( scores = self.data.remote.music.get_scores(self.game, self.version, link.other_userid)
self.game, self.version, link.other_userid
)
for score in scores: for score in scores:
music = Node.void("music") music = Node.void("music")
rival.add_child(music) rival.add_child(music)
@ -3677,9 +3643,7 @@ class SoundVoltexHeavenlyHaven(
score.id, score.id,
score.chart, score.chart,
score.points, score.points,
self.__db_to_game_clear_type( self.__db_to_game_clear_type(score.data.get_int("clear_type")),
score.data.get_int("clear_type")
),
self.__db_to_game_grade(score.data.get_int("grade")), self.__db_to_game_grade(score.data.get_int("grade")),
], ],
) )
@ -3956,31 +3920,20 @@ class SoundVoltexHeavenlyHaven(
game.add_child(itemnode) game.add_child(itemnode)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for item in achievements: for item in achievements:
if item.type[:5] != "item_": if item.type[:5] != "item_":
continue continue
itemtype = int(item.type[5:]) itemtype = int(item.type[5:])
if ( if game_config.get_bool("force_unlock_songs") and itemtype == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and itemtype == self.GAME_CATALOG_TYPE_SONG
):
# Don't echo unlocked songs, we will add all of them later # Don't echo unlocked songs, we will add all of them later
continue continue
if ( if game_config.get_bool("force_unlock_cards") and itemtype == self.GAME_CATALOG_TYPE_APPEAL_CARD:
game_config.get_bool("force_unlock_cards")
and itemtype == self.GAME_CATALOG_TYPE_APPEAL_CARD
):
# Don't echo unlocked appeal cards, we will add all of them later # Don't echo unlocked appeal cards, we will add all of them later
continue continue
if ( if game_config.get_bool("force_unlock_crew") and itemtype == self.GAME_CATALOG_TYPE_CREW:
game_config.get_bool("force_unlock_crew")
and itemtype == self.GAME_CATALOG_TYPE_CREW
):
# Don't echo unlocked crew, we will add all of them later # Don't echo unlocked crew, we will add all of them later
continue continue
@ -4047,8 +4000,7 @@ class SoundVoltexHeavenlyHaven(
courselist = [ courselist = [
c c
for c in self.__get_skill_analyzer_courses() for c in self.__get_skill_analyzer_courses()
if c.get("course_id", c.get("skill_level", -1)) == course_id if c.get("course_id", c.get("skill_level", -1)) == course_id and c["season_id"] == season_id
and c["season_id"] == season_id
] ]
if len(courselist) > 0: if len(courselist) > 0:
skill_level = max(skill_level, courselist[0]["skill_level"]) skill_level = max(skill_level, courselist[0]["skill_level"])
@ -4060,9 +4012,7 @@ class SoundVoltexHeavenlyHaven(
course_node.add_child(Node.s32("sc", course.data.get_int("score"))) course_node.add_child(Node.s32("sc", course.data.get_int("score")))
course_node.add_child(Node.s16("ct", course.data.get_int("clear_type"))) course_node.add_child(Node.s16("ct", course.data.get_int("clear_type")))
course_node.add_child(Node.s16("gr", course.data.get_int("grade"))) course_node.add_child(Node.s16("gr", course.data.get_int("grade")))
course_node.add_child( course_node.add_child(Node.s16("ar", course.data.get_int("achievement_rate")))
Node.s16("ar", course.data.get_int("achievement_rate"))
)
course_node.add_child(Node.s16("cnt", 1)) course_node.add_child(Node.s16("cnt", 1))
# Calculated skill level # Calculated skill level
@ -4104,22 +4054,16 @@ class SoundVoltexHeavenlyHaven(
return game return game
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies # Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value("earned_gamecoin_packet") earned_gamecoin_packet = request.child_value("earned_gamecoin_packet")
if earned_gamecoin_packet is not None: if earned_gamecoin_packet is not None:
newprofile.replace_int( newprofile.replace_int("packet", newprofile.get_int("packet") + earned_gamecoin_packet)
"packet", newprofile.get_int("packet") + earned_gamecoin_packet
)
earned_gamecoin_block = request.child_value("earned_gamecoin_block") earned_gamecoin_block = request.child_value("earned_gamecoin_block")
if earned_gamecoin_block is not None: if earned_gamecoin_block is not None:
newprofile.replace_int( newprofile.replace_int("block", newprofile.get_int("block") + earned_gamecoin_block)
"block", newprofile.get_int("block") + earned_gamecoin_block
)
earned_blaster_energy = request.child_value("earned_blaster_energy") earned_blaster_energy = request.child_value("earned_blaster_energy")
if earned_blaster_energy is not None: if earned_blaster_energy is not None:
newprofile.replace_int( newprofile.replace_int(
@ -4146,22 +4090,13 @@ class SoundVoltexHeavenlyHaven(
item_type = child.child_value("type") item_type = child.child_value("type")
param = child.child_value("param") param = child.child_value("param")
if ( if game_config.get_bool("force_unlock_cards") and item_type == self.GAME_CATALOG_TYPE_APPEAL_CARD:
game_config.get_bool("force_unlock_cards")
and item_type == self.GAME_CATALOG_TYPE_APPEAL_CARD
):
# Don't save back appeal cards because they were force unlocked # Don't save back appeal cards because they were force unlocked
continue continue
if ( if game_config.get_bool("force_unlock_songs") and item_type == self.GAME_CATALOG_TYPE_SONG:
game_config.get_bool("force_unlock_songs")
and item_type == self.GAME_CATALOG_TYPE_SONG
):
# Don't save back songs, because they were force unlocked # Don't save back songs, because they were force unlocked
continue continue
if ( if game_config.get_bool("force_unlock_crew") and item_type == self.GAME_CATALOG_TYPE_CREW:
game_config.get_bool("force_unlock_crew")
and item_type == self.GAME_CATALOG_TYPE_CREW
):
# Don't save back crew, because they were force unlocked # Don't save back crew, because they were force unlocked
continue continue

View File

@ -1920,9 +1920,7 @@ class SoundVoltexInfiniteInfection(
elif unlock.type == "special_unlock": elif unlock.type == "special_unlock":
info = Node.void("info") info = Node.void("info")
catalog.add_child(info) catalog.add_child(info)
info.add_child( info.add_child(Node.u8("catalog_type", self.GAME_CATALOG_TYPE_SPECIAL_SONG))
Node.u8("catalog_type", self.GAME_CATALOG_TYPE_SPECIAL_SONG)
)
info.add_child(Node.u32("catalog_id", unlock.id)) info.add_child(Node.u32("catalog_id", unlock.id))
info.add_child(Node.u32("currency_type", self.GAME_CURRENCY_BLOCKS)) info.add_child(Node.u32("currency_type", self.GAME_CURRENCY_BLOCKS))
info.add_child(Node.u32("price", unlock.data.get_int("blocks"))) info.add_child(Node.u32("price", unlock.data.get_int("blocks")))
@ -1941,9 +1939,7 @@ class SoundVoltexInfiniteInfection(
info.add_child(Node.s16("level", course["level"])) info.add_child(Node.s16("level", course["level"]))
info.add_child(Node.s32("season_id", course["season_id"])) info.add_child(Node.s32("season_id", course["season_id"]))
info.add_child(Node.string("season_name", seasons[course["season_id"]])) info.add_child(Node.string("season_name", seasons[course["season_id"]]))
info.add_child( info.add_child(Node.bool("season_new_flg", course["season_id"] == last_season))
Node.bool("season_new_flg", course["season_id"] == last_season)
)
info.add_child(Node.string("course_name", skillnames[course["level"]])) info.add_child(Node.string("course_name", skillnames[course["level"]]))
info.add_child(Node.s16("course_type", 0)) info.add_child(Node.s16("course_type", 0))
info.add_child(Node.s16("skill_name_id", course["level"])) info.add_child(Node.s16("skill_name_id", course["level"]))
@ -1983,10 +1979,7 @@ class SoundVoltexInfiniteInfection(
# Now, grab user records # Now, grab user records
records = self.data.remote.music.get_all_records(self.game, self.version) records = self.data.remote.music.get_all_records(self.game, self.version)
missing_users = [userid for (userid, _) in records] missing_users = [userid for (userid, _) in records]
users = { users = {userid: profile for (userid, profile) in self.get_any_profiles(missing_users)}
userid: profile
for (userid, profile) in self.get_any_profiles(missing_users)
}
hiscore_allover = Node.void("hiscore_allover") hiscore_allover = Node.void("hiscore_allover")
game.add_child(hiscore_allover) game.add_child(hiscore_allover)
@ -2011,14 +2004,10 @@ class SoundVoltexInfiniteInfection(
# Now, grab local records # Now, grab local records
area_users = [ area_users = [
uid uid
for (uid, prof) in self.data.local.user.get_all_profiles( for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version)
self.game, self.version
)
if prof.get_int("loc", -1) == locid if prof.get_int("loc", -1) == locid
] ]
records = self.data.local.music.get_all_records( records = self.data.local.music.get_all_records(self.game, self.version, userlist=area_users)
self.game, self.version, userlist=area_users
)
missing_users = [userid for (userid, _) in records if userid not in users] missing_users = [userid for (userid, _) in records if userid not in users]
for userid, profile in self.get_any_profiles(missing_users): for userid, profile in self.get_any_profiles(missing_users):
users[userid] = profile users[userid] = profile
@ -2051,9 +2040,7 @@ class SoundVoltexInfiniteInfection(
for songid in clears: for songid in clears:
for chart in clears[songid]: for chart in clears[songid]:
if clears[songid][chart]["total"] > 0: if clears[songid][chart]["total"] > 0:
rate = float(clears[songid][chart]["clears"]) / float( rate = float(clears[songid][chart]["clears"]) / float(clears[songid][chart]["total"])
clears[songid][chart]["total"]
)
dnode = Node.void("d") dnode = Node.void("d")
clear_rate.add_child(dnode) clear_rate.add_child(dnode)
dnode.add_child(Node.u32("id", songid)) dnode.add_child(Node.u32("id", songid))
@ -2155,11 +2142,7 @@ class SoundVoltexInfiniteInfection(
self.__db_to_game_clear_type(score.data.get_int("clear_type")), self.__db_to_game_clear_type(score.data.get_int("clear_type")),
) )
) )
music.add_child( music.add_child(Node.u32("score_grade", self.__db_to_game_grade(score.data.get_int("grade"))))
Node.u32(
"score_grade", self.__db_to_game_grade(score.data.get_int("grade"))
)
)
stats = score.data.get_dict("stats") stats = score.data.get_dict("stats")
music.add_child(Node.u32("btn_rate", stats.get_int("btn_rate"))) music.add_child(Node.u32("btn_rate", stats.get_int("btn_rate")))
music.add_child(Node.u32("long_rate", stats.get_int("long_rate"))) music.add_child(Node.u32("long_rate", stats.get_int("long_rate")))
@ -2330,9 +2313,7 @@ class SoundVoltexInfiniteInfection(
game.add_child(Node.u32("gamecoin_packet", profile.get_int("packet"))) game.add_child(Node.u32("gamecoin_packet", profile.get_int("packet")))
game.add_child(Node.u32("gamecoin_block", profile.get_int("block"))) game.add_child(Node.u32("gamecoin_block", profile.get_int("block")))
game.add_child(Node.s16("skill_name_id", profile.get_int("skill_name_id", -1))) game.add_child(Node.s16("skill_name_id", profile.get_int("skill_name_id", -1)))
game.add_child( game.add_child(Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20)))
Node.s32_array("hidden_param", profile.get_int_array("hidden_param", 20))
)
game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy"))) game.add_child(Node.u32("blaster_energy", profile.get_int("blaster_energy")))
game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count"))) game.add_child(Node.u32("blaster_count", profile.get_int("blaster_count")))
@ -2362,9 +2343,7 @@ class SoundVoltexInfiniteInfection(
game.add_child(itemnode) game.add_child(itemnode)
game_config = self.get_game_config() game_config = self.get_game_config()
achievements = self.data.local.user.get_achievements( achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
self.game, self.version, userid
)
for item in achievements: for item in achievements:
if item.type[:5] != "item_": if item.type[:5] != "item_":
@ -2375,9 +2354,7 @@ class SoundVoltexInfiniteInfection(
# Type 1 is appeal cards, and the game saves this for non-default cards but # Type 1 is appeal cards, and the game saves this for non-default cards but
# we take care of this below. # we take care of this below.
continue continue
if itemtype == self.GAME_CATALOG_TYPE_SONG and game_config.get_bool( if itemtype == self.GAME_CATALOG_TYPE_SONG and game_config.get_bool("force_unlock_songs"):
"force_unlock_songs"
):
# We will echo this below in the force unlock song section # We will echo this below in the force unlock song section
continue continue
@ -2452,22 +2429,16 @@ class SoundVoltexInfiniteInfection(
return game return game
def unformat_profile( def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
self, userid: UserID, request: Node, oldprofile: Profile
) -> Profile:
newprofile = oldprofile.clone() newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies # Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value("earned_gamecoin_packet") earned_gamecoin_packet = request.child_value("earned_gamecoin_packet")
if earned_gamecoin_packet is not None: if earned_gamecoin_packet is not None:
newprofile.replace_int( newprofile.replace_int("packet", newprofile.get_int("packet") + earned_gamecoin_packet)
"packet", newprofile.get_int("packet") + earned_gamecoin_packet
)
earned_gamecoin_block = request.child_value("earned_gamecoin_block") earned_gamecoin_block = request.child_value("earned_gamecoin_block")
if earned_gamecoin_block is not None: if earned_gamecoin_block is not None:
newprofile.replace_int( newprofile.replace_int("block", newprofile.get_int("block") + earned_gamecoin_block)
"block", newprofile.get_int("block") + earned_gamecoin_block
)
earned_blaster_energy = request.child_value("earned_blaster_energy") earned_blaster_energy = request.child_value("earned_blaster_energy")
if earned_blaster_energy is not None: if earned_blaster_energy is not None:
newprofile.replace_int( newprofile.replace_int(
@ -2478,9 +2449,7 @@ class SoundVoltexInfiniteInfection(
# Miscelaneous stuff # Miscelaneous stuff
newprofile.replace_int("blaster_count", request.child_value("blaster_count")) newprofile.replace_int("blaster_count", request.child_value("blaster_count"))
newprofile.replace_int("skill_name_id", request.child_value("skill_name_id")) newprofile.replace_int("skill_name_id", request.child_value("skill_name_id"))
newprofile.replace_int_array( newprofile.replace_int_array("hidden_param", 20, request.child_value("hidden_param"))
"hidden_param", 20, request.child_value("hidden_param")
)
# Update user's unlock status if we aren't force unlocked # Update user's unlock status if we aren't force unlocked
game_config = self.get_game_config() game_config = self.get_game_config()

View File

@ -22,9 +22,7 @@ class BaseClient:
CORRECT_PASSWORD: Final[str] = "1234" CORRECT_PASSWORD: Final[str] = "1234"
WRONG_PASSWORD: Final[str] = "4321" WRONG_PASSWORD: Final[str] = "4321"
def __init__( def __init__(self, proto: ClientProtocol, pcbid: str, config: Dict[str, Any]) -> None:
self, proto: ClientProtocol, pcbid: str, config: Dict[str, Any]
) -> None:
self.__proto = proto self.__proto = proto
self.pcbid = pcbid self.pcbid = pcbid
self.config = config self.config = config
@ -92,9 +90,7 @@ class BaseClient:
if not self.__assert_path(root, path): if not self.__assert_path(root, path):
raise Exception(f"Path '{path}' not found in root node:\n{root}") raise Exception(f"Path '{path}' not found in root node:\n{root}")
def verify_services_get( def verify_services_get(self, expected_services: List[str] = [], include_net: bool = False) -> None:
self, expected_services: List[str] = [], include_net: bool = False
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -254,9 +250,7 @@ class BaseClient:
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/pcbevent") self.assert_path(resp, "response/pcbevent")
def verify_cardmng_inquire( def verify_cardmng_inquire(self, card_id: str, msg_type: str, paseli_enabled: bool) -> Optional[str]:
self, card_id: str, msg_type: str, paseli_enabled: bool
) -> Optional[str]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -295,17 +289,11 @@ class BaseClient:
ecflag = int(resp.child("cardmng").attribute("ecflag")) ecflag = int(resp.child("cardmng").attribute("ecflag"))
if binded != 0: if binded != 0:
raise Exception( raise Exception(f"Card '{card_id}' returned invalid binded value '{binded}'")
f"Card '{card_id}' returned invalid binded value '{binded}'"
)
if newflag != 1: if newflag != 1:
raise Exception( raise Exception(f"Card '{card_id}' returned invalid newflag value '{newflag}'")
f"Card '{card_id}' returned invalid newflag value '{newflag}'"
)
if ecflag != (1 if paseli_enabled else 0): if ecflag != (1 if paseli_enabled else 0):
raise Exception( raise Exception(f"Card '{card_id}' returned invalid ecflag value '{newflag}'")
f"Card '{card_id}' returned invalid ecflag value '{newflag}'"
)
# Return the refid # Return the refid
return resp.child("cardmng").attribute("refid") return resp.child("cardmng").attribute("refid")
@ -321,17 +309,11 @@ class BaseClient:
ecflag = int(resp.child("cardmng").attribute("ecflag")) ecflag = int(resp.child("cardmng").attribute("ecflag"))
if binded != 1: if binded != 1:
raise Exception( raise Exception(f"Card '{card_id}' returned invalid binded value '{binded}'")
f"Card '{card_id}' returned invalid binded value '{binded}'"
)
if newflag != 0: if newflag != 0:
raise Exception( raise Exception(f"Card '{card_id}' returned invalid newflag value '{newflag}'")
f"Card '{card_id}' returned invalid newflag value '{newflag}'"
)
if ecflag != (1 if paseli_enabled else 0): if ecflag != (1 if paseli_enabled else 0):
raise Exception( raise Exception(f"Card '{card_id}' returned invalid ecflag value '{newflag}'")
f"Card '{card_id}' returned invalid ecflag value '{newflag}'"
)
# Return the refid # Return the refid
return resp.child("cardmng").attribute("refid") return resp.child("cardmng").attribute("refid")
@ -365,9 +347,7 @@ class BaseClient:
cardmng = Node.void("cardmng") cardmng = Node.void("cardmng")
call.add_child(cardmng) call.add_child(cardmng)
cardmng.set_attribute("method", "authpass") cardmng.set_attribute("method", "authpass")
cardmng.set_attribute( cardmng.set_attribute("pass", self.CORRECT_PASSWORD if correct else self.CORRECT_PASSWORD[::-1])
"pass", self.CORRECT_PASSWORD if correct else self.CORRECT_PASSWORD[::-1]
)
cardmng.set_attribute("refid", ref_id) cardmng.set_attribute("refid", ref_id)
# Swap with server # Swap with server
@ -426,9 +406,7 @@ class BaseClient:
newbalance = resp.child("eacoin").child_value("balance") newbalance = resp.child("eacoin").child_value("balance")
if balance - amount != newbalance: if balance - amount != newbalance:
raise Exception( raise Exception(f"Expected to get back balance {balance - amount} but got {newbalance}")
f"Expected to get back balance {balance - amount} but got {newbalance}"
)
def verify_eacoin_checkout(self, session: str) -> None: def verify_eacoin_checkout(self, session: str) -> None:
call = self.call_node() call = self.call_node()

View File

@ -190,32 +190,22 @@ class TheStarBishiBashiClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") 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 # Bishi doesn't read a new profile, it just writes out CSV for a blank one
self.verify_usergamedata_send(ref_id, msg_type="new") self.verify_usergamedata_send(ref_id, msg_type="new")
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -403,9 +403,7 @@ class DDR2013Client(BaseClient):
scores[reclink][chart] = vals scores[reclink][chart] = vals
return scores return scores
def verify_game_save( def verify_game_save(self, ref_id: str, style: int, gauge: Optional[List[int]] = None) -> None:
self, ref_id: str, style: int, gauge: Optional[List[int]] = None
) -> None:
gauge = gauge or [0, 0, 0, 0, 0] gauge = gauge or [0, 0, 0, 0, 0]
call = self.call_node() call = self.call_node()
@ -460,9 +458,7 @@ class DDR2013Client(BaseClient):
int(resp.child("game").attribute("sc5")), int(resp.child("game").attribute("sc5")),
] ]
def verify_game_save_m( def verify_game_save_m(self, ref_id: str, ext_id: str, score: Dict[str, Any]) -> None:
self, ref_id: str, ext_id: str, score: Dict[str, Any]
) -> None:
call = self.call_node() call = self.call_node()
game = Node.void("game") game = Node.void("game")
call.add_child(game) call.add_child(game)
@ -544,33 +540,23 @@ class DDR2013Client(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") 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 # 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_load(ref_id, msg_type="new")
self.verify_game_new(ref_id) self.verify_game_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify locking and unlocking profile ability # Verify locking and unlocking profile ability
@ -703,22 +689,16 @@ class DDR2013Client(BaseClient):
# Verify empty scores for starters # Verify empty scores for starters
if phase == 1: if phase == 1:
for score in dummyscores: for score in dummyscores:
last_five = self.verify_game_score( last_five = self.verify_game_score(ref_id, score["id"], score["chart"])
ref_id, score["id"], score["chart"]
)
if any([s != 0 for s in last_five]): if any([s != 0 for s in last_five]):
raise Exception( raise Exception("Score already found on song not played yet!")
"Score already found on song not played yet!"
)
for score in dummyscores: for score in dummyscores:
self.verify_game_save_m(ref_id, ext_id, score) self.verify_game_save_m(ref_id, ext_id, score)
scores = self.verify_game_load_m(ref_id) scores = self.verify_game_load_m(ref_id)
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
# Verify the attributes of the score # Verify the attributes of the score
expected_score = score.get("expected_score", score["score"]) expected_score = score.get("expected_score", score["score"])
@ -739,9 +719,7 @@ class DDR2013Client(BaseClient):
) )
# Verify that the last score is our score # Verify that the last score is our score
last_five = self.verify_game_score( last_five = self.verify_game_score(ref_id, score["id"], score["chart"])
ref_id, score["id"], score["chart"]
)
if last_five[0] != score["score"]: if last_five[0] != score["score"]:
raise Exception( raise Exception(
f'Invalid score returned for last five scores on song {score["id"]} chart {score["chart"]}!' f'Invalid score returned for last five scores on song {score["id"]} chart {score["chart"]}!'

View File

@ -423,9 +423,7 @@ class DDR2014Client(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/game") self.assert_path(resp, "response/game")
def verify_game_save( def verify_game_save(self, ref_id: str, style: int, gauge: Optional[List[int]] = None) -> None:
self, ref_id: str, style: int, gauge: Optional[List[int]] = None
) -> None:
gauge = gauge or [0, 0, 0, 0, 0] gauge = gauge or [0, 0, 0, 0, 0]
call = self.call_node() call = self.call_node()
@ -453,9 +451,7 @@ class DDR2014Client(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/game") self.assert_path(resp, "response/game")
def verify_game_save_m( def verify_game_save_m(self, ref_id: str, ext_id: str, score: Dict[str, Any]) -> None:
self, ref_id: str, ext_id: str, score: Dict[str, Any]
) -> None:
call = self.call_node() call = self.call_node()
game = Node.void("game") game = Node.void("game")
call.add_child(game) call.add_child(game)
@ -546,33 +542,23 @@ class DDR2014Client(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") 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 # 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_load(ref_id, msg_type="new")
self.verify_game_new(ref_id) self.verify_game_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify locking and unlocking profile ability # Verify locking and unlocking profile ability
@ -709,9 +695,7 @@ class DDR2014Client(BaseClient):
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
# Verify the attributes of the score # Verify the attributes of the score
expected_score = score.get("expected_score", score["score"]) expected_score = score.get("expected_score", score["score"])

View File

@ -99,9 +99,7 @@ class DDRAceClient(BaseClient):
return resp.child_value("playerdata/code") return resp.child_value("playerdata/code")
def verify_playerdata_usergamedata_advanced_ghostload( def verify_playerdata_usergamedata_advanced_ghostload(self, refid: str, ghostid: int) -> Dict[str, Any]:
self, refid: str, ghostid: int
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -140,9 +138,7 @@ class DDRAceClient(BaseClient):
"ghost": resp.child_value("playerdata/ghostdata/ghost"), "ghost": resp.child_value("playerdata/ghostdata/ghost"),
} }
def verify_playerdata_usergamedata_advanced_rivalload( def verify_playerdata_usergamedata_advanced_rivalload(self, refid: str, loadflag: int) -> None:
self, refid: str, loadflag: int
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -191,9 +187,7 @@ class DDRAceClient(BaseClient):
if resp.child_value("playerdata/data/recordtype") != loadflag: if resp.child_value("playerdata/data/recordtype") != loadflag:
raise Exception("Invalid record type returned!") raise Exception("Invalid record type returned!")
def verify_playerdata_usergamedata_advanced_userload( def verify_playerdata_usergamedata_advanced_userload(self, refid: str) -> Tuple[bool, List[Dict[str, Any]]]:
self, refid: str
) -> Tuple[bool, List[Dict[str, Any]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -252,9 +246,7 @@ class DDRAceClient(BaseClient):
music, music,
) )
def verify_playerdata_usergamedata_advanced_inheritance( def verify_playerdata_usergamedata_advanced_inheritance(self, refid: str, locid: str) -> None:
self, refid: str, locid: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -454,9 +446,7 @@ class DDRAceClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/playerdata/result") self.assert_path(resp, "response/playerdata/result")
def verify_usergamedata_send( def verify_usergamedata_send(self, ref_id: str, ext_id: int, msg_type: str, send_only_common: bool = False) -> None:
self, ref_id: str, ext_id: int, msg_type: str, send_only_common: bool = False
) -> None:
call = self.call_node() call = self.call_node()
# Set up profile write # Set up profile write
@ -720,9 +710,7 @@ class DDRAceClient(BaseClient):
self.verify_eventlog_write(location) self.verify_eventlog_write(location)
# Verify the game-wide packets Ace insists on sending before profile load # Verify the game-wide packets Ace insists on sending before profile load
is_new, music = self.verify_playerdata_usergamedata_advanced_userload( is_new, music = self.verify_playerdata_usergamedata_advanced_userload("X0000000000000000000000000123456")
"X0000000000000000000000000123456"
)
if not is_new: if not is_new:
raise Exception("Fake profiles should be new!") raise Exception("Fake profiles should be new!")
if len(music) > 0: if len(music) > 0:
@ -736,18 +724,12 @@ class DDRAceClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
self.verify_system_convcardnumber(card) self.verify_system_convcardnumber(card)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
extid = self.verify_playerdata_usergamedata_advanced_usernew(ref_id) extid = self.verify_playerdata_usergamedata_advanced_usernew(ref_id)
self.verify_usergamedata_send(ref_id, extid, "new") self.verify_usergamedata_send(ref_id, extid, "new")
@ -755,30 +737,22 @@ class DDRAceClient(BaseClient):
name = self.verify_usergamedata_recv(ref_id) name = self.verify_usergamedata_recv(ref_id)
if name != "": if name != "":
raise Exception("Name stored on profile we just created!") raise Exception("Name stored on profile we just created!")
self.verify_usergamedata_send( self.verify_usergamedata_send(ref_id, extid, "existing", send_only_common=True)
ref_id, extid, "existing", send_only_common=True
)
name = self.verify_usergamedata_recv(ref_id) name = self.verify_usergamedata_recv(ref_id)
if name != self.NAME: if name != self.NAME:
raise Exception("Name stored on profile is incorrect!") raise Exception("Name stored on profile is incorrect!")
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
is_new, music = self.verify_playerdata_usergamedata_advanced_userload( is_new, music = self.verify_playerdata_usergamedata_advanced_userload(ref_id)
ref_id
)
if is_new: if is_new:
raise Exception("Profile should not be new!") raise Exception("Profile should not be new!")
if len(music) > 0: if len(music) > 0:
@ -862,9 +836,7 @@ class DDRAceClient(BaseClient):
) )
pos = pos + 1 pos = pos + 1
is_new, scores = self.verify_playerdata_usergamedata_advanced_userload( is_new, scores = self.verify_playerdata_usergamedata_advanced_userload(ref_id)
ref_id
)
if is_new: if is_new:
raise Exception("Profile should not be new!") raise Exception("Profile should not be new!")
if len(scores) == 0: if len(scores) == 0:
@ -873,17 +845,12 @@ class DDRAceClient(BaseClient):
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]
@ -912,9 +879,7 @@ class DDRAceClient(BaseClient):
) )
# Now verify that the ghost for this score is what we saved # Now verify that the ghost for this score is what we saved
ghost = self.verify_playerdata_usergamedata_advanced_ghostload( ghost = self.verify_playerdata_usergamedata_advanced_ghostload(ref_id, received["ghostid"])
ref_id, received["ghostid"]
)
if "expected_ghost" in expected: if "expected_ghost" in expected:
expected_ghost = expected["expected_ghost"] expected_ghost = expected["expected_ghost"]
else: else:
@ -933,9 +898,7 @@ class DDRAceClient(BaseClient):
f'Wrong ghost data \'{ghost["ghost"]}\' returned for ghost, expected \'{expected_ghost}\'' f'Wrong ghost data \'{ghost["ghost"]}\' returned for ghost, expected \'{expected_ghost}\''
) )
if ghost["extid"] != extid: if ghost["extid"] != extid:
raise Exception( raise Exception(f'Wrong extid \'{ghost["extid"]}\' returned for ghost, expected \'{extid}\'')
f'Wrong extid \'{ghost["extid"]}\' returned for ghost, expected \'{extid}\''
)
# Sleep so we don't end up putting in score history on the same second # Sleep so we don't end up putting in score history on the same second
time.sleep(1) time.sleep(1)
@ -952,15 +915,9 @@ class DDRAceClient(BaseClient):
print("Skipping score checks for existing card") print("Skipping score checks for existing card")
# Verify global scores now that we've inserted some # Verify global scores now that we've inserted some
self.verify_playerdata_usergamedata_advanced_rivalload( self.verify_playerdata_usergamedata_advanced_rivalload("X0000000000000000000000000123456", 1)
"X0000000000000000000000000123456", 1 self.verify_playerdata_usergamedata_advanced_rivalload("X0000000000000000000000000123456", 2)
) self.verify_playerdata_usergamedata_advanced_rivalload("X0000000000000000000000000123456", 4)
self.verify_playerdata_usergamedata_advanced_rivalload(
"X0000000000000000000000000123456", 2
)
self.verify_playerdata_usergamedata_advanced_rivalload(
"X0000000000000000000000000123456", 4
)
# Verify paseli handling # Verify paseli handling
if paseli_enabled: if paseli_enabled:

View File

@ -347,9 +347,7 @@ class DDRX2Client(BaseClient):
index = index + 1 index = index + 1
return courses return courses
def verify_game_save( def verify_game_save(self, ref_id: str, style: int, gauge: Optional[List[int]] = None) -> None:
self, ref_id: str, style: int, gauge: Optional[List[int]] = None
) -> None:
gauge = gauge or [0, 0, 0, 0, 0] gauge = gauge or [0, 0, 0, 0, 0]
call = self.call_node() call = self.call_node()
@ -502,33 +500,23 @@ class DDRX2Client(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") 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 # 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_load(ref_id, msg_type="new")
self.verify_game_new(ref_id) self.verify_game_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify locking and unlocking profile ability # Verify locking and unlocking profile ability
@ -655,22 +643,16 @@ class DDRX2Client(BaseClient):
# Verify empty scores for starters # Verify empty scores for starters
if phase == 1: if phase == 1:
for score in dummyscores: for score in dummyscores:
last_five = self.verify_game_score( last_five = self.verify_game_score(ref_id, score["id"], score["chart"])
ref_id, score["id"], score["chart"]
)
if any([s != 0 for s in last_five]): if any([s != 0 for s in last_five]):
raise Exception( raise Exception("Score already found on song not played yet!")
"Score already found on song not played yet!"
)
for score in dummyscores: for score in dummyscores:
self.verify_game_save_m(ref_id, score) self.verify_game_save_m(ref_id, score)
scores = self.verify_game_load_m(ref_id) scores = self.verify_game_load_m(ref_id)
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
# Verify the attributes of the score # Verify the attributes of the score
expected_score = score.get("expected_score", score["score"]) expected_score = score.get("expected_score", score["score"])
@ -691,9 +673,7 @@ class DDRX2Client(BaseClient):
) )
# Verify that the last score is our score # Verify that the last score is our score
last_five = self.verify_game_score( last_five = self.verify_game_score(ref_id, score["id"], score["chart"])
ref_id, score["id"], score["chart"]
)
if last_five[0] != score["score"]: if last_five[0] != score["score"]:
raise Exception( raise Exception(
f'Invalid score returned for last five scores on song {score["id"]} chart {score["chart"]}!' f'Invalid score returned for last five scores on song {score["id"]} chart {score["chart"]}!'
@ -769,9 +749,7 @@ class DDRX2Client(BaseClient):
expected_combo = course.get("expected_combo", course["combo"]) expected_combo = course.get("expected_combo", course["combo"])
expected_rank = course.get("expected_rank", course["rank"]) expected_rank = course.get("expected_rank", course["rank"])
expected_stage = course.get("expected_stage", course["stage"]) expected_stage = course.get("expected_stage", course["stage"])
expected_combo_type = course.get( expected_combo_type = course.get("expected_combo_type", course["combo_type"])
"expected_combo_type", course["combo_type"]
)
if data["score"] != expected_score: if data["score"] != expected_score:
raise Exception( raise Exception(

View File

@ -414,9 +414,7 @@ class DDRX3Client(BaseClient):
index = index + 1 index = index + 1
return courses return courses
def verify_game_save( def verify_game_save(self, ref_id: str, style: int, gauge: Optional[List[int]] = None) -> None:
self, ref_id: str, style: int, gauge: Optional[List[int]] = None
) -> None:
gauge = gauge or [0, 0, 0, 0, 0] gauge = gauge or [0, 0, 0, 0, 0]
call = self.call_node() call = self.call_node()
@ -579,33 +577,23 @@ class DDRX3Client(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") 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 # 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_load(ref_id, msg_type="new")
self.verify_game_new(ref_id) self.verify_game_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify locking and unlocking profile ability # Verify locking and unlocking profile ability
@ -778,33 +766,23 @@ class DDRX3Client(BaseClient):
# Verify empty scores for starters # Verify empty scores for starters
if phase == 1: if phase == 1:
for score in dummyscores: for score in dummyscores:
last_five = self.verify_game_score( last_five = self.verify_game_score(ref_id, score["id"], score["chart"])
ref_id, score["id"], score["chart"]
)
if any([s != 0 for s in last_five]): if any([s != 0 for s in last_five]):
raise Exception( raise Exception("Score already found on song not played yet!")
"Score already found on song not played yet!"
)
for score in dummyscores: for score in dummyscores:
self.verify_game_save_m(ref_id, score) self.verify_game_save_m(ref_id, score)
scores = self.verify_game_load_m(ref_id) scores = self.verify_game_load_m(ref_id)
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
# Verify the attributes of the score # Verify the attributes of the score
expected_score = score.get("expected_score", score["score"]) expected_score = score.get("expected_score", score["score"])
expected_rank = score.get("expected_rank", score["rank"]) expected_rank = score.get("expected_rank", score["rank"])
expected_halo = score.get("expected_halo", score["halo"]) expected_halo = score.get("expected_halo", score["halo"])
expected_score_2nd = score.get( expected_score_2nd = score.get("expected_score_2nd", score["score_2nd"])
"expected_score_2nd", score["score_2nd"] expected_rank_2nd = score.get("expected_rank_2nd", score["rank_2nd"])
)
expected_rank_2nd = score.get(
"expected_rank_2nd", score["rank_2nd"]
)
if score["score"] != 0: if score["score"] != 0:
if data["score"] != expected_score: if data["score"] != expected_score:
@ -821,9 +799,7 @@ class DDRX3Client(BaseClient):
) )
# Verify that the last score is our score # Verify that the last score is our score
last_five = self.verify_game_score( last_five = self.verify_game_score(ref_id, score["id"], score["chart"])
ref_id, score["id"], score["chart"]
)
if last_five[0] != score["score"]: if last_five[0] != score["score"]:
raise Exception( raise Exception(
f'Invalid score returned for last five scores on song {score["id"]} chart {score["chart"]}!' f'Invalid score returned for last five scores on song {score["id"]} chart {score["chart"]}!'
@ -908,9 +884,7 @@ class DDRX3Client(BaseClient):
expected_combo = course.get("expected_combo", course["combo"]) expected_combo = course.get("expected_combo", course["combo"])
expected_rank = course.get("expected_rank", course["rank"]) expected_rank = course.get("expected_rank", course["rank"])
expected_stage = course.get("expected_stage", course["stage"]) expected_stage = course.get("expected_stage", course["stage"])
expected_combo_type = course.get( expected_combo_type = course.get("expected_combo_type", course["combo_type"])
"expected_combo_type", course["combo_type"]
)
if data["score"] != expected_score: if data["score"] != expected_score:
raise Exception( raise Exception(

View File

@ -91,9 +91,7 @@ class IIDXCannonBallersClient(BaseClient):
raise Exception(f"Invalid node data {child} in clear rate response!") raise Exception(f"Invalid node data {child} in clear rate response!")
for v in child.value: for v in child.value:
if v < 0 or v > 1001: if v < 0 or v > 1001:
raise Exception( raise Exception(f"Invalid clear percent {child} in clear rate response!")
f"Invalid clear percent {child} in clear rate response!"
)
def verify_iidx25shop_getconvention(self, lid: str) -> None: def verify_iidx25shop_getconvention(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -175,9 +173,7 @@ class IIDXCannonBallersClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/IIDX25shop") self.assert_path(resp, "response/IIDX25shop")
def verify_iidx25pc_get( def verify_iidx25pc_get(self, ref_id: str, card_id: str, lid: str) -> Dict[str, Any]:
self, ref_id: str, card_id: str, lid: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -297,9 +293,7 @@ class IIDXCannonBallersClient(BaseClient):
"expert_point": expert_point, "expert_point": expert_point,
} }
def verify_iidx25music_getrank( def verify_iidx25music_getrank(self, extid: int) -> Dict[int, Dict[int, Dict[str, int]]]:
self, extid: int
) -> Dict[int, Dict[int, Dict[str, int]]]:
scores: Dict[int, Dict[int, Dict[str, int]]] = {} scores: Dict[int, Dict[int, Dict[str, int]]] = {}
for cltype in [0, 1]: # singles, doubles for cltype in [0, 1]: # singles, doubles
call = self.call_node() call = self.call_node()
@ -321,9 +315,7 @@ class IIDXCannonBallersClient(BaseClient):
for child in resp.child("IIDX25music").children: for child in resp.child("IIDX25music").children:
if child.name == "m": if child.name == "m":
if child.value[0] != -1: if child.value[0] != -1:
raise Exception( raise Exception("Got non-self score back when requesting only our scores!")
"Got non-self score back when requesting only our scores!"
)
music_id = child.value[1] music_id = child.value[1]
normal_clear_status = child.value[2] normal_clear_status = child.value[2]
@ -461,9 +453,7 @@ class IIDXCannonBallersClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
self.assert_path(resp, "response/IIDX25pc") self.assert_path(resp, "response/IIDX25pc")
def verify_iidx25music_reg( def verify_iidx25music_reg(self, extid: int, lid: str, score: Dict[str, Any]) -> None:
self, extid: int, lid: str, score: Dict[str, Any]
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -491,9 +481,7 @@ class IIDXCannonBallersClient(BaseClient):
self.assert_path(resp, "response/IIDX25music/shopdata/@rank") self.assert_path(resp, "response/IIDX25music/shopdata/@rank")
self.assert_path(resp, "response/IIDX25music/ranklist/data") self.assert_path(resp, "response/IIDX25music/ranklist/data")
def verify_iidx25music_appoint( def verify_iidx25music_appoint(self, extid: int, musicid: int, chart: int) -> Tuple[int, bytes]:
self, extid: int, musicid: int, chart: int
) -> Tuple[int, bytes]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -618,9 +606,7 @@ class IIDXCannonBallersClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX25music") self.assert_path(resp, "response/IIDX25music")
def verify_iidx25grade_raised( def verify_iidx25grade_raised(self, iidxid: int, shop_name: str, dantype: str) -> None:
self, iidxid: int, shop_name: str, dantype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -644,9 +630,7 @@ class IIDXCannonBallersClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX25grade/@pnum") self.assert_path(resp, "response/IIDX25grade/@pnum")
def verify_iidx25ranking_entry( def verify_iidx25ranking_entry(self, iidxid: int, shop_name: str, coursetype: str) -> None:
self, iidxid: int, shop_name: str, coursetype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -757,13 +741,9 @@ class IIDXCannonBallersClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
self.assert_path(resp, "response/IIDX25music/cpu_score_list/score_list/score") self.assert_path(resp, "response/IIDX25music/cpu_score_list/score_list/score")
self.assert_path( self.assert_path(resp, "response/IIDX25music/cpu_score_list/score_list/enable_score")
resp, "response/IIDX25music/cpu_score_list/score_list/enable_score"
)
self.assert_path(resp, "response/IIDX25music/cpu_score_list/score_list/ghost") self.assert_path(resp, "response/IIDX25music/cpu_score_list/score_list/ghost")
self.assert_path( self.assert_path(resp, "response/IIDX25music/cpu_score_list/score_list/enable_ghost")
resp, "response/IIDX25music/cpu_score_list/score_list/enable_ghost"
)
def verify_iidx25gamesystem_systeminfo(self, lid: str) -> None: def verify_iidx25gamesystem_systeminfo(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -820,32 +800,22 @@ class IIDXCannonBallersClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_iidx25pc_reg(ref_id, card, lid) self.verify_iidx25pc_reg(ref_id, card, lid)
self.verify_iidx25pc_get(ref_id, card, lid) self.verify_iidx25pc_get(ref_id, card, lid)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -940,9 +910,7 @@ class IIDXCannonBallersClient(BaseClient):
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
if "expected_ex_score" in score: if "expected_ex_score" in score:
expected_score = score["expected_ex_score"] expected_score = score["expected_ex_score"]
@ -971,9 +939,7 @@ class IIDXCannonBallersClient(BaseClient):
) )
# Verify we can fetch our own ghost # Verify we can fetch our own ghost
ex_score, ghost = self.verify_iidx25music_appoint( ex_score, ghost = self.verify_iidx25music_appoint(profile["extid"], score["id"], score["chart"])
profile["extid"], score["id"], score["chart"]
)
if ex_score != expected_score: if ex_score != expected_score:
raise Exception( raise Exception(
f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\'' f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\''
@ -1078,9 +1044,7 @@ class IIDXCannonBallersClient(BaseClient):
) )
scores = self.verify_iidx25music_getrank(profile["extid"]) scores = self.verify_iidx25music_getrank(profile["extid"])
if 1000 not in scores: if 1000 not in scores:
raise Exception( raise Exception(f"Didn't get expected scores back for song {1000} beginner chart!")
f"Didn't get expected scores back for song {1000} beginner chart!"
)
if 6 not in scores[1000]: if 6 not in scores[1000]:
raise Exception(f"Didn't get beginner score back for song {1000}!") raise Exception(f"Didn't get beginner score back for song {1000}!")
if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}: if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}:
@ -1101,12 +1065,8 @@ class IIDXCannonBallersClient(BaseClient):
self.verify_iidx25ranking_classicentry(profile["extid"]) self.verify_iidx25ranking_classicentry(profile["extid"])
profile = self.verify_iidx25pc_get(ref_id, card, lid) profile = self.verify_iidx25pc_get(ref_id, card, lid)
for ptype in ["ir_data", "secret_course_data", "classic_course_data"]: for ptype in ["ir_data", "secret_course_data", "classic_course_data"]:
if profile[ptype] != { if profile[ptype] != {2: {1: {"clear_status": 4, "pgnum": 1771, "gnum": 967}}}:
2: {1: {"clear_status": 4, "pgnum": 1771, "gnum": 967}} raise Exception(f"Invalid data {profile[ptype]} returned on profile load for {ptype}!")
}:
raise Exception(
f"Invalid data {profile[ptype]} returned on profile load for {ptype}!"
)
else: else:
print("Skipping score checks for existing card") print("Skipping score checks for existing card")

View File

@ -90,9 +90,7 @@ class IIDXCopulaClient(BaseClient):
raise Exception(f"Invalid node data {child} in clear rate response!") raise Exception(f"Invalid node data {child} in clear rate response!")
for v in child.value: for v in child.value:
if v < 0 or v > 101: if v < 0 or v > 101:
raise Exception( raise Exception(f"Invalid clear percent {child} in clear rate response!")
f"Invalid clear percent {child} in clear rate response!"
)
def verify_iidx23shop_getconvention(self, lid: str) -> None: def verify_iidx23shop_getconvention(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -171,9 +169,7 @@ class IIDXCopulaClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/IIDX23shop") self.assert_path(resp, "response/IIDX23shop")
def verify_iidx23pc_get( def verify_iidx23pc_get(self, ref_id: str, card_id: str, lid: str) -> Dict[str, Any]:
self, ref_id: str, card_id: str, lid: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -269,9 +265,7 @@ class IIDXCopulaClient(BaseClient):
"expert_point": expert_point, "expert_point": expert_point,
} }
def verify_iidx23music_getrank( def verify_iidx23music_getrank(self, extid: int) -> Dict[int, Dict[int, Dict[str, int]]]:
self, extid: int
) -> Dict[int, Dict[int, Dict[str, int]]]:
scores: Dict[int, Dict[int, Dict[str, int]]] = {} scores: Dict[int, Dict[int, Dict[str, int]]] = {}
for cltype in [0, 1]: # singles, doubles for cltype in [0, 1]: # singles, doubles
call = self.call_node() call = self.call_node()
@ -293,9 +287,7 @@ class IIDXCopulaClient(BaseClient):
for child in resp.child("IIDX23music").children: for child in resp.child("IIDX23music").children:
if child.name == "m": if child.name == "m":
if child.value[0] != -1: if child.value[0] != -1:
raise Exception( raise Exception("Got non-self score back when requesting only our scores!")
"Got non-self score back when requesting only our scores!"
)
music_id = child.value[1] music_id = child.value[1]
normal_clear_status = child.value[2] normal_clear_status = child.value[2]
@ -434,9 +426,7 @@ class IIDXCopulaClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
self.assert_path(resp, "response/IIDX23pc") self.assert_path(resp, "response/IIDX23pc")
def verify_iidx23music_reg( def verify_iidx23music_reg(self, extid: int, lid: str, score: Dict[str, Any]) -> None:
self, extid: int, lid: str, score: Dict[str, Any]
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -464,9 +454,7 @@ class IIDXCopulaClient(BaseClient):
self.assert_path(resp, "response/IIDX23music/shopdata/@rank") self.assert_path(resp, "response/IIDX23music/shopdata/@rank")
self.assert_path(resp, "response/IIDX23music/ranklist/data") self.assert_path(resp, "response/IIDX23music/ranklist/data")
def verify_iidx23music_appoint( def verify_iidx23music_appoint(self, extid: int, musicid: int, chart: int) -> Tuple[int, bytes]:
self, extid: int, musicid: int, chart: int
) -> Tuple[int, bytes]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -586,9 +574,7 @@ class IIDXCopulaClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX23music") self.assert_path(resp, "response/IIDX23music")
def verify_iidx23grade_raised( def verify_iidx23grade_raised(self, iidxid: int, shop_name: str, dantype: str) -> None:
self, iidxid: int, shop_name: str, dantype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -612,9 +598,7 @@ class IIDXCopulaClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX23grade/@pnum") self.assert_path(resp, "response/IIDX23grade/@pnum")
def verify_iidx23ranking_entry( def verify_iidx23ranking_entry(self, iidxid: int, shop_name: str, coursetype: str) -> None:
self, iidxid: int, shop_name: str, coursetype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -682,32 +666,22 @@ class IIDXCopulaClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_iidx23pc_reg(ref_id, card, lid) self.verify_iidx23pc_reg(ref_id, card, lid)
self.verify_iidx23pc_get(ref_id, card, lid) self.verify_iidx23pc_get(ref_id, card, lid)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -802,9 +776,7 @@ class IIDXCopulaClient(BaseClient):
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
if "expected_ex_score" in score: if "expected_ex_score" in score:
expected_score = score["expected_ex_score"] expected_score = score["expected_ex_score"]
@ -833,9 +805,7 @@ class IIDXCopulaClient(BaseClient):
) )
# Verify we can fetch our own ghost # Verify we can fetch our own ghost
ex_score, ghost = self.verify_iidx23music_appoint( ex_score, ghost = self.verify_iidx23music_appoint(profile["extid"], score["id"], score["chart"])
profile["extid"], score["id"], score["chart"]
)
if ex_score != expected_score: if ex_score != expected_score:
raise Exception( raise Exception(
f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\'' f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\''
@ -940,9 +910,7 @@ class IIDXCopulaClient(BaseClient):
) )
scores = self.verify_iidx23music_getrank(profile["extid"]) scores = self.verify_iidx23music_getrank(profile["extid"])
if 1000 not in scores: if 1000 not in scores:
raise Exception( raise Exception(f"Didn't get expected scores back for song {1000} beginner chart!")
f"Didn't get expected scores back for song {1000} beginner chart!"
)
if 6 not in scores[1000]: if 6 not in scores[1000]:
raise Exception(f"Didn't get beginner score back for song {1000}!") raise Exception(f"Didn't get beginner score back for song {1000}!")
if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}: if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}:
@ -962,12 +930,8 @@ class IIDXCopulaClient(BaseClient):
self.verify_iidx23ranking_entry(profile["extid"], newname, "secret") self.verify_iidx23ranking_entry(profile["extid"], newname, "secret")
profile = self.verify_iidx23pc_get(ref_id, card, lid) profile = self.verify_iidx23pc_get(ref_id, card, lid)
for ptype in ["ir_data", "secret_course_data"]: for ptype in ["ir_data", "secret_course_data"]:
if profile[ptype] != { if profile[ptype] != {2: {1: {"clear_status": 4, "pgnum": 1771, "gnum": 967}}}:
2: {1: {"clear_status": 4, "pgnum": 1771, "gnum": 967}} raise Exception(f"Invalid data {profile[ptype]} returned on profile load for {ptype}!")
}:
raise Exception(
f"Invalid data {profile[ptype]} returned on profile load for {ptype}!"
)
else: else:
print("Skipping score checks for existing card") print("Skipping score checks for existing card")

View File

@ -90,9 +90,7 @@ class IIDXPendualClient(BaseClient):
raise Exception(f"Invalid node data {child} in clear rate response!") raise Exception(f"Invalid node data {child} in clear rate response!")
for v in child.value: for v in child.value:
if v < 0 or v > 101: if v < 0 or v > 101:
raise Exception( raise Exception(f"Invalid clear percent {child} in clear rate response!")
f"Invalid clear percent {child} in clear rate response!"
)
def verify_iidx22shop_getconvention(self, lid: str) -> None: def verify_iidx22shop_getconvention(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -171,9 +169,7 @@ class IIDXPendualClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/IIDX22shop") self.assert_path(resp, "response/IIDX22shop")
def verify_iidx22pc_get( def verify_iidx22pc_get(self, ref_id: str, card_id: str, lid: str) -> Dict[str, Any]:
self, ref_id: str, card_id: str, lid: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -270,9 +266,7 @@ class IIDXPendualClient(BaseClient):
"expert_point": expert_point, "expert_point": expert_point,
} }
def verify_iidx22music_getrank( def verify_iidx22music_getrank(self, extid: int) -> Dict[int, Dict[int, Dict[str, int]]]:
self, extid: int
) -> Dict[int, Dict[int, Dict[str, int]]]:
scores: Dict[int, Dict[int, Dict[str, int]]] = {} scores: Dict[int, Dict[int, Dict[str, int]]] = {}
for cltype in [0, 1]: # singles, doubles for cltype in [0, 1]: # singles, doubles
call = self.call_node() call = self.call_node()
@ -294,9 +288,7 @@ class IIDXPendualClient(BaseClient):
for child in resp.child("IIDX22music").children: for child in resp.child("IIDX22music").children:
if child.name == "m": if child.name == "m":
if child.value[0] != -1: if child.value[0] != -1:
raise Exception( raise Exception("Got non-self score back when requesting only our scores!")
"Got non-self score back when requesting only our scores!"
)
music_id = child.value[1] music_id = child.value[1]
normal_clear_status = child.value[2] normal_clear_status = child.value[2]
@ -435,9 +427,7 @@ class IIDXPendualClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
self.assert_path(resp, "response/IIDX22pc") self.assert_path(resp, "response/IIDX22pc")
def verify_iidx22music_reg( def verify_iidx22music_reg(self, extid: int, lid: str, score: Dict[str, Any]) -> None:
self, extid: int, lid: str, score: Dict[str, Any]
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -465,9 +455,7 @@ class IIDXPendualClient(BaseClient):
self.assert_path(resp, "response/IIDX22music/shopdata/@rank") self.assert_path(resp, "response/IIDX22music/shopdata/@rank")
self.assert_path(resp, "response/IIDX22music/ranklist/data") self.assert_path(resp, "response/IIDX22music/ranklist/data")
def verify_iidx22music_appoint( def verify_iidx22music_appoint(self, extid: int, musicid: int, chart: int) -> Tuple[int, bytes]:
self, extid: int, musicid: int, chart: int
) -> Tuple[int, bytes]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -587,9 +575,7 @@ class IIDXPendualClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX22music") self.assert_path(resp, "response/IIDX22music")
def verify_iidx22grade_raised( def verify_iidx22grade_raised(self, iidxid: int, shop_name: str, dantype: str) -> None:
self, iidxid: int, shop_name: str, dantype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -613,9 +599,7 @@ class IIDXPendualClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX22grade/@pnum") self.assert_path(resp, "response/IIDX22grade/@pnum")
def verify_iidx22ranking_entry( def verify_iidx22ranking_entry(self, iidxid: int, shop_name: str, coursetype: str) -> None:
self, iidxid: int, shop_name: str, coursetype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -683,32 +667,22 @@ class IIDXPendualClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_iidx22pc_reg(ref_id, card, lid) self.verify_iidx22pc_reg(ref_id, card, lid)
self.verify_iidx22pc_get(ref_id, card, lid) self.verify_iidx22pc_get(ref_id, card, lid)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -803,9 +777,7 @@ class IIDXPendualClient(BaseClient):
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
if "expected_ex_score" in score: if "expected_ex_score" in score:
expected_score = score["expected_ex_score"] expected_score = score["expected_ex_score"]
@ -834,9 +806,7 @@ class IIDXPendualClient(BaseClient):
) )
# Verify we can fetch our own ghost # Verify we can fetch our own ghost
ex_score, ghost = self.verify_iidx22music_appoint( ex_score, ghost = self.verify_iidx22music_appoint(profile["extid"], score["id"], score["chart"])
profile["extid"], score["id"], score["chart"]
)
if ex_score != expected_score: if ex_score != expected_score:
raise Exception( raise Exception(
f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\'' f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\''
@ -941,9 +911,7 @@ class IIDXPendualClient(BaseClient):
) )
scores = self.verify_iidx22music_getrank(profile["extid"]) scores = self.verify_iidx22music_getrank(profile["extid"])
if 1000 not in scores: if 1000 not in scores:
raise Exception( raise Exception(f"Didn't get expected scores back for song {1000} beginner chart!")
f"Didn't get expected scores back for song {1000} beginner chart!"
)
if 6 not in scores[1000]: if 6 not in scores[1000]:
raise Exception(f"Didn't get beginner score back for song {1000}!") raise Exception(f"Didn't get beginner score back for song {1000}!")
if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}: if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}:
@ -963,12 +931,8 @@ class IIDXPendualClient(BaseClient):
self.verify_iidx22ranking_entry(profile["extid"], newname, "secret") self.verify_iidx22ranking_entry(profile["extid"], newname, "secret")
profile = self.verify_iidx22pc_get(ref_id, card, lid) profile = self.verify_iidx22pc_get(ref_id, card, lid)
for ptype in ["ir_data", "secret_course_data"]: for ptype in ["ir_data", "secret_course_data"]:
if profile[ptype] != { if profile[ptype] != {2: {1: {"clear_status": 4, "pgnum": 1771, "gnum": 967}}}:
2: {1: {"clear_status": 4, "pgnum": 1771, "gnum": 967}} raise Exception(f"Invalid data {profile[ptype]} returned on profile load for {ptype}!")
}:
raise Exception(
f"Invalid data {profile[ptype]} returned on profile load for {ptype}!"
)
else: else:
print("Skipping score checks for existing card") print("Skipping score checks for existing card")

View File

@ -90,9 +90,7 @@ class IIDXRootageClient(BaseClient):
raise Exception(f"Invalid node data {child} in clear rate response!") raise Exception(f"Invalid node data {child} in clear rate response!")
for v in child.value: for v in child.value:
if v < 0 or v > 1001: if v < 0 or v > 1001:
raise Exception( raise Exception(f"Invalid clear percent {child} in clear rate response!")
f"Invalid clear percent {child} in clear rate response!"
)
def verify_iidx26shop_getconvention(self, lid: str) -> None: def verify_iidx26shop_getconvention(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -174,9 +172,7 @@ class IIDXRootageClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/IIDX26shop") self.assert_path(resp, "response/IIDX26shop")
def verify_iidx26pc_get( def verify_iidx26pc_get(self, ref_id: str, card_id: str, lid: str) -> Dict[str, Any]:
self, ref_id: str, card_id: str, lid: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -238,9 +234,7 @@ class IIDXRootageClient(BaseClient):
"expert_point": expert_point, "expert_point": expert_point,
} }
def verify_iidx26music_getrank( def verify_iidx26music_getrank(self, extid: int) -> Dict[int, Dict[int, Dict[str, int]]]:
self, extid: int
) -> Dict[int, Dict[int, Dict[str, int]]]:
scores: Dict[int, Dict[int, Dict[str, int]]] = {} scores: Dict[int, Dict[int, Dict[str, int]]] = {}
for cltype in [0, 1]: # singles, doubles for cltype in [0, 1]: # singles, doubles
call = self.call_node() call = self.call_node()
@ -262,9 +256,7 @@ class IIDXRootageClient(BaseClient):
for child in resp.child("IIDX26music").children: for child in resp.child("IIDX26music").children:
if child.name == "m": if child.name == "m":
if child.value[0] != -1: if child.value[0] != -1:
raise Exception( raise Exception("Got non-self score back when requesting only our scores!")
"Got non-self score back when requesting only our scores!"
)
music_id = child.value[1] music_id = child.value[1]
normal_clear_status = child.value[2] normal_clear_status = child.value[2]
@ -406,9 +398,7 @@ class IIDXRootageClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
self.assert_path(resp, "response/IIDX26pc") self.assert_path(resp, "response/IIDX26pc")
def verify_iidx26music_reg( def verify_iidx26music_reg(self, extid: int, lid: str, score: Dict[str, Any]) -> None:
self, extid: int, lid: str, score: Dict[str, Any]
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -436,9 +426,7 @@ class IIDXRootageClient(BaseClient):
self.assert_path(resp, "response/IIDX26music/shopdata/@rank") self.assert_path(resp, "response/IIDX26music/shopdata/@rank")
self.assert_path(resp, "response/IIDX26music/ranklist/data") self.assert_path(resp, "response/IIDX26music/ranklist/data")
def verify_iidx26music_appoint( def verify_iidx26music_appoint(self, extid: int, musicid: int, chart: int) -> Tuple[int, bytes]:
self, extid: int, musicid: int, chart: int
) -> Tuple[int, bytes]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -563,9 +551,7 @@ class IIDXRootageClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX26music") self.assert_path(resp, "response/IIDX26music")
def verify_iidx26grade_raised( def verify_iidx26grade_raised(self, iidxid: int, shop_name: str, dantype: str) -> None:
self, iidxid: int, shop_name: str, dantype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -650,13 +636,9 @@ class IIDXRootageClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
self.assert_path(resp, "response/IIDX26music/cpu_score_list/score_list/score") self.assert_path(resp, "response/IIDX26music/cpu_score_list/score_list/score")
self.assert_path( self.assert_path(resp, "response/IIDX26music/cpu_score_list/score_list/enable_score")
resp, "response/IIDX26music/cpu_score_list/score_list/enable_score"
)
self.assert_path(resp, "response/IIDX26music/cpu_score_list/score_list/ghost") self.assert_path(resp, "response/IIDX26music/cpu_score_list/score_list/ghost")
self.assert_path( self.assert_path(resp, "response/IIDX26music/cpu_score_list/score_list/enable_ghost")
resp, "response/IIDX26music/cpu_score_list/score_list/enable_ghost"
)
def verify_iidx26gamesystem_systeminfo(self, lid: str) -> None: def verify_iidx26gamesystem_systeminfo(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -713,32 +695,22 @@ class IIDXRootageClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_iidx26pc_reg(ref_id, card, lid) self.verify_iidx26pc_reg(ref_id, card, lid)
self.verify_iidx26pc_get(ref_id, card, lid) self.verify_iidx26pc_get(ref_id, card, lid)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -829,9 +801,7 @@ class IIDXRootageClient(BaseClient):
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
if "expected_ex_score" in score: if "expected_ex_score" in score:
expected_score = score["expected_ex_score"] expected_score = score["expected_ex_score"]
@ -860,9 +830,7 @@ class IIDXRootageClient(BaseClient):
) )
# Verify we can fetch our own ghost # Verify we can fetch our own ghost
ex_score, ghost = self.verify_iidx26music_appoint( ex_score, ghost = self.verify_iidx26music_appoint(profile["extid"], score["id"], score["chart"])
profile["extid"], score["id"], score["chart"]
)
if ex_score != expected_score: if ex_score != expected_score:
raise Exception( raise Exception(
f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\'' f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\''
@ -967,9 +935,7 @@ class IIDXRootageClient(BaseClient):
) )
scores = self.verify_iidx26music_getrank(profile["extid"]) scores = self.verify_iidx26music_getrank(profile["extid"])
if 1000 not in scores: if 1000 not in scores:
raise Exception( raise Exception(f"Didn't get expected scores back for song {1000} beginner chart!")
f"Didn't get expected scores back for song {1000} beginner chart!"
)
if 6 not in scores[1000]: if 6 not in scores[1000]:
raise Exception(f"Didn't get beginner score back for song {1000}!") raise Exception(f"Didn't get beginner score back for song {1000}!")
if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}: if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}:

View File

@ -92,9 +92,7 @@ class IIDXSinobuzClient(BaseClient):
raise Exception(f"Invalid node data {child} in clear rate response!") raise Exception(f"Invalid node data {child} in clear rate response!")
for v in child.value: for v in child.value:
if v < 0 or v > 1001: if v < 0 or v > 1001:
raise Exception( raise Exception(f"Invalid clear percent {child} in clear rate response!")
f"Invalid clear percent {child} in clear rate response!"
)
def verify_iidx24shop_getconvention(self, lid: str) -> None: def verify_iidx24shop_getconvention(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -176,9 +174,7 @@ class IIDXSinobuzClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/IIDX24shop") self.assert_path(resp, "response/IIDX24shop")
def verify_iidx24pc_get( def verify_iidx24pc_get(self, ref_id: str, card_id: str, lid: str) -> Dict[str, Any]:
self, ref_id: str, card_id: str, lid: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -298,9 +294,7 @@ class IIDXSinobuzClient(BaseClient):
"expert_point": expert_point, "expert_point": expert_point,
} }
def verify_iidx24music_getrank( def verify_iidx24music_getrank(self, extid: int) -> Dict[int, Dict[int, Dict[str, int]]]:
self, extid: int
) -> Dict[int, Dict[int, Dict[str, int]]]:
scores: Dict[int, Dict[int, Dict[str, int]]] = {} scores: Dict[int, Dict[int, Dict[str, int]]] = {}
for cltype in [0, 1]: # singles, doubles for cltype in [0, 1]: # singles, doubles
call = self.call_node() call = self.call_node()
@ -322,9 +316,7 @@ class IIDXSinobuzClient(BaseClient):
for child in resp.child("IIDX24music").children: for child in resp.child("IIDX24music").children:
if child.name == "m": if child.name == "m":
if child.value[0] != -1: if child.value[0] != -1:
raise Exception( raise Exception("Got non-self score back when requesting only our scores!")
"Got non-self score back when requesting only our scores!"
)
music_id = child.value[1] music_id = child.value[1]
normal_clear_status = child.value[2] normal_clear_status = child.value[2]
@ -454,9 +446,7 @@ class IIDXSinobuzClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
self.assert_path(resp, "response/IIDX24pc") self.assert_path(resp, "response/IIDX24pc")
def verify_iidx24music_reg( def verify_iidx24music_reg(self, extid: int, lid: str, score: Dict[str, Any]) -> None:
self, extid: int, lid: str, score: Dict[str, Any]
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -485,9 +475,7 @@ class IIDXSinobuzClient(BaseClient):
self.assert_path(resp, "response/IIDX24music/shopdata/@rank") self.assert_path(resp, "response/IIDX24music/shopdata/@rank")
self.assert_path(resp, "response/IIDX24music/ranklist/data") self.assert_path(resp, "response/IIDX24music/ranklist/data")
def verify_iidx24music_appoint( def verify_iidx24music_appoint(self, extid: int, musicid: int, chart: int) -> Tuple[int, bytes]:
self, extid: int, musicid: int, chart: int
) -> Tuple[int, bytes]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -612,9 +600,7 @@ class IIDXSinobuzClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX24music") self.assert_path(resp, "response/IIDX24music")
def verify_iidx24grade_raised( def verify_iidx24grade_raised(self, iidxid: int, shop_name: str, dantype: str) -> None:
self, iidxid: int, shop_name: str, dantype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -638,9 +624,7 @@ class IIDXSinobuzClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX24grade/@pnum") self.assert_path(resp, "response/IIDX24grade/@pnum")
def verify_iidx24ranking_entry( def verify_iidx24ranking_entry(self, iidxid: int, shop_name: str, coursetype: str) -> None:
self, iidxid: int, shop_name: str, coursetype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -730,32 +714,22 @@ class IIDXSinobuzClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_iidx24pc_reg(ref_id, card, lid) self.verify_iidx24pc_reg(ref_id, card, lid)
self.verify_iidx24pc_get(ref_id, card, lid) self.verify_iidx24pc_get(ref_id, card, lid)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -850,9 +824,7 @@ class IIDXSinobuzClient(BaseClient):
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
if "expected_ex_score" in score: if "expected_ex_score" in score:
expected_score = score["expected_ex_score"] expected_score = score["expected_ex_score"]
@ -881,9 +853,7 @@ class IIDXSinobuzClient(BaseClient):
) )
# Verify we can fetch our own ghost # Verify we can fetch our own ghost
ex_score, ghost = self.verify_iidx24music_appoint( ex_score, ghost = self.verify_iidx24music_appoint(profile["extid"], score["id"], score["chart"])
profile["extid"], score["id"], score["chart"]
)
if ex_score != expected_score: if ex_score != expected_score:
raise Exception( raise Exception(
f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\'' f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\''
@ -988,9 +958,7 @@ class IIDXSinobuzClient(BaseClient):
) )
scores = self.verify_iidx24music_getrank(profile["extid"]) scores = self.verify_iidx24music_getrank(profile["extid"])
if 1000 not in scores: if 1000 not in scores:
raise Exception( raise Exception(f"Didn't get expected scores back for song {1000} beginner chart!")
f"Didn't get expected scores back for song {1000} beginner chart!"
)
if 6 not in scores[1000]: if 6 not in scores[1000]:
raise Exception(f"Didn't get beginner score back for song {1000}!") raise Exception(f"Didn't get beginner score back for song {1000}!")
if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}: if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}:
@ -1011,12 +979,8 @@ class IIDXSinobuzClient(BaseClient):
self.verify_iidx24ranking_classicentry(profile["extid"]) self.verify_iidx24ranking_classicentry(profile["extid"])
profile = self.verify_iidx24pc_get(ref_id, card, lid) profile = self.verify_iidx24pc_get(ref_id, card, lid)
for ptype in ["ir_data", "secret_course_data", "classic_course_data"]: for ptype in ["ir_data", "secret_course_data", "classic_course_data"]:
if profile[ptype] != { if profile[ptype] != {2: {1: {"clear_status": 4, "pgnum": 1771, "gnum": 967}}}:
2: {1: {"clear_status": 4, "pgnum": 1771, "gnum": 967}} raise Exception(f"Invalid data {profile[ptype]} returned on profile load for {ptype}!")
}:
raise Exception(
f"Invalid data {profile[ptype]} returned on profile load for {ptype}!"
)
else: else:
print("Skipping score checks for existing card") print("Skipping score checks for existing card")

View File

@ -92,9 +92,7 @@ class IIDXSpadaClient(BaseClient):
raise Exception(f"Invalid node data {child} in clear rate response!") raise Exception(f"Invalid node data {child} in clear rate response!")
for v in child.value: for v in child.value:
if v < 0 or v > 101: if v < 0 or v > 101:
raise Exception( raise Exception(f"Invalid clear percent {child} in clear rate response!")
f"Invalid clear percent {child} in clear rate response!"
)
def verify_iidx21shop_getconvention(self, lid: str) -> None: def verify_iidx21shop_getconvention(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -173,9 +171,7 @@ class IIDXSpadaClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/IIDX21shop") self.assert_path(resp, "response/IIDX21shop")
def verify_iidx21pc_get( def verify_iidx21pc_get(self, ref_id: str, card_id: str, lid: str) -> Dict[str, Any]:
self, ref_id: str, card_id: str, lid: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -223,9 +219,7 @@ class IIDXSpadaClient(BaseClient):
"deller": int(resp.child("IIDX21pc/deller").attribute("deller")), "deller": int(resp.child("IIDX21pc/deller").attribute("deller")),
} }
def verify_iidx21music_getrank( def verify_iidx21music_getrank(self, extid: int) -> Dict[int, Dict[int, Dict[str, int]]]:
self, extid: int
) -> Dict[int, Dict[int, Dict[str, int]]]:
scores: Dict[int, Dict[int, Dict[str, int]]] = {} scores: Dict[int, Dict[int, Dict[str, int]]] = {}
for cltype in [0, 1]: # singles, doubles for cltype in [0, 1]: # singles, doubles
call = self.call_node() call = self.call_node()
@ -247,9 +241,7 @@ class IIDXSpadaClient(BaseClient):
for child in resp.child("IIDX21music").children: for child in resp.child("IIDX21music").children:
if child.name == "m": if child.name == "m":
if child.value[0] != -1: if child.value[0] != -1:
raise Exception( raise Exception("Got non-self score back when requesting only our scores!")
"Got non-self score back when requesting only our scores!"
)
music_id = child.value[1] music_id = child.value[1]
normal_clear_status = child.value[2] normal_clear_status = child.value[2]
@ -374,9 +366,7 @@ class IIDXSpadaClient(BaseClient):
resp = self.exchange("", call) resp = self.exchange("", call)
self.assert_path(resp, "response/IIDX21pc") self.assert_path(resp, "response/IIDX21pc")
def verify_iidx21music_reg( def verify_iidx21music_reg(self, extid: int, lid: str, score: Dict[str, Any]) -> None:
self, extid: int, lid: str, score: Dict[str, Any]
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -404,9 +394,7 @@ class IIDXSpadaClient(BaseClient):
self.assert_path(resp, "response/IIDX21music/shopdata/@rank") self.assert_path(resp, "response/IIDX21music/shopdata/@rank")
self.assert_path(resp, "response/IIDX21music/ranklist/data") self.assert_path(resp, "response/IIDX21music/ranklist/data")
def verify_iidx21music_appoint( def verify_iidx21music_appoint(self, extid: int, musicid: int, chart: int) -> Tuple[int, bytes]:
self, extid: int, musicid: int, chart: int
) -> Tuple[int, bytes]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -526,9 +514,7 @@ class IIDXSpadaClient(BaseClient):
# Verify nodes that cause crashes if they don't exist # Verify nodes that cause crashes if they don't exist
self.assert_path(resp, "response/IIDX21music") self.assert_path(resp, "response/IIDX21music")
def verify_iidx21grade_raised( def verify_iidx21grade_raised(self, iidxid: int, shop_name: str, dantype: str) -> None:
self, iidxid: int, shop_name: str, dantype: str
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -592,32 +578,22 @@ class IIDXSpadaClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_iidx21pc_reg(ref_id, card, lid) self.verify_iidx21pc_reg(ref_id, card, lid)
self.verify_iidx21pc_get(ref_id, card, lid) self.verify_iidx21pc_get(ref_id, card, lid)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -706,9 +682,7 @@ class IIDXSpadaClient(BaseClient):
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
if "expected_ex_score" in score: if "expected_ex_score" in score:
expected_score = score["expected_ex_score"] expected_score = score["expected_ex_score"]
@ -737,9 +711,7 @@ class IIDXSpadaClient(BaseClient):
) )
# Verify we can fetch our own ghost # Verify we can fetch our own ghost
ex_score, ghost = self.verify_iidx21music_appoint( ex_score, ghost = self.verify_iidx21music_appoint(profile["extid"], score["id"], score["chart"])
profile["extid"], score["id"], score["chart"]
)
if ex_score != expected_score: if ex_score != expected_score:
raise Exception( raise Exception(
f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\'' f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\''
@ -791,9 +763,7 @@ class IIDXSpadaClient(BaseClient):
) )
scores = self.verify_iidx21music_getrank(profile["extid"]) scores = self.verify_iidx21music_getrank(profile["extid"])
if 1000 not in scores: if 1000 not in scores:
raise Exception( raise Exception(f"Didn't get expected scores back for song {1000} beginner chart!")
f"Didn't get expected scores back for song {1000} beginner chart!"
)
if 6 not in scores[1000]: if 6 not in scores[1000]:
raise Exception(f"Didn't get beginner score back for song {1000}!") raise Exception(f"Didn't get beginner score back for song {1000}!")
if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}: if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}:

View File

@ -89,9 +89,7 @@ class IIDXTricoroClient(BaseClient):
raise Exception(f"Invalid node data {child} in clear rate response!") raise Exception(f"Invalid node data {child} in clear rate response!")
for v in child.value: for v in child.value:
if v < 0 or v > 101: if v < 0 or v > 101:
raise Exception( raise Exception(f"Invalid clear percent {child} in clear rate response!")
f"Invalid clear percent {child} in clear rate response!"
)
def verify_shop_getconvention(self, lid: str) -> None: def verify_shop_getconvention(self, lid: str) -> None:
call = self.call_node() call = self.call_node()
@ -238,9 +236,7 @@ class IIDXTricoroClient(BaseClient):
for child in resp.child("music").children: for child in resp.child("music").children:
if child.name == "m": if child.name == "m":
if child.value[0] != -1: if child.value[0] != -1:
raise Exception( raise Exception("Got non-self score back when requesting only our scores!")
"Got non-self score back when requesting only our scores!"
)
music_id = child.value[1] music_id = child.value[1]
normal_clear_status = child.value[2] normal_clear_status = child.value[2]
@ -368,9 +364,7 @@ class IIDXTricoroClient(BaseClient):
self.assert_path(resp, "response/music/shopdata/@rank") self.assert_path(resp, "response/music/shopdata/@rank")
self.assert_path(resp, "response/music/ranklist/data") self.assert_path(resp, "response/music/ranklist/data")
def verify_music_appoint( def verify_music_appoint(self, extid: int, musicid: int, chart: int) -> Tuple[int, bytes]:
self, extid: int, musicid: int, chart: int
) -> Tuple[int, bytes]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -554,32 +548,22 @@ class IIDXTricoroClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_pc_reg(ref_id, card, lid) self.verify_pc_reg(ref_id, card, lid)
self.verify_pc_get(ref_id, card, lid) self.verify_pc_get(ref_id, card, lid)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -668,9 +652,7 @@ class IIDXTricoroClient(BaseClient):
for score in dummyscores: for score in dummyscores:
data = scores.get(score["id"], {}).get(score["chart"], None) data = scores.get(score["id"], {}).get(score["chart"], None)
if data is None: if data is None:
raise Exception( raise Exception(f'Expected to get score back for song {score["id"]} chart {score["chart"]}!')
f'Expected to get score back for song {score["id"]} chart {score["chart"]}!'
)
if "expected_ex_score" in score: if "expected_ex_score" in score:
expected_score = score["expected_ex_score"] expected_score = score["expected_ex_score"]
@ -699,9 +681,7 @@ class IIDXTricoroClient(BaseClient):
) )
# Verify we can fetch our own ghost # Verify we can fetch our own ghost
ex_score, ghost = self.verify_music_appoint( ex_score, ghost = self.verify_music_appoint(profile["extid"], score["id"], score["chart"])
profile["extid"], score["id"], score["chart"]
)
if ex_score != expected_score: if ex_score != expected_score:
raise Exception( raise Exception(
f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\'' f'Expected a score of \'{expected_score}\' for song \'{score["id"]}\' chart \'{score["chart"]}\' but got score \'{data["ex_score"]}\''
@ -753,9 +733,7 @@ class IIDXTricoroClient(BaseClient):
) )
scores = self.verify_music_getrank(profile["extid"]) scores = self.verify_music_getrank(profile["extid"])
if 1000 not in scores: if 1000 not in scores:
raise Exception( raise Exception(f"Didn't get expected scores back for song {1000} beginner chart!")
f"Didn't get expected scores back for song {1000} beginner chart!"
)
if 6 not in scores[1000]: if 6 not in scores[1000]:
raise Exception(f"Didn't get beginner score back for song {1000}!") raise Exception(f"Didn't get beginner score back for song {1000}!")
if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}: if scores[1000][6] != {"clear_status": 4, "ex_score": -1, "miss_count": -1}:

View File

@ -53,24 +53,12 @@ class JubeatClanClient(BaseClient):
self.assert_path(resp, "response/shopinfo/data/info/born/year") self.assert_path(resp, "response/shopinfo/data/info/born/year")
self.assert_path(resp, "response/shopinfo/data/info/collection/rating_s") self.assert_path(resp, "response/shopinfo/data/info/collection/rating_s")
self.assert_path(resp, "response/shopinfo/data/info/expert_option/is_available") self.assert_path(resp, "response/shopinfo/data/info/expert_option/is_available")
self.assert_path( self.assert_path(resp, "response/shopinfo/data/info/all_music_matching/is_available")
resp, "response/shopinfo/data/info/all_music_matching/is_available" self.assert_path(resp, "response/shopinfo/data/info/all_music_matching/team/default_flag")
) self.assert_path(resp, "response/shopinfo/data/info/all_music_matching/team/redbelk_flag")
self.assert_path( self.assert_path(resp, "response/shopinfo/data/info/all_music_matching/team/cyanttle_flag")
resp, "response/shopinfo/data/info/all_music_matching/team/default_flag" self.assert_path(resp, "response/shopinfo/data/info/all_music_matching/team/greenesia_flag")
) self.assert_path(resp, "response/shopinfo/data/info/all_music_matching/team/plumpark_flag")
self.assert_path(
resp, "response/shopinfo/data/info/all_music_matching/team/redbelk_flag"
)
self.assert_path(
resp, "response/shopinfo/data/info/all_music_matching/team/cyanttle_flag"
)
self.assert_path(
resp, "response/shopinfo/data/info/all_music_matching/team/greenesia_flag"
)
self.assert_path(
resp, "response/shopinfo/data/info/all_music_matching/team/plumpark_flag"
)
self.assert_path(resp, "response/shopinfo/data/info/question_list") self.assert_path(resp, "response/shopinfo/data/info/question_list")
self.assert_path(resp, "response/shopinfo/data/info/drop_list") self.assert_path(resp, "response/shopinfo/data/info/drop_list")
self.assert_path(resp, "response/shopinfo/data/info/daily_bonus_list") self.assert_path(resp, "response/shopinfo/data/info/daily_bonus_list")
@ -138,24 +126,12 @@ class JubeatClanClient(BaseClient):
self.assert_path(resp, "response/gametop/data/info/born/year") self.assert_path(resp, "response/gametop/data/info/born/year")
self.assert_path(resp, "response/gametop/data/info/collection/rating_s") self.assert_path(resp, "response/gametop/data/info/collection/rating_s")
self.assert_path(resp, "response/gametop/data/info/expert_option/is_available") self.assert_path(resp, "response/gametop/data/info/expert_option/is_available")
self.assert_path( self.assert_path(resp, "response/gametop/data/info/all_music_matching/is_available")
resp, "response/gametop/data/info/all_music_matching/is_available" self.assert_path(resp, "response/gametop/data/info/all_music_matching/team/default_flag")
) self.assert_path(resp, "response/gametop/data/info/all_music_matching/team/redbelk_flag")
self.assert_path( self.assert_path(resp, "response/gametop/data/info/all_music_matching/team/cyanttle_flag")
resp, "response/gametop/data/info/all_music_matching/team/default_flag" self.assert_path(resp, "response/gametop/data/info/all_music_matching/team/greenesia_flag")
) self.assert_path(resp, "response/gametop/data/info/all_music_matching/team/plumpark_flag")
self.assert_path(
resp, "response/gametop/data/info/all_music_matching/team/redbelk_flag"
)
self.assert_path(
resp, "response/gametop/data/info/all_music_matching/team/cyanttle_flag"
)
self.assert_path(
resp, "response/gametop/data/info/all_music_matching/team/greenesia_flag"
)
self.assert_path(
resp, "response/gametop/data/info/all_music_matching/team/plumpark_flag"
)
self.assert_path(resp, "response/gametop/data/info/question_list") self.assert_path(resp, "response/gametop/data/info/question_list")
self.assert_path(resp, "response/gametop/data/info/drop_list") self.assert_path(resp, "response/gametop/data/info/drop_list")
self.assert_path(resp, "response/gametop/data/info/daily_bonus_list") self.assert_path(resp, "response/gametop/data/info/daily_bonus_list")
@ -234,19 +210,13 @@ class JubeatClanClient(BaseClient):
self.assert_path(resp, "response/gametop/data/player/lab_edit_seq") self.assert_path(resp, "response/gametop/data/player/lab_edit_seq")
self.assert_path(resp, "response/gametop/data/player/event_info") self.assert_path(resp, "response/gametop/data/player/event_info")
self.assert_path(resp, "response/gametop/data/player/navi/flag") self.assert_path(resp, "response/gametop/data/player/navi/flag")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/music_id")
resp, "response/gametop/data/player/fc_challenge/today/music_id"
)
self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/state") self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/state")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/music_id")
resp, "response/gametop/data/player/fc_challenge/whim/music_id"
)
self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/state") self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/state")
self.assert_path(resp, "response/gametop/data/player/official_news/news_list") self.assert_path(resp, "response/gametop/data/player/official_news/news_list")
self.assert_path(resp, "response/gametop/data/player/rivallist") self.assert_path(resp, "response/gametop/data/player/rivallist")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/free_first_play/is_available")
resp, "response/gametop/data/player/free_first_play/is_available"
)
self.assert_path(resp, "response/gametop/data/player/jbox/point") self.assert_path(resp, "response/gametop/data/player/jbox/point")
self.assert_path(resp, "response/gametop/data/player/jbox/emblem/normal/index") self.assert_path(resp, "response/gametop/data/player/jbox/emblem/normal/index")
self.assert_path(resp, "response/gametop/data/player/jbox/emblem/premium/index") self.assert_path(resp, "response/gametop/data/player/jbox/emblem/premium/index")
@ -255,9 +225,7 @@ class JubeatClanClient(BaseClient):
self.assert_path(resp, "response/gametop/data/player/born/status") self.assert_path(resp, "response/gametop/data/player/born/status")
self.assert_path(resp, "response/gametop/data/player/question_list") self.assert_path(resp, "response/gametop/data/player/question_list")
self.assert_path(resp, "response/gametop/data/player/jubility/@param") self.assert_path(resp, "response/gametop/data/player/jubility/@param")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/jubility/target_music_list")
resp, "response/gametop/data/player/jubility/target_music_list"
)
self.assert_path(resp, "response/gametop/data/player/team/@id") self.assert_path(resp, "response/gametop/data/player/team/@id")
self.assert_path(resp, "response/gametop/data/player/team/section") self.assert_path(resp, "response/gametop/data/player/team/section")
self.assert_path(resp, "response/gametop/data/player/team/street") self.assert_path(resp, "response/gametop/data/player/team/street")
@ -277,24 +245,12 @@ class JubeatClanClient(BaseClient):
self.assert_path(resp, "response/gametop/data/player/drop_list/drop/@id") self.assert_path(resp, "response/gametop/data/player/drop_list/drop/@id")
self.assert_path(resp, "response/gametop/data/player/drop_list/drop/exp") self.assert_path(resp, "response/gametop/data/player/drop_list/drop/exp")
self.assert_path(resp, "response/gametop/data/player/drop_list/drop/flag") self.assert_path(resp, "response/gametop/data/player/drop_list/drop/flag")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/drop_list/drop/item_list/item/@id")
resp, "response/gametop/data/player/drop_list/drop/item_list/item/@id" self.assert_path(resp, "response/gametop/data/player/drop_list/drop/item_list/item/num")
) self.assert_path(resp, "response/gametop/data/player/fill_in_category/no_gray_flag_list")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fill_in_category/all_yellow_flag_list")
resp, "response/gametop/data/player/drop_list/drop/item_list/item/num" self.assert_path(resp, "response/gametop/data/player/fill_in_category/full_combo_flag_list")
) self.assert_path(resp, "response/gametop/data/player/fill_in_category/excellent_flag_list")
self.assert_path(
resp, "response/gametop/data/player/fill_in_category/no_gray_flag_list"
)
self.assert_path(
resp, "response/gametop/data/player/fill_in_category/all_yellow_flag_list"
)
self.assert_path(
resp, "response/gametop/data/player/fill_in_category/full_combo_flag_list"
)
self.assert_path(
resp, "response/gametop/data/player/fill_in_category/excellent_flag_list"
)
self.assert_path(resp, "response/gametop/data/player/daily_bonus_list") self.assert_path(resp, "response/gametop/data/player/daily_bonus_list")
self.assert_path(resp, "response/gametop/data/player/ticket_list") self.assert_path(resp, "response/gametop/data/player/ticket_list")
@ -661,31 +617,21 @@ class JubeatClanClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_gametop_regist(card, ref_id) self.verify_gametop_regist(card, ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -26,13 +26,9 @@ class JubeatFestoClient(BaseClient):
self.assert_path(resp, f"response/{base}/data/info/jbox/emblem/premium/index") self.assert_path(resp, f"response/{base}/data/info/jbox/emblem/premium/index")
self.assert_path(resp, f"response/{base}/data/info/born/status") self.assert_path(resp, f"response/{base}/data/info/born/status")
self.assert_path(resp, f"response/{base}/data/info/born/year") self.assert_path(resp, f"response/{base}/data/info/born/year")
self.assert_path( self.assert_path(resp, f"response/{base}/data/info/konami_logo_50th/is_available")
resp, f"response/{base}/data/info/konami_logo_50th/is_available"
)
self.assert_path(resp, f"response/{base}/data/info/expert_option/is_available") self.assert_path(resp, f"response/{base}/data/info/expert_option/is_available")
self.assert_path( self.assert_path(resp, f"response/{base}/data/info/all_music_matching/is_available")
resp, f"response/{base}/data/info/all_music_matching/is_available"
)
self.assert_path(resp, f"response/{base}/data/info/department/shop_list") self.assert_path(resp, f"response/{base}/data/info/department/shop_list")
self.assert_path(resp, f"response/{base}/data/info/question_list") self.assert_path(resp, f"response/{base}/data/info/question_list")
# Don't bother asserting on actual courses, this is highly specific. # Don't bother asserting on actual courses, this is highly specific.
@ -171,9 +167,7 @@ class JubeatFestoClient(BaseClient):
data = Node.void("data") data = Node.void("data")
logger.add_child(data) logger.add_child(data)
data.add_child(Node.string("code", "pcbinfo_01")) data.add_child(Node.string("code", "pcbinfo_01"))
data.add_child( data.add_child(Node.string("information", "u can literally put anything here lmao"))
Node.string("information", "u can literally put anything here lmao")
)
# Swap with server # Swap with server
resp = self.exchange("", call) resp = self.exchange("", call)
@ -326,19 +320,13 @@ class JubeatFestoClient(BaseClient):
# Required nodes for events and stuff # Required nodes for events and stuff
self.assert_path(resp, "response/gametop/data/player/rivallist") self.assert_path(resp, "response/gametop/data/player/rivallist")
self.assert_path(resp, "response/gametop/data/player/lab_edit_seq") self.assert_path(resp, "response/gametop/data/player/lab_edit_seq")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/music_id")
resp, "response/gametop/data/player/fc_challenge/today/music_id"
)
self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/state") self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/state")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/music_id")
resp, "response/gametop/data/player/fc_challenge/whim/music_id"
)
self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/state") self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/state")
self.assert_path(resp, "response/gametop/data/player/official_news/news_list") self.assert_path(resp, "response/gametop/data/player/official_news/news_list")
self.assert_path(resp, "response/gametop/data/player/history/@count") self.assert_path(resp, "response/gametop/data/player/history/@count")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/free_first_play/is_available")
resp, "response/gametop/data/player/free_first_play/is_available"
)
self.assert_path(resp, "response/gametop/data/player/event_info") self.assert_path(resp, "response/gametop/data/player/event_info")
self.assert_path(resp, "response/gametop/data/player/jbox/point") self.assert_path(resp, "response/gametop/data/player/jbox/point")
self.assert_path(resp, "response/gametop/data/player/jbox/emblem/normal/index") self.assert_path(resp, "response/gametop/data/player/jbox/emblem/normal/index")
@ -369,9 +357,7 @@ class JubeatFestoClient(BaseClient):
resp, resp,
"response/gametop/data/player/fill_in_category/normal/excellent_flag_list", "response/gametop/data/player/fill_in_category/normal/excellent_flag_list",
) )
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fill_in_category/hard/no_gray_flag_list")
resp, "response/gametop/data/player/fill_in_category/hard/no_gray_flag_list"
)
self.assert_path( self.assert_path(
resp, resp,
"response/gametop/data/player/fill_in_category/hard/all_yellow_flag_list", "response/gametop/data/player/fill_in_category/hard/all_yellow_flag_list",
@ -783,31 +769,21 @@ class JubeatFestoClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_gametop_regist(card, ref_id) self.verify_gametop_regist(card, ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -41,16 +41,12 @@ class JubeatPropClient(BaseClient):
self.assert_path(resp, "response/shopinfo/data/info/share_music") self.assert_path(resp, "response/shopinfo/data/info/share_music")
self.assert_path(resp, "response/shopinfo/data/info/bonus_music") self.assert_path(resp, "response/shopinfo/data/info/bonus_music")
self.assert_path(resp, "response/shopinfo/data/info/only_now_music") self.assert_path(resp, "response/shopinfo/data/info/only_now_music")
self.assert_path( self.assert_path(resp, "response/shopinfo/data/info/fc_challenge/today/music_id")
resp, "response/shopinfo/data/info/fc_challenge/today/music_id"
)
self.assert_path(resp, "response/shopinfo/data/info/white_music_list") self.assert_path(resp, "response/shopinfo/data/info/white_music_list")
self.assert_path(resp, "response/shopinfo/data/info/open_music_list") self.assert_path(resp, "response/shopinfo/data/info/open_music_list")
self.assert_path(resp, "response/shopinfo/data/info/cabinet_survey/id") self.assert_path(resp, "response/shopinfo/data/info/cabinet_survey/id")
self.assert_path(resp, "response/shopinfo/data/info/cabinet_survey/status") self.assert_path(resp, "response/shopinfo/data/info/cabinet_survey/status")
self.assert_path( self.assert_path(resp, "response/shopinfo/data/info/kaitou_bisco/remaining_days")
resp, "response/shopinfo/data/info/kaitou_bisco/remaining_days"
)
self.assert_path(resp, "response/shopinfo/data/info/league/status") self.assert_path(resp, "response/shopinfo/data/info/league/status")
self.assert_path(resp, "response/shopinfo/data/info/bistro/bistro_id") self.assert_path(resp, "response/shopinfo/data/info/bistro/bistro_id")
self.assert_path(resp, "response/shopinfo/data/info/jbox/point") self.assert_path(resp, "response/shopinfo/data/info/jbox/point")
@ -165,27 +161,17 @@ class JubeatPropClient(BaseClient):
self.assert_path(resp, "response/gametop/data/player/cabinet_survey/read_flag") self.assert_path(resp, "response/gametop/data/player/cabinet_survey/read_flag")
self.assert_path(resp, "response/gametop/data/player/kaitou_bisco/read_flag") self.assert_path(resp, "response/gametop/data/player/kaitou_bisco/read_flag")
self.assert_path(resp, "response/gametop/data/player/navi/flag") self.assert_path(resp, "response/gametop/data/player/navi/flag")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/music_id")
resp, "response/gametop/data/player/fc_challenge/today/music_id"
)
self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/state") self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/state")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/music_id")
resp, "response/gametop/data/player/fc_challenge/whim/music_id"
)
self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/state") self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/state")
self.assert_path(resp, "response/gametop/data/player/news/checked") self.assert_path(resp, "response/gametop/data/player/news/checked")
self.assert_path(resp, "response/gametop/data/player/news/checked_flag") self.assert_path(resp, "response/gametop/data/player/news/checked_flag")
self.assert_path(resp, "response/gametop/data/player/rivallist") self.assert_path(resp, "response/gametop/data/player/rivallist")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/free_first_play/is_available")
resp, "response/gametop/data/player/free_first_play/is_available"
)
self.assert_path(resp, "response/gametop/data/player/free_first_play/point") self.assert_path(resp, "response/gametop/data/player/free_first_play/point")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/free_first_play/point_used")
resp, "response/gametop/data/player/free_first_play/point_used" self.assert_path(resp, "response/gametop/data/player/free_first_play/come_come_jbox/is_valid")
)
self.assert_path(
resp, "response/gametop/data/player/free_first_play/come_come_jbox/is_valid"
)
self.assert_path( self.assert_path(
resp, resp,
"response/gametop/data/player/free_first_play/come_come_jbox/end_time_if_paired", "response/gametop/data/player/free_first_play/come_come_jbox/end_time_if_paired",
@ -201,17 +187,13 @@ class JubeatPropClient(BaseClient):
self.assert_path(resp, "response/gametop/data/player/league/class") self.assert_path(resp, "response/gametop/data/player/league/class")
self.assert_path(resp, "response/gametop/data/player/league/subclass") self.assert_path(resp, "response/gametop/data/player/league/subclass")
self.assert_path(resp, "response/gametop/data/player/new_music") self.assert_path(resp, "response/gametop/data/player/new_music")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/eapass_privilege/emblem_list")
resp, "response/gametop/data/player/eapass_privilege/emblem_list"
)
self.assert_path(resp, "response/gametop/data/player/bonus_music/music") self.assert_path(resp, "response/gametop/data/player/bonus_music/music")
self.assert_path(resp, "response/gametop/data/player/bonus_music/event_id") self.assert_path(resp, "response/gametop/data/player/bonus_music/event_id")
self.assert_path(resp, "response/gametop/data/player/bonus_music/till_time") self.assert_path(resp, "response/gametop/data/player/bonus_music/till_time")
self.assert_path(resp, "response/gametop/data/player/bistro/chef/id") self.assert_path(resp, "response/gametop/data/player/bistro/chef/id")
self.assert_path(resp, "response/gametop/data/player/bistro/carry_over") self.assert_path(resp, "response/gametop/data/player/bistro/carry_over")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/bistro/route_list/route_count")
resp, "response/gametop/data/player/bistro/route_list/route_count"
)
self.assert_path(resp, "response/gametop/data/player/bistro/extension") self.assert_path(resp, "response/gametop/data/player/bistro/extension")
self.assert_path(resp, "response/gametop/data/player/gift_list") self.assert_path(resp, "response/gametop/data/player/gift_list")
@ -507,9 +489,7 @@ class JubeatPropClient(BaseClient):
leagueid = resp.child_value("gametop/data/league_list/league/id") leagueid = resp.child_value("gametop/data/league_list/league/id")
playernode = None playernode = None
for player in resp.child( for player in resp.child("gametop/data/league_list/league/player_list").children:
"gametop/data/league_list/league/player_list"
).children:
if player.child_value("jid") == jid: if player.child_value("jid") == jid:
playernode = player playernode = player
break break
@ -599,31 +579,21 @@ class JubeatPropClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_gametop_regist(card, ref_id) self.verify_gametop_regist(card, ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -731,13 +701,9 @@ class JubeatPropClient(BaseClient):
courses = self.verify_gametop_get_course(jid) courses = self.verify_gametop_get_course(jid)
league = self.verify_gametop_get_league(jid) league = self.verify_gametop_get_league(jid)
if len(courses) > 0: if len(courses) > 0:
raise Exception( raise Exception("Got nonzero course count without playing any courses!")
"Got nonzero course count without playing any courses!"
)
if league[1][0] != 0 or league[1][1] != 0 or league[1][2] != 0: if league[1][0] != 0 or league[1][1] != 0 or league[1][2] != 0:
raise Exception( raise Exception("Got nonzero league count without playing any league!")
"Got nonzero league count without playing any league!"
)
for score in dummyscores: for score in dummyscores:
newscore = scores[str(score["id"])][score["chart"]] newscore = scores[str(score["id"])][score["chart"]]
@ -808,14 +774,10 @@ class JubeatPropClient(BaseClient):
for course in dummycourses: for course in dummycourses:
# Find the course # Find the course
foundcourses = [ foundcourses = [c for c in courses if c["course_id"] == course["course_id"]]
c for c in courses if c["course_id"] == course["course_id"]
]
if len(foundcourses) == 0: if len(foundcourses) == 0:
raise Exception( raise Exception(f"Didn't find course by ID {course['course_id']}")
f"Didn't find course by ID {course['course_id']}"
)
foundcourse = foundcourses[0] foundcourse = foundcourses[0]
if "expected_rating" in course: if "expected_rating" in course:
@ -846,33 +808,21 @@ class JubeatPropClient(BaseClient):
time.sleep(1) time.sleep(1)
# Play a league course, save the score # Play a league course, save the score
self.verify_gameend_regist( self.verify_gameend_regist(ref_id, jid, [], {}, (league[0], (123456, 234567, 345678)))
ref_id, jid, [], {}, (league[0], (123456, 234567, 345678))
)
jid = self.verify_gametop_get_pdata(card, ref_id) jid = self.verify_gametop_get_pdata(card, ref_id)
league = self.verify_gametop_get_league(jid) league = self.verify_gametop_get_league(jid)
if ( if league[1][0] != 123456 or league[1][1] != 234567 or league[1][2] != 345678:
league[1][0] != 123456
or league[1][1] != 234567
or league[1][2] != 345678
):
raise Exception( raise Exception(
f"League score didn\t save! Got wrong values {league[1][0]}, {league[1][1]}, {league[1][2]} back!" f"League score didn\t save! Got wrong values {league[1][0]}, {league[1][1]}, {league[1][2]} back!"
) )
# Play a league course, do worse, make sure it doesn't overwrite # Play a league course, do worse, make sure it doesn't overwrite
self.verify_gameend_regist( self.verify_gameend_regist(ref_id, jid, [], {}, (league[0], (12345, 23456, 34567)))
ref_id, jid, [], {}, (league[0], (12345, 23456, 34567))
)
jid = self.verify_gametop_get_pdata(card, ref_id) jid = self.verify_gametop_get_pdata(card, ref_id)
league = self.verify_gametop_get_league(jid) league = self.verify_gametop_get_league(jid)
if ( if league[1][0] != 123456 or league[1][1] != 234567 or league[1][2] != 345678:
league[1][0] != 123456
or league[1][1] != 234567
or league[1][2] != 345678
):
raise Exception( raise Exception(
f"League score got overwritten! Got wrong values {league[1][0]}, {league[1][1]}, {league[1][2]} back!" f"League score got overwritten! Got wrong values {league[1][0]}, {league[1][1]}, {league[1][2]} back!"
) )

View File

@ -160,20 +160,14 @@ class JubeatQubellClient(BaseClient):
self.assert_path(resp, "response/gametop/data/player/lab_edit_seq") self.assert_path(resp, "response/gametop/data/player/lab_edit_seq")
self.assert_path(resp, "response/gametop/data/player/event_info") self.assert_path(resp, "response/gametop/data/player/event_info")
self.assert_path(resp, "response/gametop/data/player/navi/flag") self.assert_path(resp, "response/gametop/data/player/navi/flag")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/music_id")
resp, "response/gametop/data/player/fc_challenge/today/music_id"
)
self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/state") self.assert_path(resp, "response/gametop/data/player/fc_challenge/today/state")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/music_id")
resp, "response/gametop/data/player/fc_challenge/whim/music_id"
)
self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/state") self.assert_path(resp, "response/gametop/data/player/fc_challenge/whim/state")
self.assert_path(resp, "response/gametop/data/player/news/checked") self.assert_path(resp, "response/gametop/data/player/news/checked")
self.assert_path(resp, "response/gametop/data/player/news/checked_flag") self.assert_path(resp, "response/gametop/data/player/news/checked_flag")
self.assert_path(resp, "response/gametop/data/player/rivallist") self.assert_path(resp, "response/gametop/data/player/rivallist")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/free_first_play/is_available")
resp, "response/gametop/data/player/free_first_play/is_available"
)
self.assert_path(resp, "response/gametop/data/player/jbox/point") self.assert_path(resp, "response/gametop/data/player/jbox/point")
self.assert_path(resp, "response/gametop/data/player/jbox/emblem/normal/index") self.assert_path(resp, "response/gametop/data/player/jbox/emblem/normal/index")
self.assert_path(resp, "response/gametop/data/player/jbox/emblem/premium/index") self.assert_path(resp, "response/gametop/data/player/jbox/emblem/premium/index")
@ -189,28 +183,14 @@ class JubeatQubellClient(BaseClient):
self.assert_path(resp, "response/gametop/data/player/digdig/eternal/ratio") self.assert_path(resp, "response/gametop/data/player/digdig/eternal/ratio")
self.assert_path(resp, "response/gametop/data/player/digdig/eternal/used_point") self.assert_path(resp, "response/gametop/data/player/digdig/eternal/used_point")
self.assert_path(resp, "response/gametop/data/player/digdig/eternal/point") self.assert_path(resp, "response/gametop/data/player/digdig/eternal/point")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/digdig/eternal/excavated_point")
resp, "response/gametop/data/player/digdig/eternal/excavated_point"
)
self.assert_path(resp, "response/gametop/data/player/digdig/eternal/cube/state") self.assert_path(resp, "response/gametop/data/player/digdig/eternal/cube/state")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/digdig/eternal/cube/item/kind")
resp, "response/gametop/data/player/digdig/eternal/cube/item/kind" self.assert_path(resp, "response/gametop/data/player/digdig/eternal/cube/item/value")
) self.assert_path(resp, "response/gametop/data/player/digdig/eternal/cube/norma/till_time")
self.assert_path( self.assert_path(resp, "response/gametop/data/player/digdig/eternal/cube/norma/kind")
resp, "response/gametop/data/player/digdig/eternal/cube/item/value" self.assert_path(resp, "response/gametop/data/player/digdig/eternal/cube/norma/value")
) self.assert_path(resp, "response/gametop/data/player/digdig/eternal/cube/norma/param")
self.assert_path(
resp, "response/gametop/data/player/digdig/eternal/cube/norma/till_time"
)
self.assert_path(
resp, "response/gametop/data/player/digdig/eternal/cube/norma/kind"
)
self.assert_path(
resp, "response/gametop/data/player/digdig/eternal/cube/norma/value"
)
self.assert_path(
resp, "response/gametop/data/player/digdig/eternal/cube/norma/param"
)
# Return the jid # Return the jid
return resp.child_value("gametop/data/player/jid") return resp.child_value("gametop/data/player/jid")
@ -497,31 +477,21 @@ class JubeatQubellClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_gametop_regist(card, ref_id) self.verify_gametop_regist(card, ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -134,9 +134,7 @@ class JubeatSaucerClient(BaseClient):
# Return the jid # Return the jid
return resp.child_value("gametop/data/player/jid") return resp.child_value("gametop/data/player/jid")
def verify_gameend_regist( def verify_gameend_regist(self, ref_id: str, jid: int, scores: List[Dict[str, Any]]) -> None:
self, ref_id: str, jid: int, scores: List[Dict[str, Any]]
) -> None:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -378,31 +376,21 @@ class JubeatSaucerClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_gametop_regist(card, ref_id) self.verify_gametop_regist(card, ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -457,31 +457,21 @@ class JubeatSaucerFulfillClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_gametop_regist(card, ref_id) self.verify_gametop_regist(card, ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:
@ -583,9 +573,7 @@ class JubeatSaucerFulfillClient(BaseClient):
scores = self.verify_gametop_get_mdata(jid) scores = self.verify_gametop_get_mdata(jid)
courses = self.verify_gametop_get_course(jid) courses = self.verify_gametop_get_course(jid)
if len(courses) > 0: if len(courses) > 0:
raise Exception( raise Exception("Got nonzero course count without playing any courses!")
"Got nonzero course count without playing any courses!"
)
for score in dummyscores: for score in dummyscores:
newscore = scores[str(score["id"])][score["chart"]] newscore = scores[str(score["id"])][score["chart"]]
@ -656,14 +644,10 @@ class JubeatSaucerFulfillClient(BaseClient):
for course in dummycourses: for course in dummycourses:
# Find the course # Find the course
foundcourses = [ foundcourses = [c for c in courses if c["course_id"] == course["course_id"]]
c for c in courses if c["course_id"] == course["course_id"]
]
if len(foundcourses) == 0: if len(foundcourses) == 0:
raise Exception( raise Exception(f"Didn't find course by ID {course['course_id']}")
f"Didn't find course by ID {course['course_id']}"
)
foundcourse = foundcourses[0] foundcourse = foundcourses[0]
if "expected_rating" in course: if "expected_rating" in course:

View File

@ -318,32 +318,22 @@ class MetalGearArcadeClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# MGA doesn't read a new profile, it just writes out CSV for a blank one # MGA doesn't read a new profile, it just writes out CSV for a blank one
self.verify_usergamedata_send(ref_id, msg_type="new") self.verify_usergamedata_send(ref_id, msg_type="new")
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -165,9 +165,7 @@ class Museca1Client(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/game_3/result") self.assert_path(resp, "response/game_3/result")
def verify_game_save( def verify_game_save(self, location: str, refid: str, packet: int, block: int, blaster_energy: int) -> None:
self, location: str, refid: str, packet: int, block: int, blaster_energy: int
) -> None:
call = self.call_node() call = self.call_node()
game = Node.void("game_3") game = Node.void("game_3")
@ -230,9 +228,7 @@ class Museca1Client(BaseClient):
self.assert_path(resp, "response/game_3/music_limited") self.assert_path(resp, "response/game_3/music_limited")
self.assert_path(resp, "response/game_3/event") self.assert_path(resp, "response/game_3/event")
def verify_game_load( def verify_game_load(self, cardid: str, refid: str, msg_type: str) -> Dict[str, Any]:
self, cardid: str, refid: str, msg_type: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
game = Node.void("game_3") game = Node.void("game_3")
@ -354,9 +350,7 @@ class Museca1Client(BaseClient):
return scores return scores
def verify_game_save_m( def verify_game_save_m(self, location: str, refid: str, score: Dict[str, int]) -> None:
self, location: str, refid: str, score: Dict[str, int]
) -> None:
call = self.call_node() call = self.call_node()
game = Node.void("game_3") game = Node.void("game_3")
@ -428,17 +422,11 @@ class Museca1Client(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Museca doesn't read the new profile, it asks for the profile itself after calling new # Museca doesn't read the new profile, it asks for the profile itself after calling new
self.verify_game_load(card, ref_id, msg_type="new") self.verify_game_load(card, ref_id, msg_type="new")
@ -446,16 +434,12 @@ class Museca1Client(BaseClient):
self.verify_game_load(card, ref_id, msg_type="existing") self.verify_game_load(card, ref_id, msg_type="existing")
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify account freezing # Verify account freezing
@ -467,34 +451,24 @@ class Museca1Client(BaseClient):
# Verify profile loading and saving # Verify profile loading and saving
profile = self.verify_game_load(card, ref_id, msg_type="existing") profile = self.verify_game_load(card, ref_id, msg_type="existing")
if profile["name"] != self.NAME: if profile["name"] != self.NAME:
raise Exception( raise Exception(f'Profile has incorrect name {profile["name"]} associated with it!')
f'Profile has incorrect name {profile["name"]} associated with it!'
)
if profile["packet"] != 0: if profile["packet"] != 0:
raise Exception("Profile has nonzero blocks associated with it!") raise Exception("Profile has nonzero blocks associated with it!")
if profile["block"] != 0: if profile["block"] != 0:
raise Exception("Profile has nonzero packets associated with it!") raise Exception("Profile has nonzero packets associated with it!")
if profile["blaster_energy"] != 0: if profile["blaster_energy"] != 0:
raise Exception( raise Exception("Profile has nonzero blaster energy associated with it!")
"Profile has nonzero blaster energy associated with it!"
)
self.verify_game_save( self.verify_game_save(location, ref_id, packet=123, block=234, blaster_energy=42)
location, ref_id, packet=123, block=234, blaster_energy=42
)
profile = self.verify_game_load(card, ref_id, msg_type="existing") profile = self.verify_game_load(card, ref_id, msg_type="existing")
if profile["name"] != self.NAME: if profile["name"] != self.NAME:
raise Exception( raise Exception(f'Profile has incorrect name {profile["name"]} associated with it!')
f'Profile has incorrect name {profile["name"]} associated with it!'
)
if profile["packet"] != 123: if profile["packet"] != 123:
raise Exception("Profile has invalid blocks associated with it!") raise Exception("Profile has invalid blocks associated with it!")
if profile["block"] != 234: if profile["block"] != 234:
raise Exception("Profile has invalid packets associated with it!") raise Exception("Profile has invalid packets associated with it!")
if profile["blaster_energy"] != 42: if profile["blaster_energy"] != 42:
raise Exception( raise Exception("Profile has invalid blaster energy associated with it!")
"Profile has invalid blaster energy associated with it!"
)
# Verify empty profile has no scores on it # Verify empty profile has no scores on it
scores = self.verify_game_load_m(ref_id) scores = self.verify_game_load_m(ref_id)
@ -567,17 +541,12 @@ class Museca1Client(BaseClient):
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]

View File

@ -165,9 +165,7 @@ class Museca1PlusClient(BaseClient):
# Verify that response is correct # Verify that response is correct
self.assert_path(resp, "response/game_3/result") self.assert_path(resp, "response/game_3/result")
def verify_game_save( def verify_game_save(self, location: str, refid: str, packet: int, block: int, blaster_energy: int) -> None:
self, location: str, refid: str, packet: int, block: int, blaster_energy: int
) -> None:
call = self.call_node() call = self.call_node()
game = Node.void("game_3") game = Node.void("game_3")
@ -230,9 +228,7 @@ class Museca1PlusClient(BaseClient):
self.assert_path(resp, "response/game_3/music_limited") self.assert_path(resp, "response/game_3/music_limited")
self.assert_path(resp, "response/game_3/event") self.assert_path(resp, "response/game_3/event")
def verify_game_load( def verify_game_load(self, cardid: str, refid: str, msg_type: str) -> Dict[str, Any]:
self, cardid: str, refid: str, msg_type: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
game = Node.void("game_3") game = Node.void("game_3")
@ -369,9 +365,7 @@ class Museca1PlusClient(BaseClient):
return scores return scores
def verify_game_save_m( def verify_game_save_m(self, location: str, refid: str, score: Dict[str, int]) -> None:
self, location: str, refid: str, score: Dict[str, int]
) -> None:
call = self.call_node() call = self.call_node()
game = Node.void("game_3") game = Node.void("game_3")
@ -443,17 +437,11 @@ class Museca1PlusClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Museca doesn't read the new profile, it asks for the profile itself after calling new # Museca doesn't read the new profile, it asks for the profile itself after calling new
self.verify_game_load(card, ref_id, msg_type="new") self.verify_game_load(card, ref_id, msg_type="new")
@ -461,16 +449,12 @@ class Museca1PlusClient(BaseClient):
self.verify_game_load(card, ref_id, msg_type="existing") self.verify_game_load(card, ref_id, msg_type="existing")
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify account freezing # Verify account freezing
@ -485,34 +469,24 @@ class Museca1PlusClient(BaseClient):
# Verify profile loading and saving # Verify profile loading and saving
profile = self.verify_game_load(card, ref_id, msg_type="existing") profile = self.verify_game_load(card, ref_id, msg_type="existing")
if profile["name"] != self.NAME: if profile["name"] != self.NAME:
raise Exception( raise Exception(f'Profile has incorrect name {profile["name"]} associated with it!')
f'Profile has incorrect name {profile["name"]} associated with it!'
)
if profile["packet"] != 0: if profile["packet"] != 0:
raise Exception("Profile has nonzero blocks associated with it!") raise Exception("Profile has nonzero blocks associated with it!")
if profile["block"] != 0: if profile["block"] != 0:
raise Exception("Profile has nonzero packets associated with it!") raise Exception("Profile has nonzero packets associated with it!")
if profile["blaster_energy"] != 0: if profile["blaster_energy"] != 0:
raise Exception( raise Exception("Profile has nonzero blaster energy associated with it!")
"Profile has nonzero blaster energy associated with it!"
)
self.verify_game_save( self.verify_game_save(location, ref_id, packet=123, block=234, blaster_energy=42)
location, ref_id, packet=123, block=234, blaster_energy=42
)
profile = self.verify_game_load(card, ref_id, msg_type="existing") profile = self.verify_game_load(card, ref_id, msg_type="existing")
if profile["name"] != self.NAME: if profile["name"] != self.NAME:
raise Exception( raise Exception(f'Profile has incorrect name {profile["name"]} associated with it!')
f'Profile has incorrect name {profile["name"]} associated with it!'
)
if profile["packet"] != 123: if profile["packet"] != 123:
raise Exception("Profile has invalid blocks associated with it!") raise Exception("Profile has invalid blocks associated with it!")
if profile["block"] != 234: if profile["block"] != 234:
raise Exception("Profile has invalid packets associated with it!") raise Exception("Profile has invalid packets associated with it!")
if profile["blaster_energy"] != 42: if profile["blaster_energy"] != 42:
raise Exception( raise Exception("Profile has invalid blaster energy associated with it!")
"Profile has invalid blaster energy associated with it!"
)
# Verify empty profile has no scores on it # Verify empty profile has no scores on it
scores = self.verify_game_load_m(ref_id) scores = self.verify_game_load_m(ref_id)
@ -585,17 +559,12 @@ class Museca1PlusClient(BaseClient):
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]

View File

@ -118,9 +118,7 @@ class PopnMusicEclaleClient(BaseClient):
self.assert_path(resp, "response/player23/stamp/stamp_id") self.assert_path(resp, "response/player23/stamp/stamp_id")
self.assert_path(resp, "response/player23/stamp/cnt") self.assert_path(resp, "response/player23/stamp/cnt")
def verify_player23_read( def verify_player23_read(self, ref_id: str, msg_type: str) -> Dict[str, Dict[int, Dict[str, int]]]:
self, ref_id: str, msg_type: str
) -> Dict[str, Dict[int, Dict[str, int]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -139,9 +137,7 @@ class PopnMusicEclaleClient(BaseClient):
self.assert_path(resp, "response/player23/result") self.assert_path(resp, "response/player23/result")
status = resp.child_value("player23/result") status = resp.child_value("player23/result")
if status != 2: if status != 2:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
return { return {
"medals": {}, "medals": {},
@ -156,9 +152,7 @@ class PopnMusicEclaleClient(BaseClient):
self.assert_path(resp, "response/player23/result") self.assert_path(resp, "response/player23/result")
status = resp.child_value("player23/result") status = resp.child_value("player23/result")
if status != 0: if status != 0:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
name = resp.child_value("player23/account/name") name = resp.child_value("player23/account/name")
if name != self.NAME: if name != self.NAME:
raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'") raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'")
@ -192,9 +186,7 @@ class PopnMusicEclaleClient(BaseClient):
else: else:
raise Exception(f"Unrecognized message type '{msg_type}'") raise Exception(f"Unrecognized message type '{msg_type}'")
def verify_player23_read_score( def verify_player23_read_score(self, ref_id: str) -> Dict[str, Dict[int, Dict[int, int]]]:
self, ref_id: str
) -> Dict[str, Dict[int, Dict[int, int]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -418,32 +410,22 @@ class PopnMusicEclaleClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_player23_read(ref_id, msg_type="new") self.verify_player23_read(ref_id, msg_type="new")
self.verify_player23_new(ref_id) self.verify_player23_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify proper handling of basic stuff # Verify proper handling of basic stuff
@ -489,9 +471,7 @@ class PopnMusicEclaleClient(BaseClient):
raise Exception("Expecting to see chara ID 5 to have type 2 in characters!") raise Exception("Expecting to see chara ID 5 to have type 2 in characters!")
# Verify purchases work # Verify purchases work
self.verify_player23_buy( self.verify_player23_buy(ref_id, item={"id": 6, "type": 7, "param": 8, "lumina": 400, "price": 250})
ref_id, item={"id": 6, "type": 7, "param": 8, "lumina": 400, "price": 250}
)
unlocks = self.verify_player23_read(ref_id, msg_type="query") unlocks = self.verify_player23_read(ref_id, msg_type="query")
if 6 not in unlocks["items"]: if 6 not in unlocks["items"]:
raise Exception("Expecting to see item ID 6 in items!") raise Exception("Expecting to see item ID 6 in items!")
@ -500,9 +480,7 @@ class PopnMusicEclaleClient(BaseClient):
if unlocks["items"][6]["param"] != 8: if unlocks["items"][6]["param"] != 8:
raise Exception("Expecting to see item ID 6 to have param 8 in items!") raise Exception("Expecting to see item ID 6 to have param 8 in items!")
if unlocks["lumina"][0]["lumina"] != 150: if unlocks["lumina"][0]["lumina"] != 150:
raise Exception( raise Exception(f'Got wrong value for lumina {unlocks["lumina"][0]["lumina"]} after purchase!')
f'Got wrong value for lumina {unlocks["lumina"][0]["lumina"]} after purchase!'
)
if cardid is None: if cardid is None:
# Verify score handling # Verify score handling

View File

@ -115,9 +115,7 @@ class PopnMusicFantasiaClient(BaseClient):
if len(node.value) != length: if len(node.value) != length:
raise Exception(f"Node '{name}' is wrong array length!") raise Exception(f"Node '{name}' is wrong array length!")
def verify_playerdata_get( def verify_playerdata_get(self, ref_id: str, msg_type: str) -> Optional[Dict[str, Any]]:
self, ref_id: str, msg_type: str
) -> Optional[Dict[str, Any]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -125,9 +123,7 @@ class PopnMusicFantasiaClient(BaseClient):
call.add_child(playerdata) call.add_child(playerdata)
playerdata.set_attribute("method", "get") playerdata.set_attribute("method", "get")
if msg_type == "new": if msg_type == "new":
playerdata.set_attribute( playerdata.set_attribute("model", self.config["old_profile_model"].split(":")[0])
"model", self.config["old_profile_model"].split(":")[0]
)
playerdata.add_child(Node.string("ref_id", ref_id)) playerdata.add_child(Node.string("ref_id", ref_id))
playerdata.add_child(Node.string("shop_name", "")) playerdata.add_child(Node.string("shop_name", ""))
@ -143,9 +139,7 @@ class PopnMusicFantasiaClient(BaseClient):
status = int(resp.child("playerdata").attribute("status")) status = int(resp.child("playerdata").attribute("status"))
if status != 109: if status != 109:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
# No score data # No score data
return None return None
@ -181,11 +175,7 @@ class PopnMusicFantasiaClient(BaseClient):
) )
medals = [ medals = [
transform_medals(medal) transform_medals(medal) for medal in resp.child("playerdata").child("base").child("clear_medal").value
for medal in resp.child("playerdata")
.child("base")
.child("clear_medal")
.value
] ]
hiscore = resp.child("playerdata").child("hiscore").value hiscore = resp.child("playerdata").child("hiscore").value
@ -202,8 +192,7 @@ class PopnMusicFantasiaClient(BaseClient):
hiscores.append(value & 0x1FFFF) hiscores.append(value & 0x1FFFF)
scores = [ scores = [
(hiscores[x], hiscores[x + 1], hiscores[x + 2], hiscores[x + 3]) (hiscores[x], hiscores[x + 1], hiscores[x + 2], hiscores[x + 3]) for x in range(0, len(hiscores), 4)
for x in range(0, len(hiscores), 4)
] ]
return {"medals": medals, "scores": scores} return {"medals": medals, "scores": scores}
@ -240,9 +229,7 @@ class PopnMusicFantasiaClient(BaseClient):
}[score["chart"]], }[score["chart"]],
) )
) )
stage.add_child( stage.add_child(Node.u16("n_data", (score["medal"] << (4 * score["chart"]))))
Node.u16("n_data", (score["medal"] << (4 * score["chart"])))
)
stage.add_child(Node.u8("e_data", 0)) stage.add_child(Node.u8("e_data", 0))
stage.add_child(Node.s32("score", score["score"])) stage.add_child(Node.s32("score", score["score"]))
stage.add_child(Node.u8("ojama_1", 0)) stage.add_child(Node.u8("ojama_1", 0))
@ -325,32 +312,22 @@ class PopnMusicFantasiaClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_playerdata_get(ref_id, msg_type="new") self.verify_playerdata_get(ref_id, msg_type="new")
self.verify_playerdata_new(ref_id) self.verify_playerdata_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -136,9 +136,7 @@ class PopnMusicKaimeiClient(BaseClient):
self.assert_path(resp, "response/player24/stamp/stamp_id") self.assert_path(resp, "response/player24/stamp/stamp_id")
self.assert_path(resp, "response/player24/stamp/cnt") self.assert_path(resp, "response/player24/stamp/cnt")
def verify_player24_read( def verify_player24_read(self, ref_id: str, msg_type: str) -> Dict[str, Dict[int, Dict[str, int]]]:
self, ref_id: str, msg_type: str
) -> Dict[str, Dict[int, Dict[str, int]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -157,9 +155,7 @@ class PopnMusicKaimeiClient(BaseClient):
self.assert_path(resp, "response/player24/result") self.assert_path(resp, "response/player24/result")
status = resp.child_value("player24/result") status = resp.child_value("player24/result")
if status != 2: if status != 2:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
return { return {
"items": {}, "items": {},
@ -173,9 +169,7 @@ class PopnMusicKaimeiClient(BaseClient):
self.assert_path(resp, "response/player24/result") self.assert_path(resp, "response/player24/result")
status = resp.child_value("player24/result") status = resp.child_value("player24/result")
if status != 0: if status != 0:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
name = resp.child_value("player24/account/name") name = resp.child_value("player24/account/name")
if name != self.NAME: if name != self.NAME:
raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'") raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'")
@ -207,16 +201,12 @@ class PopnMusicKaimeiClient(BaseClient):
"items": items, "items": items,
"characters": charas, "characters": charas,
"courses": courses, "courses": courses,
"points": { "points": {0: {"points": resp.child_value("player24/account/player_point")}},
0: {"points": resp.child_value("player24/account/player_point")}
},
} }
else: else:
raise Exception(f"Unrecognized message type '{msg_type}'") raise Exception(f"Unrecognized message type '{msg_type}'")
def verify_player24_read_score( def verify_player24_read_score(self, ref_id: str) -> Dict[str, Dict[int, Dict[int, int]]]:
self, ref_id: str
) -> Dict[str, Dict[int, Dict[int, int]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -468,32 +458,22 @@ class PopnMusicKaimeiClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_player24_read(ref_id, msg_type="new") self.verify_player24_read(ref_id, msg_type="new")
self.verify_player24_new(ref_id) self.verify_player24_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify proper handling of basic stuff # Verify proper handling of basic stuff
@ -531,9 +511,7 @@ class PopnMusicKaimeiClient(BaseClient):
if 5 not in unlocks["characters"]: if 5 not in unlocks["characters"]:
raise Exception("Expecting to see chara ID 5 in characters!") raise Exception("Expecting to see chara ID 5 in characters!")
if unlocks["characters"][5]["friendship"] != 420: if unlocks["characters"][5]["friendship"] != 420:
raise Exception( raise Exception("Expecting to see chara ID 5 to have type 2 in characters!")
"Expecting to see chara ID 5 to have type 2 in characters!"
)
# Verify purchases work # Verify purchases work
self.verify_player24_buy( self.verify_player24_buy(
@ -548,9 +526,7 @@ class PopnMusicKaimeiClient(BaseClient):
if unlocks["items"][6]["param"] != 8: if unlocks["items"][6]["param"] != 8:
raise Exception("Expecting to see item ID 6 to have param 8 in items!") raise Exception("Expecting to see item ID 6 to have param 8 in items!")
if unlocks["points"][0]["points"] != 150: if unlocks["points"][0]["points"] != 150:
raise Exception( raise Exception(f'Got wrong value for points {unlocks["points"][0]["points"]} after purchase!')
f'Got wrong value for points {unlocks["points"][0]["points"]} after purchase!'
)
# Verify course handling # Verify course handling
self.verify_player24_update_ranking(ref_id, location) self.verify_player24_update_ranking(ref_id, location)
@ -558,25 +534,15 @@ class PopnMusicKaimeiClient(BaseClient):
if 12345 not in unlocks["courses"]: if 12345 not in unlocks["courses"]:
raise Exception("Expecting to see course ID 12345 in courses!") raise Exception("Expecting to see course ID 12345 in courses!")
if unlocks["courses"][12345]["clear_type"] != 7: if unlocks["courses"][12345]["clear_type"] != 7:
raise Exception( raise Exception("Expecting to see item ID 12345 to have clear_type 7 in courses!")
"Expecting to see item ID 12345 to have clear_type 7 in courses!"
)
if unlocks["courses"][12345]["clear_rank"] != 5: if unlocks["courses"][12345]["clear_rank"] != 5:
raise Exception( raise Exception("Expecting to see item ID 12345 to have clear_rank 5 in courses!")
"Expecting to see item ID 12345 to have clear_rank 5 in courses!"
)
if unlocks["courses"][12345]["total_score"] != 86000: if unlocks["courses"][12345]["total_score"] != 86000:
raise Exception( raise Exception("Expecting to see item ID 12345 to have total_score 86000 in courses!")
"Expecting to see item ID 12345 to have total_score 86000 in courses!"
)
if unlocks["courses"][12345]["count"] != 1: if unlocks["courses"][12345]["count"] != 1:
raise Exception( raise Exception("Expecting to see item ID 12345 to have count 1 in courses!")
"Expecting to see item ID 12345 to have count 1 in courses!"
)
if unlocks["courses"][12345]["sheet_num"] != 2: if unlocks["courses"][12345]["sheet_num"] != 2:
raise Exception( raise Exception("Expecting to see item ID 12345 to have sheet_num 2 in courses!")
"Expecting to see item ID 12345 to have sheet_num 2 in courses!"
)
# Verify score handling # Verify score handling
scores = self.verify_player24_read_score(ref_id) scores = self.verify_player24_read_score(ref_id)

View File

@ -49,9 +49,7 @@ class PopnMusicLapistoriaClient(BaseClient):
if node.data_type != "void": if node.data_type != "void":
raise Exception(f"Node '{name}' has wrong data type!") raise Exception(f"Node '{name}' has wrong data type!")
def verify_player22_read( def verify_player22_read(self, ref_id: str, msg_type: str) -> Optional[Dict[str, Any]]:
self, ref_id: str, msg_type: str
) -> Optional[Dict[str, Any]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -72,9 +70,7 @@ class PopnMusicLapistoriaClient(BaseClient):
status = int(resp.child("player22").attribute("status")) status = int(resp.child("player22").attribute("status"))
if status != 109: if status != 109:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
# No score data # No score data
return None return None
@ -287,32 +283,22 @@ class PopnMusicLapistoriaClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_player22_read(ref_id, msg_type="new") self.verify_player22_read(ref_id, msg_type="new")
self.verify_player22_new(ref_id) self.verify_player22_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -136,9 +136,7 @@ class PopnMusicPeaceClient(BaseClient):
self.assert_path(resp, "response/player24/stamp/stamp_id") self.assert_path(resp, "response/player24/stamp/stamp_id")
self.assert_path(resp, "response/player24/stamp/cnt") self.assert_path(resp, "response/player24/stamp/cnt")
def verify_player24_read( def verify_player24_read(self, ref_id: str, msg_type: str) -> Dict[str, Dict[int, Dict[str, int]]]:
self, ref_id: str, msg_type: str
) -> Dict[str, Dict[int, Dict[str, int]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -157,9 +155,7 @@ class PopnMusicPeaceClient(BaseClient):
self.assert_path(resp, "response/player24/result") self.assert_path(resp, "response/player24/result")
status = resp.child_value("player24/result") status = resp.child_value("player24/result")
if status != 2: if status != 2:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
return { return {
"items": {}, "items": {},
@ -173,9 +169,7 @@ class PopnMusicPeaceClient(BaseClient):
self.assert_path(resp, "response/player24/result") self.assert_path(resp, "response/player24/result")
status = resp.child_value("player24/result") status = resp.child_value("player24/result")
if status != 0: if status != 0:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
name = resp.child_value("player24/account/name") name = resp.child_value("player24/account/name")
if name != self.NAME: if name != self.NAME:
raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'") raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'")
@ -207,16 +201,12 @@ class PopnMusicPeaceClient(BaseClient):
"items": items, "items": items,
"characters": charas, "characters": charas,
"courses": courses, "courses": courses,
"points": { "points": {0: {"points": resp.child_value("player24/account/player_point")}},
0: {"points": resp.child_value("player24/account/player_point")}
},
} }
else: else:
raise Exception(f"Unrecognized message type '{msg_type}'") raise Exception(f"Unrecognized message type '{msg_type}'")
def verify_player24_read_score( def verify_player24_read_score(self, ref_id: str) -> Dict[str, Dict[int, Dict[int, int]]]:
self, ref_id: str
) -> Dict[str, Dict[int, Dict[int, int]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -468,32 +458,22 @@ class PopnMusicPeaceClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_player24_read(ref_id, msg_type="new") self.verify_player24_read(ref_id, msg_type="new")
self.verify_player24_new(ref_id) self.verify_player24_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify proper handling of basic stuff # Verify proper handling of basic stuff
@ -531,9 +511,7 @@ class PopnMusicPeaceClient(BaseClient):
if 5 not in unlocks["characters"]: if 5 not in unlocks["characters"]:
raise Exception("Expecting to see chara ID 5 in characters!") raise Exception("Expecting to see chara ID 5 in characters!")
if unlocks["characters"][5]["friendship"] != 420: if unlocks["characters"][5]["friendship"] != 420:
raise Exception( raise Exception("Expecting to see chara ID 5 to have type 2 in characters!")
"Expecting to see chara ID 5 to have type 2 in characters!"
)
# Verify purchases work # Verify purchases work
self.verify_player24_buy( self.verify_player24_buy(
@ -548,9 +526,7 @@ class PopnMusicPeaceClient(BaseClient):
if unlocks["items"][6]["param"] != 8: if unlocks["items"][6]["param"] != 8:
raise Exception("Expecting to see item ID 6 to have param 8 in items!") raise Exception("Expecting to see item ID 6 to have param 8 in items!")
if unlocks["points"][0]["points"] != 150: if unlocks["points"][0]["points"] != 150:
raise Exception( raise Exception(f'Got wrong value for points {unlocks["points"][0]["points"]} after purchase!')
f'Got wrong value for points {unlocks["points"][0]["points"]} after purchase!'
)
# Verify course handling # Verify course handling
self.verify_player24_update_ranking(ref_id, location) self.verify_player24_update_ranking(ref_id, location)
@ -558,25 +534,15 @@ class PopnMusicPeaceClient(BaseClient):
if 12345 not in unlocks["courses"]: if 12345 not in unlocks["courses"]:
raise Exception("Expecting to see course ID 12345 in courses!") raise Exception("Expecting to see course ID 12345 in courses!")
if unlocks["courses"][12345]["clear_type"] != 7: if unlocks["courses"][12345]["clear_type"] != 7:
raise Exception( raise Exception("Expecting to see item ID 12345 to have clear_type 7 in courses!")
"Expecting to see item ID 12345 to have clear_type 7 in courses!"
)
if unlocks["courses"][12345]["clear_rank"] != 5: if unlocks["courses"][12345]["clear_rank"] != 5:
raise Exception( raise Exception("Expecting to see item ID 12345 to have clear_rank 5 in courses!")
"Expecting to see item ID 12345 to have clear_rank 5 in courses!"
)
if unlocks["courses"][12345]["total_score"] != 86000: if unlocks["courses"][12345]["total_score"] != 86000:
raise Exception( raise Exception("Expecting to see item ID 12345 to have total_score 86000 in courses!")
"Expecting to see item ID 12345 to have total_score 86000 in courses!"
)
if unlocks["courses"][12345]["count"] != 1: if unlocks["courses"][12345]["count"] != 1:
raise Exception( raise Exception("Expecting to see item ID 12345 to have count 1 in courses!")
"Expecting to see item ID 12345 to have count 1 in courses!"
)
if unlocks["courses"][12345]["sheet_num"] != 2: if unlocks["courses"][12345]["sheet_num"] != 2:
raise Exception( raise Exception("Expecting to see item ID 12345 to have sheet_num 2 in courses!")
"Expecting to see item ID 12345 to have sheet_num 2 in courses!"
)
# Verify score handling # Verify score handling
scores = self.verify_player24_read_score(ref_id) scores = self.verify_player24_read_score(ref_id)

View File

@ -80,9 +80,7 @@ class PopnMusicSunnyParkClient(BaseClient):
if len(node.value) != 5: if len(node.value) != 5:
raise Exception(f"Node '{name}' is wrong array length!") raise Exception(f"Node '{name}' is wrong array length!")
def verify_playerdata_get( def verify_playerdata_get(self, ref_id: str, msg_type: str) -> Optional[Dict[str, Any]]:
self, ref_id: str, msg_type: str
) -> Optional[Dict[str, Any]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -90,9 +88,7 @@ class PopnMusicSunnyParkClient(BaseClient):
call.add_child(playerdata) call.add_child(playerdata)
playerdata.set_attribute("method", "get") playerdata.set_attribute("method", "get")
if msg_type == "new": if msg_type == "new":
playerdata.set_attribute( playerdata.set_attribute("model", self.config["old_profile_model"].split(":")[0])
"model", self.config["old_profile_model"].split(":")[0]
)
playerdata.add_child(Node.string("ref_id", ref_id)) playerdata.add_child(Node.string("ref_id", ref_id))
playerdata.add_child(Node.string("shop_name", "")) playerdata.add_child(Node.string("shop_name", ""))
@ -115,9 +111,7 @@ class PopnMusicSunnyParkClient(BaseClient):
status = int(resp.child("playerdata").attribute("status")) status = int(resp.child("playerdata").attribute("status"))
if status != 109: if status != 109:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
# No score data # No score data
return None return None
@ -149,11 +143,7 @@ class PopnMusicSunnyParkClient(BaseClient):
) )
medals = [ medals = [
transform_medals(medal) transform_medals(medal) for medal in resp.child("playerdata").child("base").child("clear_medal").value
for medal in resp.child("playerdata")
.child("base")
.child("clear_medal")
.value
] ]
hiscore = resp.child("playerdata").child("hiscore").value hiscore = resp.child("playerdata").child("hiscore").value
@ -170,8 +160,7 @@ class PopnMusicSunnyParkClient(BaseClient):
hiscores.append(value & 0x1FFFF) hiscores.append(value & 0x1FFFF)
scores = [ scores = [
(hiscores[x], hiscores[x + 1], hiscores[x + 2], hiscores[x + 3]) (hiscores[x], hiscores[x + 1], hiscores[x + 2], hiscores[x + 3]) for x in range(0, len(hiscores), 4)
for x in range(0, len(hiscores), 4)
] ]
return {"medals": medals, "scores": scores} return {"medals": medals, "scores": scores}
@ -198,9 +187,7 @@ class PopnMusicSunnyParkClient(BaseClient):
playerdata.add_child(stage) playerdata.add_child(stage)
stage.add_child(Node.s16("no", score["id"])) stage.add_child(Node.s16("no", score["id"]))
stage.add_child(Node.u8("sheet", score["chart"])) stage.add_child(Node.u8("sheet", score["chart"]))
stage.add_child( stage.add_child(Node.u16("n_data", (score["medal"] << (4 * score["chart"]))))
Node.u16("n_data", (score["medal"] << (4 * score["chart"])))
)
stage.add_child(Node.s32("score", score["score"])) stage.add_child(Node.s32("score", score["score"]))
# Swap with server # Swap with server
@ -273,32 +260,22 @@ class PopnMusicSunnyParkClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_playerdata_get(ref_id, msg_type="new") self.verify_playerdata_get(ref_id, msg_type="new")
self.verify_playerdata_new(ref_id) self.verify_playerdata_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -66,9 +66,7 @@ class PopnMusicTuneStreetClient(BaseClient):
if name not in resp.child("game").attributes: if name not in resp.child("game").attributes:
raise Exception(f"Missing attribute '{name}' in response!") raise Exception(f"Missing attribute '{name}' in response!")
def verify_playerdata_get( def verify_playerdata_get(self, ref_id: str, msg_type: str) -> Optional[Dict[str, Any]]:
self, ref_id: str, msg_type: str
) -> Optional[Dict[str, Any]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -80,9 +78,7 @@ class PopnMusicTuneStreetClient(BaseClient):
playerdata.set_attribute("ref_id", ref_id) playerdata.set_attribute("ref_id", ref_id)
if msg_type == "new": if msg_type == "new":
playerdata.set_attribute( playerdata.set_attribute("model", self.config["old_profile_model"].split(":")[0])
"model", self.config["old_profile_model"].split(":")[0]
)
# Swap with server # Swap with server
resp = self.exchange("pnm/playerdata", call) resp = self.exchange("pnm/playerdata", call)
@ -93,9 +89,7 @@ class PopnMusicTuneStreetClient(BaseClient):
status = int(resp.child("playerdata").attribute("status")) status = int(resp.child("playerdata").attribute("status"))
if status != 109: if status != 109:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
# No score data # No score data
return None return None
@ -105,20 +99,12 @@ class PopnMusicTuneStreetClient(BaseClient):
self.assert_path(resp, "response/playerdata/hiscore") self.assert_path(resp, "response/playerdata/hiscore")
self.assert_path(resp, "response/playerdata/town") self.assert_path(resp, "response/playerdata/town")
name = ( name = resp.child("playerdata").child("b").value[0:12].decode("SHIFT_JIS").replace("\x00", "")
resp.child("playerdata")
.child("b")
.value[0:12]
.decode("SHIFT_JIS")
.replace("\x00", "")
)
if name != self.NAME: if name != self.NAME:
raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'") raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'")
medals = resp.child("playerdata").child("b").value[108:] medals = resp.child("playerdata").child("b").value[108:]
medals = [ medals = [(medals[x] + (medals[x + 1] << 8)) for x in range(0, len(medals), 2)]
(medals[x] + (medals[x + 1] << 8)) for x in range(0, len(medals), 2)
]
# Extract and return score data # Extract and return score data
def transform_medals(medal: int) -> Tuple[int, int, int, int]: def transform_medals(medal: int) -> Tuple[int, int, int, int]:
@ -273,32 +259,22 @@ class PopnMusicTuneStreetClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_playerdata_get(ref_id, msg_type="new") self.verify_playerdata_get(ref_id, msg_type="new")
self.verify_playerdata_new(card, ref_id) self.verify_playerdata_new(card, ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
if cardid is None: if cardid is None:

View File

@ -136,9 +136,7 @@ class PopnMusicUsaNekoClient(BaseClient):
self.assert_path(resp, "response/player24/stamp/stamp_id") self.assert_path(resp, "response/player24/stamp/stamp_id")
self.assert_path(resp, "response/player24/stamp/cnt") self.assert_path(resp, "response/player24/stamp/cnt")
def verify_player24_read( def verify_player24_read(self, ref_id: str, msg_type: str) -> Dict[str, Dict[int, Dict[str, int]]]:
self, ref_id: str, msg_type: str
) -> Dict[str, Dict[int, Dict[str, int]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -157,9 +155,7 @@ class PopnMusicUsaNekoClient(BaseClient):
self.assert_path(resp, "response/player24/result") self.assert_path(resp, "response/player24/result")
status = resp.child_value("player24/result") status = resp.child_value("player24/result")
if status != 2: if status != 2:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
return { return {
"items": {}, "items": {},
@ -173,9 +169,7 @@ class PopnMusicUsaNekoClient(BaseClient):
self.assert_path(resp, "response/player24/result") self.assert_path(resp, "response/player24/result")
status = resp.child_value("player24/result") status = resp.child_value("player24/result")
if status != 0: if status != 0:
raise Exception( raise Exception(f"Reference ID '{ref_id}' returned invalid status '{status}'")
f"Reference ID '{ref_id}' returned invalid status '{status}'"
)
name = resp.child_value("player24/account/name") name = resp.child_value("player24/account/name")
if name != self.NAME: if name != self.NAME:
raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'") raise Exception(f"Invalid name '{name}' returned for Ref ID '{ref_id}'")
@ -207,16 +201,12 @@ class PopnMusicUsaNekoClient(BaseClient):
"items": items, "items": items,
"characters": charas, "characters": charas,
"courses": courses, "courses": courses,
"points": { "points": {0: {"points": resp.child_value("player24/account/player_point")}},
0: {"points": resp.child_value("player24/account/player_point")}
},
} }
else: else:
raise Exception(f"Unrecognized message type '{msg_type}'") raise Exception(f"Unrecognized message type '{msg_type}'")
def verify_player24_read_score( def verify_player24_read_score(self, ref_id: str) -> Dict[str, Dict[int, Dict[int, int]]]:
self, ref_id: str
) -> Dict[str, Dict[int, Dict[int, int]]]:
call = self.call_node() call = self.call_node()
# Construct node # Construct node
@ -468,32 +458,22 @@ class PopnMusicUsaNekoClient(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
self.verify_player24_read(ref_id, msg_type="new") self.verify_player24_read(ref_id, msg_type="new")
self.verify_player24_new(ref_id) self.verify_player24_new(ref_id)
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify proper handling of basic stuff # Verify proper handling of basic stuff
@ -531,9 +511,7 @@ class PopnMusicUsaNekoClient(BaseClient):
if 5 not in unlocks["characters"]: if 5 not in unlocks["characters"]:
raise Exception("Expecting to see chara ID 5 in characters!") raise Exception("Expecting to see chara ID 5 in characters!")
if unlocks["characters"][5]["friendship"] != 420: if unlocks["characters"][5]["friendship"] != 420:
raise Exception( raise Exception("Expecting to see chara ID 5 to have type 2 in characters!")
"Expecting to see chara ID 5 to have type 2 in characters!"
)
# Verify purchases work # Verify purchases work
self.verify_player24_buy( self.verify_player24_buy(
@ -548,9 +526,7 @@ class PopnMusicUsaNekoClient(BaseClient):
if unlocks["items"][6]["param"] != 8: if unlocks["items"][6]["param"] != 8:
raise Exception("Expecting to see item ID 6 to have param 8 in items!") raise Exception("Expecting to see item ID 6 to have param 8 in items!")
if unlocks["points"][0]["points"] != 150: if unlocks["points"][0]["points"] != 150:
raise Exception( raise Exception(f'Got wrong value for points {unlocks["points"][0]["points"]} after purchase!')
f'Got wrong value for points {unlocks["points"][0]["points"]} after purchase!'
)
# Verify course handling # Verify course handling
self.verify_player24_update_ranking(ref_id, location) self.verify_player24_update_ranking(ref_id, location)
@ -558,25 +534,15 @@ class PopnMusicUsaNekoClient(BaseClient):
if 12345 not in unlocks["courses"]: if 12345 not in unlocks["courses"]:
raise Exception("Expecting to see course ID 12345 in courses!") raise Exception("Expecting to see course ID 12345 in courses!")
if unlocks["courses"][12345]["clear_type"] != 7: if unlocks["courses"][12345]["clear_type"] != 7:
raise Exception( raise Exception("Expecting to see item ID 12345 to have clear_type 7 in courses!")
"Expecting to see item ID 12345 to have clear_type 7 in courses!"
)
if unlocks["courses"][12345]["clear_rank"] != 5: if unlocks["courses"][12345]["clear_rank"] != 5:
raise Exception( raise Exception("Expecting to see item ID 12345 to have clear_rank 5 in courses!")
"Expecting to see item ID 12345 to have clear_rank 5 in courses!"
)
if unlocks["courses"][12345]["total_score"] != 86000: if unlocks["courses"][12345]["total_score"] != 86000:
raise Exception( raise Exception("Expecting to see item ID 12345 to have total_score 86000 in courses!")
"Expecting to see item ID 12345 to have total_score 86000 in courses!"
)
if unlocks["courses"][12345]["count"] != 1: if unlocks["courses"][12345]["count"] != 1:
raise Exception( raise Exception("Expecting to see item ID 12345 to have count 1 in courses!")
"Expecting to see item ID 12345 to have count 1 in courses!"
)
if unlocks["courses"][12345]["sheet_num"] != 2: if unlocks["courses"][12345]["sheet_num"] != 2:
raise Exception( raise Exception("Expecting to see item ID 12345 to have sheet_num 2 in courses!")
"Expecting to see item ID 12345 to have sheet_num 2 in courses!"
)
# Verify score handling # Verify score handling
scores = self.verify_player24_read_score(ref_id) scores = self.verify_player24_read_score(ref_id)

View File

@ -182,9 +182,7 @@ class ReflecBeatColette(BaseClient):
self.assert_path(resp, "response/player/pdata/record") self.assert_path(resp, "response/player/pdata/record")
if resp.child_value("player/pdata/base/name") != self.NAME: if resp.child_value("player/pdata/base/name") != self.NAME:
raise Exception( raise Exception(f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!')
f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!'
)
scores = [] scores = []
for child in resp.child("player/pdata/record").children: for child in resp.child("player/pdata/record").children:
@ -203,9 +201,7 @@ class ReflecBeatColette(BaseClient):
scores.append(score) scores.append(score)
return scores return scores
def verify_player_write( def verify_player_write(self, refid: str, loc: str, scores: List[Dict[str, int]]) -> int:
self, refid: str, loc: str, scores: List[Dict[str, int]]
) -> int:
call = self.call_node() call = self.call_node()
player = Node.void("player") player = Node.void("player")
@ -471,9 +467,7 @@ class ReflecBeatColette(BaseClient):
if name != self.NAME: if name != self.NAME:
raise Exception(f"Invalid name '{name}' returned for comment!") raise Exception(f"Invalid name '{name}' returned for comment!")
if comment != "アメ〜〜!": if comment != "アメ〜〜!":
raise Exception( raise Exception(f"Invalid comment '{comment}' returned for comment!")
f"Invalid comment '{comment}' returned for comment!"
)
found = True found = True
if not found: if not found:
@ -553,17 +547,11 @@ class ReflecBeatColette(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Always get a player start, regardless of new profile or not # Always get a player start, regardless of new profile or not
self.verify_player_start(ref_id) self.verify_player_start(ref_id)
@ -586,16 +574,12 @@ class ReflecBeatColette(BaseClient):
) )
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify lobby functionality # Verify lobby functionality
@ -690,26 +674,19 @@ class ReflecBeatColette(BaseClient):
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]
else: else:
expected_score = expected["score"] expected_score = expected["score"]
if "expected_achievement_rate" in expected: if "expected_achievement_rate" in expected:
expected_achievement_rate = expected[ expected_achievement_rate = expected["expected_achievement_rate"]
"expected_achievement_rate"
]
else: else:
expected_achievement_rate = expected["achievement_rate"] expected_achievement_rate = expected["achievement_rate"]
if "expected_clear_type" in expected: if "expected_clear_type" in expected:

View File

@ -123,11 +123,7 @@ class ReflecBeatGroovinUpper(BaseClient):
player.add_child(Node.u8_array("ga", [127, 0, 0, 1])) player.add_child(Node.u8_array("ga", [127, 0, 0, 1]))
player.add_child(Node.u16("gp", 10573)) player.add_child(Node.u16("gp", 10573))
player.add_child(Node.u8_array("la", [16, 0, 0, 0])) player.add_child(Node.u8_array("la", [16, 0, 0, 0]))
player.add_child( player.add_child(Node.u8_array("pnid", [39, 16, 0, 0, 0, 23, 62, 60, 39, 127, 0, 0, 1, 23, 62, 60]))
Node.u8_array(
"pnid", [39, 16, 0, 0, 0, 23, 62, 60, 39, 127, 0, 0, 1, 23, 62, 60]
)
)
call.add_child(player) call.add_child(player)
@ -293,13 +289,9 @@ class ReflecBeatGroovinUpper(BaseClient):
self.assert_path(resp, "response/player/pdata/pue") self.assert_path(resp, "response/player/pdata/pue")
if resp.child_value("player/pdata/base/name") != self.NAME: if resp.child_value("player/pdata/base/name") != self.NAME:
raise Exception( raise Exception(f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!')
f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!'
)
def verify_player_rb4readscore( def verify_player_rb4readscore(self, refid: str, location: str) -> List[Dict[str, int]]:
self, refid: str, location: str
) -> List[Dict[str, int]]:
call = self.call_node() call = self.call_node()
player = Node.void("player") player = Node.void("player")
@ -347,9 +339,7 @@ class ReflecBeatGroovinUpper(BaseClient):
continue continue
if child.child_value("user_id") != extid: if child.child_value("user_id") != extid:
raise Exception( raise Exception(f'Invalid user ID returned {child.child_value("user_id")}')
f'Invalid user ID returned {child.child_value("user_id")}'
)
episode = { episode = {
"id": child.child_value("type"), "id": child.child_value("type"),
@ -598,9 +588,7 @@ class ReflecBeatGroovinUpper(BaseClient):
if name != self.NAME: if name != self.NAME:
raise Exception(f"Invalid name '{name}' returned for comment!") raise Exception(f"Invalid name '{name}' returned for comment!")
if comment != "アメ〜〜!": if comment != "アメ〜〜!":
raise Exception( raise Exception(f"Invalid comment '{comment}' returned for comment!")
f"Invalid comment '{comment}' returned for comment!"
)
found = True found = True
if not found: if not found:
@ -683,17 +671,11 @@ class ReflecBeatGroovinUpper(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Always get a player start, regardless of new profile or not # Always get a player start, regardless of new profile or not
@ -706,16 +688,12 @@ class ReflecBeatGroovinUpper(BaseClient):
) )
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify lobby functionality # Verify lobby functionality
@ -853,26 +831,19 @@ class ReflecBeatGroovinUpper(BaseClient):
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]
else: else:
expected_score = expected["score"] expected_score = expected["score"]
if "expected_achievement_rate" in expected: if "expected_achievement_rate" in expected:
expected_achievement_rate = expected[ expected_achievement_rate = expected["expected_achievement_rate"]
"expected_achievement_rate"
]
else: else:
expected_achievement_rate = expected["achievement_rate"] expected_achievement_rate = expected["achievement_rate"]
if "expected_clear_type" in expected: if "expected_clear_type" in expected:

View File

@ -213,9 +213,7 @@ class ReflecBeatLimelight(BaseClient):
self.assert_path(resp, "response/player/pdata/narrow_down/adv_param") self.assert_path(resp, "response/player/pdata/narrow_down/adv_param")
if resp.child_value("player/pdata/base/name") != self.NAME: if resp.child_value("player/pdata/base/name") != self.NAME:
raise Exception( raise Exception(f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!')
f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!'
)
scores = [] scores = []
for child in resp.child("player/pdata/record").children: for child in resp.child("player/pdata/record").children:
@ -343,9 +341,7 @@ class ReflecBeatLimelight(BaseClient):
return f'{thing["id"]}-{thing["chart"]}' return f'{thing["id"]}-{thing["chart"]}'
updates = [key(score) for score in scores] updates = [key(score) for score in scores]
sortedrecords = { sortedrecords = {key(record): record for record in records if key(record) in updates}
key(record): record for record in records if key(record) in updates
}
# Now, see what records need updating and update them # Now, see what records need updating and update them
for score in scores: for score in scores:
@ -366,9 +362,7 @@ class ReflecBeatLimelight(BaseClient):
"id": score["id"], "id": score["id"],
"chart": score["chart"], "chart": score["chart"],
"clear_type": max(record["clear_type"], score["clear_type"]), "clear_type": max(record["clear_type"], score["clear_type"]),
"achievement_rate": max( "achievement_rate": max(record["achievement_rate"], score["achievement_rate"]),
record["achievement_rate"], score["achievement_rate"]
),
"score": max(record["score"], score["score"]), "score": max(record["score"], score["score"]),
"combo": max(record["combo"], score["combo"]), "combo": max(record["combo"], score["combo"]),
"miss_count": min(record["miss_count"], score["miss_count"]), "miss_count": min(record["miss_count"], score["miss_count"]),
@ -443,9 +437,7 @@ class ReflecBeatLimelight(BaseClient):
self.assert_path(resp, "response/player/time") self.assert_path(resp, "response/player/time")
return resp.child_value("player/uid") return resp.child_value("player/uid")
def verify_log_play( def verify_log_play(self, extid: int, loc: str, scores: List[Dict[str, int]]) -> None:
self, extid: int, loc: str, scores: List[Dict[str, int]]
) -> None:
call = self.call_node() call = self.call_node()
log = Node.void("log") log = Node.void("log")
@ -683,9 +675,7 @@ class ReflecBeatLimelight(BaseClient):
if name != self.NAME: if name != self.NAME:
raise Exception(f"Invalid name '{name}' returned for comment!") raise Exception(f"Invalid name '{name}' returned for comment!")
if comment != "アメ〜〜!": if comment != "アメ〜〜!":
raise Exception( raise Exception(f"Invalid comment '{comment}' returned for comment!")
f"Invalid comment '{comment}' returned for comment!"
)
found = True found = True
if not found: if not found:
@ -745,17 +735,11 @@ class ReflecBeatLimelight(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Always get a player start, regardless of new profile or not # Always get a player start, regardless of new profile or not
self.verify_player_start(ref_id) self.verify_player_start(ref_id)
@ -769,16 +753,12 @@ class ReflecBeatLimelight(BaseClient):
) )
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify lobby functionality # Verify lobby functionality
@ -875,26 +855,19 @@ class ReflecBeatLimelight(BaseClient):
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]
else: else:
expected_score = expected["score"] expected_score = expected["score"]
if "expected_achievement_rate" in expected: if "expected_achievement_rate" in expected:
expected_achievement_rate = expected[ expected_achievement_rate = expected["expected_achievement_rate"]
"expected_achievement_rate"
]
else: else:
expected_achievement_rate = expected["achievement_rate"] expected_achievement_rate = expected["achievement_rate"]
if "expected_clear_type" in expected: if "expected_clear_type" in expected:

View File

@ -155,9 +155,7 @@ class ReflecBeat(BaseClient):
self.assert_path(resp, "response/player/pdata/cmnt") self.assert_path(resp, "response/player/pdata/cmnt")
if resp.child_value("player/pdata/base/name") != self.NAME: if resp.child_value("player/pdata/base/name") != self.NAME:
raise Exception( raise Exception(f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!')
f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!'
)
scores = [] scores = []
for child in resp.child("player/pdata/record").children: for child in resp.child("player/pdata/record").children:
@ -224,9 +222,7 @@ class ReflecBeat(BaseClient):
return f'{thing["id"]}-{thing["chart"]}' return f'{thing["id"]}-{thing["chart"]}'
updates = [key(score) for score in scores] updates = [key(score) for score in scores]
sortedrecords = { sortedrecords = {key(record): record for record in records if key(record) in updates}
key(record): record for record in records if key(record) in updates
}
# Now, see what records need updating and update them # Now, see what records need updating and update them
for score in scores: for score in scores:
@ -247,9 +243,7 @@ class ReflecBeat(BaseClient):
"id": score["id"], "id": score["id"],
"chart": score["chart"], "chart": score["chart"],
"clear_type": max(record["clear_type"], score["clear_type"]), "clear_type": max(record["clear_type"], score["clear_type"]),
"achievement_rate": max( "achievement_rate": max(record["achievement_rate"], score["achievement_rate"]),
record["achievement_rate"], score["achievement_rate"]
),
"score": max(record["score"], score["score"]), "score": max(record["score"], score["score"]),
"combo": max(record["combo"], score["combo"]), "combo": max(record["combo"], score["combo"]),
"miss_count": min(record["miss_count"], score["miss_count"]), "miss_count": min(record["miss_count"], score["miss_count"]),
@ -310,9 +304,7 @@ class ReflecBeat(BaseClient):
self.assert_path(resp, "response/player/time") self.assert_path(resp, "response/player/time")
return resp.child_value("player/uid") return resp.child_value("player/uid")
def verify_log_play( def verify_log_play(self, extid: int, loc: str, scores: List[Dict[str, int]]) -> None:
self, extid: int, loc: str, scores: List[Dict[str, int]]
) -> None:
call = self.call_node() call = self.call_node()
log = Node.void("log") log = Node.void("log")
@ -468,17 +460,11 @@ class ReflecBeat(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Always get a player start, regardless of new profile or not # Always get a player start, regardless of new profile or not
self.verify_player_start(ref_id) self.verify_player_start(ref_id)
@ -492,16 +478,12 @@ class ReflecBeat(BaseClient):
) )
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify lobby functionality # Verify lobby functionality
@ -593,26 +575,19 @@ class ReflecBeat(BaseClient):
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]
else: else:
expected_score = expected["score"] expected_score = expected["score"]
if "expected_achievement_rate" in expected: if "expected_achievement_rate" in expected:
expected_achievement_rate = expected[ expected_achievement_rate = expected["expected_achievement_rate"]
"expected_achievement_rate"
]
else: else:
expected_achievement_rate = expected["achievement_rate"] expected_achievement_rate = expected["achievement_rate"]
if "expected_clear_type" in expected: if "expected_clear_type" in expected:

View File

@ -121,11 +121,7 @@ class ReflecBeatVolzza(BaseClient):
player.add_child(Node.u8_array("ga", [127, 0, 0, 1])) player.add_child(Node.u8_array("ga", [127, 0, 0, 1]))
player.add_child(Node.u16("gp", 10573)) player.add_child(Node.u16("gp", 10573))
player.add_child(Node.u8_array("la", [16, 0, 0, 0])) player.add_child(Node.u8_array("la", [16, 0, 0, 0]))
player.add_child( player.add_child(Node.u8_array("pnid", [39, 16, 0, 0, 0, 23, 62, 60, 39, 127, 0, 0, 1, 23, 62, 60]))
Node.u8_array(
"pnid", [39, 16, 0, 0, 0, 23, 62, 60, 39, 127, 0, 0, 1, 23, 62, 60]
)
)
call.add_child(player) call.add_child(player)
@ -246,9 +242,7 @@ class ReflecBeatVolzza(BaseClient):
self.assert_path(resp, "response/player/ap") self.assert_path(resp, "response/player/ap")
self.assert_path(resp, "response/player/uattr") self.assert_path(resp, "response/player/uattr")
def verify_player_rb5_player_read( def verify_player_rb5_player_read(self, refid: str, cardid: str, location: str) -> None:
self, refid: str, cardid: str, location: str
) -> None:
call = self.call_node() call = self.call_node()
player = Node.void("player") player = Node.void("player")
@ -303,13 +297,9 @@ class ReflecBeatVolzza(BaseClient):
self.assert_path(resp, "response/player/pdata/mylist/list/mlst") self.assert_path(resp, "response/player/pdata/mylist/list/mlst")
if resp.child_value("player/pdata/base/name") != self.NAME: if resp.child_value("player/pdata/base/name") != self.NAME:
raise Exception( raise Exception(f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!')
f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!'
)
def verify_player_rb5_player_read_score( def verify_player_rb5_player_read_score(self, refid: str, location: str) -> List[Dict[str, int]]:
self, refid: str, location: str
) -> List[Dict[str, int]]:
call = self.call_node() call = self.call_node()
player = Node.void("player") player = Node.void("player")
@ -581,17 +571,11 @@ class ReflecBeatVolzza(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Always get a player start, regardless of new profile or not # Always get a player start, regardless of new profile or not
@ -603,16 +587,12 @@ class ReflecBeatVolzza(BaseClient):
) )
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify lobby functionality # Verify lobby functionality
@ -699,35 +679,26 @@ class ReflecBeatVolzza(BaseClient):
"expected_miss_count": 0, "expected_miss_count": 0,
}, },
] ]
self.verify_player_rb5_player_write( self.verify_player_rb5_player_write(ref_id, location, scores=dummyscores)
ref_id, location, scores=dummyscores
)
self.verify_player_rb5_player_read(ref_id, card, location) self.verify_player_rb5_player_read(ref_id, card, location)
scores = self.verify_player_rb5_player_read_score(ref_id, location) scores = self.verify_player_rb5_player_read_score(ref_id, location)
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]
else: else:
expected_score = expected["score"] expected_score = expected["score"]
if "expected_achievement_rate" in expected: if "expected_achievement_rate" in expected:
expected_achievement_rate = expected[ expected_achievement_rate = expected["expected_achievement_rate"]
"expected_achievement_rate"
]
else: else:
expected_achievement_rate = expected["achievement_rate"] expected_achievement_rate = expected["achievement_rate"]
if "expected_clear_type" in expected: if "expected_clear_type" in expected:

View File

@ -122,11 +122,7 @@ class ReflecBeatVolzza2(BaseClient):
player.add_child(Node.u8_array("ga", [127, 0, 0, 1])) player.add_child(Node.u8_array("ga", [127, 0, 0, 1]))
player.add_child(Node.u16("gp", 10573)) player.add_child(Node.u16("gp", 10573))
player.add_child(Node.u8_array("la", [16, 0, 0, 0])) player.add_child(Node.u8_array("la", [16, 0, 0, 0]))
player.add_child( player.add_child(Node.u8_array("pnid", [39, 16, 0, 0, 0, 23, 62, 60, 39, 127, 0, 0, 1, 23, 62, 60]))
Node.u8_array(
"pnid", [39, 16, 0, 0, 0, 23, 62, 60, 39, 127, 0, 0, 1, 23, 62, 60]
)
)
call.add_child(player) call.add_child(player)
@ -248,9 +244,7 @@ class ReflecBeatVolzza2(BaseClient):
self.assert_path(resp, "response/player/ap") self.assert_path(resp, "response/player/ap")
self.assert_path(resp, "response/player/uattr") self.assert_path(resp, "response/player/uattr")
def verify_player_rb5_player_read( def verify_player_rb5_player_read(self, refid: str, cardid: str, location: str) -> Dict[str, Any]:
self, refid: str, cardid: str, location: str
) -> Dict[str, Any]:
call = self.call_node() call = self.call_node()
player = Node.void("player") player = Node.void("player")
@ -310,9 +304,7 @@ class ReflecBeatVolzza2(BaseClient):
self.assert_path(resp, "response/player/pdata/mycourse_f") self.assert_path(resp, "response/player/pdata/mycourse_f")
if resp.child_value("player/pdata/base/name") != self.NAME: if resp.child_value("player/pdata/base/name") != self.NAME:
raise Exception( raise Exception(f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!')
f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!'
)
mycourse = [ mycourse = [
{ {
@ -340,9 +332,7 @@ class ReflecBeatVolzza2(BaseClient):
"mycourse": mycourse, "mycourse": mycourse,
} }
def verify_player_rb5_player_read_score_5( def verify_player_rb5_player_read_score_5(self, refid: str, location: str) -> List[Dict[str, int]]:
self, refid: str, location: str
) -> List[Dict[str, int]]:
call = self.call_node() call = self.call_node()
player = Node.void("player") player = Node.void("player")
@ -386,9 +376,7 @@ class ReflecBeatVolzza2(BaseClient):
scores.append(score) scores.append(score)
return scores return scores
def verify_player_rb5_player_read_score_old_5( def verify_player_rb5_player_read_score_old_5(self, refid: str, location: str) -> List[Dict[str, int]]:
self, refid: str, location: str
) -> List[Dict[str, int]]:
call = self.call_node() call = self.call_node()
player = Node.void("player") player = Node.void("player")
@ -688,17 +676,11 @@ class ReflecBeatVolzza2(BaseClient):
print(f"Generated random card ID {card} for use.") print(f"Generated random card ID {card} for use.")
if cardid is None: if cardid is None:
self.verify_cardmng_inquire( self.verify_cardmng_inquire(card, msg_type="unregistered", paseli_enabled=paseli_enabled)
card, msg_type="unregistered", paseli_enabled=paseli_enabled
)
ref_id = self.verify_cardmng_getrefid(card) ref_id = self.verify_cardmng_getrefid(card)
if len(ref_id) != 16: if len(ref_id) != 16:
raise Exception( raise Exception(f"Invalid refid '{ref_id}' returned when registering card")
f"Invalid refid '{ref_id}' returned when registering card" if ref_id != self.verify_cardmng_inquire(card, msg_type="new", paseli_enabled=paseli_enabled):
)
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") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Always get a player start, regardless of new profile or not # Always get a player start, regardless of new profile or not
@ -710,16 +692,12 @@ class ReflecBeatVolzza2(BaseClient):
) )
else: else:
print("Skipping new card checks for existing card") print("Skipping new card checks for existing card")
ref_id = self.verify_cardmng_inquire( ref_id = self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled)
card, msg_type="query", paseli_enabled=paseli_enabled
)
# Verify pin handling and return card handling # Verify pin handling and return card handling
self.verify_cardmng_authpass(ref_id, correct=True) self.verify_cardmng_authpass(ref_id, correct=True)
self.verify_cardmng_authpass(ref_id, correct=False) self.verify_cardmng_authpass(ref_id, correct=False)
if ref_id != self.verify_cardmng_inquire( if ref_id != self.verify_cardmng_inquire(card, msg_type="query", paseli_enabled=paseli_enabled):
card, msg_type="query", paseli_enabled=paseli_enabled
):
raise Exception(f"Invalid refid '{ref_id}' returned when querying card") raise Exception(f"Invalid refid '{ref_id}' returned when querying card")
# Verify lobby functionality # Verify lobby functionality
@ -815,35 +793,26 @@ class ReflecBeatVolzza2(BaseClient):
"expected_miss_count": 0, "expected_miss_count": 0,
}, },
] ]
self.verify_player_rb5_player_write_5( self.verify_player_rb5_player_write_5(ref_id, location, scores=dummyscores)
ref_id, location, scores=dummyscores
)
self.verify_player_rb5_player_read(ref_id, card, location) self.verify_player_rb5_player_read(ref_id, card, location)
scores = self.verify_player_rb5_player_read_score_5(ref_id, location) scores = self.verify_player_rb5_player_read_score_5(ref_id, location)
for expected in dummyscores: for expected in dummyscores:
actual = None actual = None
for received in scores: for received in scores:
if ( if received["id"] == expected["id"] and received["chart"] == expected["chart"]:
received["id"] == expected["id"]
and received["chart"] == expected["chart"]
):
actual = received actual = received
break break
if actual is None: if actual is None:
raise Exception( raise Exception(f"Didn't find song {expected['id']} chart {expected['chart']} in response!")
f"Didn't find song {expected['id']} chart {expected['chart']} in response!"
)
if "expected_score" in expected: if "expected_score" in expected:
expected_score = expected["expected_score"] expected_score = expected["expected_score"]
else: else:
expected_score = expected["score"] expected_score = expected["score"]
if "expected_achievement_rate" in expected: if "expected_achievement_rate" in expected:
expected_achievement_rate = expected[ expected_achievement_rate = expected["expected_achievement_rate"]
"expected_achievement_rate"
]
else: else:
expected_achievement_rate = expected["achievement_rate"] expected_achievement_rate = expected["achievement_rate"]
if "expected_clear_type" in expected: if "expected_clear_type" in expected:

Some files were not shown because too many files have changed in this diff Show More