Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SuperNova 2 Support #86

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions bemani/backend/ddr/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ def format_profile(self, userid: UserID, profile: Profile) -> Node:
"""
return Node.void("game")

def format_profile_part(self, userid: UserID, profile: Profile, part: str) -> Node:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Profile for SN2 is split into 3 binary chunks, where to break this logic down, it being here feels wrong

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly the format_profile and unformat_profile convention were both established to just give some sort of unity across games. They don't need to exist outside of the fact that the base of most games assumes it can call that for profile loads. If there's 3 parts here, this can diverge for cleaner code.

"""
Base handler for a profile. Given a userid and a profile dictionary,
return a Node representing a profile. Should be overridden.
"""
return Node.void("game")

def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
"""
Base handler for a score list. Given a userid, profile and a score list,
Expand All @@ -142,6 +149,24 @@ def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -
"""
return oldprofile

def get_profile_by_refid_and_part(self, refid: Optional[str], part: Optional[str]) -> Optional[Node]:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this definitely feels weird. But, the pattern is established. Worth a think.

"""
Given a RefID, return a formatted profile node. Basically every game
needs a profile lookup, even if it handles where that happens in
a different request. This is provided for code deduplication.
"""
if refid is None:
return None

# First try to load the actual profile
userid = self.data.remote.user.from_refid(self.game, self.version, refid)
profile = self.get_profile(userid)
if profile is None:
return None

# Now, return it
return self.format_profile_part(userid, profile, part)

def get_profile_by_refid(self, refid: Optional[str]) -> Optional[Node]:
"""
Given a RefID, return a formatted profile node. Basically every game
Expand Down
3 changes: 3 additions & 0 deletions bemani/backend/ddr/ddrsn2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from bemani.backend.ddr.ddrsn2.ddrsn2 import DDRSuperNova2
Copy link
Owner

@DragonMinded DragonMinded Feb 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting separating this into a module instead of a single file. Any reason for having this across a bunch of files? Don't see a problem with it, just curious.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, mostly just a leftover from my JS work. A common lint is only one class defined per file. If it's a bit awkward I'm ok with merging them into one file.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDGAF either way, pattern in the repo is one file, we don't do silly things like have an import system that depends on there being one export/class per file, so you can get away with a lot of stuff.


__all__ = ["DDRSuperNova2"]
26 changes: 26 additions & 0 deletions bemani/backend/ddr/ddrsn2/battlerecord.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import logging
from ctypes import *


class BattleRecordStruct(Structure):
_pack_ = 1
_fields_ = [
("name", c_char * 14),
("wins", c_uint16),
("loses", c_uint16),
("draws", c_uint16),
]


class BattleRecord:
@staticmethod
def create(name: str, wins: int, losses: int, draws: int) -> BattleRecordStruct:
this_name = name
if len(this_name) > 8:
this_name = this_name[:8]
logging.warning("name {} too long, truncating to {}", name, this_name)
elif len(this_name) < 8:
logging.warning("name too short, padding with spaces")
this_name = this_name.ljust(8, " ")

return BattleRecordStruct(this_name.encode("ascii"), wins, losses, draws)
Loading