mirror of
https://github.com/DragonMinded/bemaniutils.git
synced 2026-10-11 16:58:22 +03:00
Format code with black, include wrapper script to handle that, update linter checks to accomodate, fix a few miscelaneous type errors.
This commit is contained in:
@@ -14,11 +14,15 @@ class BaseObject:
|
||||
various fetch versions.
|
||||
"""
|
||||
|
||||
def __init__(self, data: Data, game: GameConstants, version: int, omnimix: bool) -> None:
|
||||
def __init__(
|
||||
self, data: Data, game: GameConstants, version: int, omnimix: bool
|
||||
) -> None:
|
||||
self.data = data
|
||||
self.game = game
|
||||
self.version = version
|
||||
self.omnimix = omnimix
|
||||
|
||||
def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> Any:
|
||||
raise APIException('Object fetch not supported for this version!')
|
||||
def fetch_v1(
|
||||
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
|
||||
) -> Any:
|
||||
raise APIException("Object fetch not supported for this version!")
|
||||
|
||||
@@ -7,31 +7,30 @@ from bemani.data import Song
|
||||
|
||||
|
||||
class CatalogObject(BaseObject):
|
||||
|
||||
def __format_ddr_song(self, song: Song) -> Dict[str, Any]:
|
||||
groove = song.data.get_dict('groove')
|
||||
groove = song.data.get_dict("groove")
|
||||
return {
|
||||
'editid': str(song.data.get_int('edit_id')),
|
||||
'difficulty': song.data.get_int('difficulty'),
|
||||
'bpm_min': song.data.get_int('bpm_min'),
|
||||
'bpm_max': song.data.get_int('bpm_max'),
|
||||
'category': str(song.data.get_int('category')),
|
||||
'groove': {
|
||||
'air': groove.get_int('air'),
|
||||
'chaos': groove.get_int('chaos'),
|
||||
'freeze': groove.get_int('freeze'),
|
||||
'stream': groove.get_int('stream'),
|
||||
'voltage': groove.get_int('voltage'),
|
||||
"editid": str(song.data.get_int("edit_id")),
|
||||
"difficulty": song.data.get_int("difficulty"),
|
||||
"bpm_min": song.data.get_int("bpm_min"),
|
||||
"bpm_max": song.data.get_int("bpm_max"),
|
||||
"category": str(song.data.get_int("category")),
|
||||
"groove": {
|
||||
"air": groove.get_int("air"),
|
||||
"chaos": groove.get_int("chaos"),
|
||||
"freeze": groove.get_int("freeze"),
|
||||
"stream": groove.get_int("stream"),
|
||||
"voltage": groove.get_int("voltage"),
|
||||
},
|
||||
}
|
||||
|
||||
def __format_iidx_song(self, song: Song) -> Dict[str, Any]:
|
||||
return {
|
||||
'difficulty': song.data.get_int('difficulty'),
|
||||
'bpm_min': song.data.get_int('bpm_min'),
|
||||
'bpm_max': song.data.get_int('bpm_max'),
|
||||
'notecount': song.data.get_int('notecount'),
|
||||
'category': str(int(song.id / 1000)),
|
||||
"difficulty": song.data.get_int("difficulty"),
|
||||
"bpm_min": song.data.get_int("bpm_min"),
|
||||
"bpm_max": song.data.get_int("bpm_max"),
|
||||
"notecount": song.data.get_int("notecount"),
|
||||
"category": str(int(song.id / 1000)),
|
||||
}
|
||||
|
||||
def __format_jubeat_song(self, song: Song) -> Dict[str, Any]:
|
||||
@@ -46,67 +45,69 @@ class CatalogObject(BaseObject):
|
||||
6: VersionConstants.JUBEAT_PROP,
|
||||
7: VersionConstants.JUBEAT_QUBELL,
|
||||
8: VersionConstants.JUBEAT_CLAN,
|
||||
9: VersionConstants.JUBEAT_FESTO
|
||||
9: VersionConstants.JUBEAT_FESTO,
|
||||
}.get(int(song.id / 10000000), VersionConstants.JUBEAT)
|
||||
# Map the category to the version numbers defined on BEMAPI.
|
||||
categorymapping = {
|
||||
VersionConstants.JUBEAT: '1',
|
||||
VersionConstants.JUBEAT_RIPPLES: '2',
|
||||
VersionConstants.JUBEAT_RIPPLES_APPEND: '2a',
|
||||
VersionConstants.JUBEAT_KNIT: '3',
|
||||
VersionConstants.JUBEAT_KNIT_APPEND: '3a',
|
||||
VersionConstants.JUBEAT_COPIOUS: '4',
|
||||
VersionConstants.JUBEAT_COPIOUS_APPEND: '4a',
|
||||
VersionConstants.JUBEAT_SAUCER: '5',
|
||||
VersionConstants.JUBEAT_SAUCER_FULFILL: '5a',
|
||||
VersionConstants.JUBEAT_PROP: '6',
|
||||
VersionConstants.JUBEAT_QUBELL: '7',
|
||||
VersionConstants.JUBEAT_CLAN: '8',
|
||||
VersionConstants.JUBEAT_FESTO: '9',
|
||||
VersionConstants.JUBEAT: "1",
|
||||
VersionConstants.JUBEAT_RIPPLES: "2",
|
||||
VersionConstants.JUBEAT_RIPPLES_APPEND: "2a",
|
||||
VersionConstants.JUBEAT_KNIT: "3",
|
||||
VersionConstants.JUBEAT_KNIT_APPEND: "3a",
|
||||
VersionConstants.JUBEAT_COPIOUS: "4",
|
||||
VersionConstants.JUBEAT_COPIOUS_APPEND: "4a",
|
||||
VersionConstants.JUBEAT_SAUCER: "5",
|
||||
VersionConstants.JUBEAT_SAUCER_FULFILL: "5a",
|
||||
VersionConstants.JUBEAT_PROP: "6",
|
||||
VersionConstants.JUBEAT_QUBELL: "7",
|
||||
VersionConstants.JUBEAT_CLAN: "8",
|
||||
VersionConstants.JUBEAT_FESTO: "9",
|
||||
}
|
||||
return {
|
||||
'difficulty': song.data.get_int('difficulty'),
|
||||
'category': categorymapping.get(song.data.get_int('version', defaultcategory), '1'),
|
||||
'bpm_min': song.data.get_int('bpm_min'),
|
||||
'bpm_max': song.data.get_int('bpm_max'),
|
||||
"difficulty": song.data.get_int("difficulty"),
|
||||
"category": categorymapping.get(
|
||||
song.data.get_int("version", defaultcategory), "1"
|
||||
),
|
||||
"bpm_min": song.data.get_int("bpm_min"),
|
||||
"bpm_max": song.data.get_int("bpm_max"),
|
||||
}
|
||||
|
||||
def __format_museca_song(self, song: Song) -> Dict[str, Any]:
|
||||
return {
|
||||
'difficulty': song.data.get_int('difficulty'),
|
||||
'bpm_min': song.data.get_int('bpm_min'),
|
||||
'bpm_max': song.data.get_int('bpm_max'),
|
||||
'limited': song.data.get_int('limited'),
|
||||
"difficulty": song.data.get_int("difficulty"),
|
||||
"bpm_min": song.data.get_int("bpm_min"),
|
||||
"bpm_max": song.data.get_int("bpm_max"),
|
||||
"limited": song.data.get_int("limited"),
|
||||
}
|
||||
|
||||
def __format_popn_song(self, song: Song) -> Dict[str, Any]:
|
||||
return {
|
||||
'difficulty': song.data.get_int('difficulty'),
|
||||
'category': song.data.get_str('category'),
|
||||
"difficulty": song.data.get_int("difficulty"),
|
||||
"category": song.data.get_str("category"),
|
||||
}
|
||||
|
||||
def __format_reflec_song(self, song: Song) -> Dict[str, Any]:
|
||||
return {
|
||||
'difficulty': song.data.get_int('difficulty'),
|
||||
'category': str(song.data.get_int('folder')),
|
||||
'musicid': song.data.get_str('chart_id'),
|
||||
"difficulty": song.data.get_int("difficulty"),
|
||||
"category": str(song.data.get_int("folder")),
|
||||
"musicid": song.data.get_str("chart_id"),
|
||||
}
|
||||
|
||||
def __format_sdvx_song(self, song: Song) -> Dict[str, Any]:
|
||||
return {
|
||||
'difficulty': song.data.get_int('difficulty'),
|
||||
'bpm_min': song.data.get_int('bpm_min'),
|
||||
'bpm_max': song.data.get_int('bpm_max'),
|
||||
'limited': song.data.get_int('limited'),
|
||||
"difficulty": song.data.get_int("difficulty"),
|
||||
"bpm_min": song.data.get_int("bpm_min"),
|
||||
"bpm_max": song.data.get_int("bpm_max"),
|
||||
"limited": song.data.get_int("limited"),
|
||||
}
|
||||
|
||||
def __format_song(self, song: Song) -> Dict[str, Any]:
|
||||
base = {
|
||||
'song': str(song.id),
|
||||
'chart': str(song.chart),
|
||||
'title': song.name or "",
|
||||
'artist': song.artist or "",
|
||||
'genre': song.genre or "",
|
||||
"song": str(song.id),
|
||||
"chart": str(song.chart),
|
||||
"title": song.name or "",
|
||||
"artist": song.artist or "",
|
||||
"genre": song.genre or "",
|
||||
}
|
||||
|
||||
if self.game == GameConstants.DDR:
|
||||
@@ -198,7 +199,7 @@ class CatalogObject(BaseObject):
|
||||
"type": item.type[3:],
|
||||
}
|
||||
for item in items
|
||||
if item.type in ['qp_body', 'qp_face', 'qp_hair', 'qp_hand', 'qp_head']
|
||||
if item.type in ["qp_body", "qp_face", "qp_hair", "qp_hand", "qp_head"]
|
||||
],
|
||||
}
|
||||
|
||||
@@ -222,17 +223,22 @@ class CatalogObject(BaseObject):
|
||||
else:
|
||||
return self.version
|
||||
|
||||
def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> Dict[str, List[Dict[str, Any]]]:
|
||||
def fetch_v1(
|
||||
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
|
||||
) -> Dict[str, List[Dict[str, Any]]]:
|
||||
# Verify IDs
|
||||
if idtype != APIConstants.ID_TYPE_SERVER:
|
||||
raise APIException(
|
||||
'Unsupported ID for lookup!',
|
||||
"Unsupported ID for lookup!",
|
||||
405,
|
||||
)
|
||||
|
||||
# Fetch the songs
|
||||
songs = self.data.local.music.get_all_songs(self.game, self.music_version)
|
||||
if self.game == GameConstants.JUBEAT and self.version == VersionConstants.JUBEAT_CLAN:
|
||||
if (
|
||||
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
|
||||
# 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
|
||||
@@ -255,7 +261,7 @@ class CatalogObject(BaseObject):
|
||||
)
|
||||
songs.extend(additions)
|
||||
retval = {
|
||||
'songs': [self.__format_song(song) for song in songs],
|
||||
"songs": [self.__format_song(song) for song in songs],
|
||||
}
|
||||
|
||||
# Fetch any optional extras per-game, return
|
||||
|
||||
@@ -7,24 +7,23 @@ from bemani.data import UserID
|
||||
|
||||
|
||||
class ProfileObject(BaseObject):
|
||||
|
||||
def __format_ddr_profile(self, profile: Profile, exact: bool) -> Dict[str, Any]:
|
||||
return {
|
||||
'area': profile.get_int('area', -1) if exact else -1,
|
||||
"area": profile.get_int("area", -1) if exact else -1,
|
||||
}
|
||||
|
||||
def __format_iidx_profile(self, profile: Profile, exact: bool) -> Dict[str, Any]:
|
||||
qpro = profile.get_dict('qpro')
|
||||
qpro = profile.get_dict("qpro")
|
||||
|
||||
return {
|
||||
'area': profile.get_int('pid', -1),
|
||||
'qpro': {
|
||||
'head': qpro.get_int('head', -1) if exact else -1,
|
||||
'hair': qpro.get_int('hair', -1) if exact else -1,
|
||||
'face': qpro.get_int('face', -1) if exact else -1,
|
||||
'body': qpro.get_int('body', -1) if exact else -1,
|
||||
'hand': qpro.get_int('hand', -1) if exact else -1,
|
||||
}
|
||||
"area": profile.get_int("pid", -1),
|
||||
"qpro": {
|
||||
"head": qpro.get_int("head", -1) if exact else -1,
|
||||
"hair": qpro.get_int("hair", -1) if exact else -1,
|
||||
"face": qpro.get_int("face", -1) if exact else -1,
|
||||
"body": qpro.get_int("body", -1) if exact else -1,
|
||||
"hand": qpro.get_int("hand", -1) if exact else -1,
|
||||
},
|
||||
}
|
||||
|
||||
def __format_jubeat_profile(self, profile: Profile, exact: bool) -> Dict[str, Any]:
|
||||
@@ -35,25 +34,27 @@ class ProfileObject(BaseObject):
|
||||
|
||||
def __format_popn_profile(self, profile: Profile, exact: bool) -> Dict[str, Any]:
|
||||
return {
|
||||
'character': profile.get_int('chara', -1) if exact else -1,
|
||||
"character": profile.get_int("chara", -1) if exact else -1,
|
||||
}
|
||||
|
||||
def __format_reflec_profile(self, profile: Profile, exact: bool) -> Dict[str, Any]:
|
||||
return {
|
||||
'icon': profile.get_dict('config').get_int('icon_id', -1) if exact else -1,
|
||||
"icon": profile.get_dict("config").get_int("icon_id", -1) if exact else -1,
|
||||
}
|
||||
|
||||
def __format_sdvx_profile(self, profile: Profile, exact: bool) -> Dict[str, Any]:
|
||||
return {}
|
||||
|
||||
def __format_profile(self, cardids: List[str], profile: Profile, settings: ValidatedDict, exact: bool) -> Dict[str, Any]:
|
||||
def __format_profile(
|
||||
self, cardids: List[str], profile: Profile, settings: ValidatedDict, exact: bool
|
||||
) -> Dict[str, Any]:
|
||||
base = {
|
||||
'name': profile.get_str('name'),
|
||||
'cards': cardids,
|
||||
'registered': settings.get_int('first_play_timestamp', -1),
|
||||
'updated': settings.get_int('last_play_timestamp', -1),
|
||||
'plays': settings.get_int('total_plays', -1),
|
||||
'match': 'exact' if exact else 'partial',
|
||||
"name": profile.get_str("name"),
|
||||
"cards": cardids,
|
||||
"registered": settings.get_int("first_play_timestamp", -1),
|
||||
"updated": settings.get_int("last_play_timestamp", -1),
|
||||
"plays": settings.get_int("total_plays", -1),
|
||||
"match": "exact" if exact else "partial",
|
||||
}
|
||||
|
||||
if self.game == GameConstants.DDR:
|
||||
@@ -73,19 +74,23 @@ class ProfileObject(BaseObject):
|
||||
|
||||
return base
|
||||
|
||||
def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||
def fetch_v1(
|
||||
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
|
||||
) -> List[Dict[str, Any]]:
|
||||
# Fetch the profiles
|
||||
profiles: List[Tuple[UserID, Profile]] = []
|
||||
if idtype == APIConstants.ID_TYPE_SERVER:
|
||||
profiles.extend(self.data.local.user.get_all_profiles(self.game, self.version))
|
||||
profiles.extend(
|
||||
self.data.local.user.get_all_profiles(self.game, self.version)
|
||||
)
|
||||
elif idtype == APIConstants.ID_TYPE_SONG:
|
||||
raise APIException(
|
||||
'Unsupported ID for lookup!',
|
||||
"Unsupported ID for lookup!",
|
||||
405,
|
||||
)
|
||||
elif idtype == APIConstants.ID_TYPE_INSTANCE:
|
||||
raise APIException(
|
||||
'Unsupported ID for lookup!',
|
||||
"Unsupported ID for lookup!",
|
||||
405,
|
||||
)
|
||||
elif idtype == APIConstants.ID_TYPE_CARD:
|
||||
@@ -103,11 +108,13 @@ class ProfileObject(BaseObject):
|
||||
# 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
|
||||
# order to not break remote networks, try our best to return any profile.
|
||||
profile = self.data.local.user.get_any_profile(self.game, self.version, userid)
|
||||
profile = self.data.local.user.get_any_profile(
|
||||
self.game, self.version, userid
|
||||
)
|
||||
if profile is not None:
|
||||
profiles.append((userid, profile))
|
||||
else:
|
||||
raise APIException('Invalid ID type!')
|
||||
raise APIException("Invalid ID type!")
|
||||
|
||||
# Now, fetch the users, and filter out profiles belonging to orphaned users
|
||||
retval: List[Dict[str, Any]] = []
|
||||
@@ -126,6 +133,13 @@ class ProfileObject(BaseObject):
|
||||
if settings is None:
|
||||
settings = ValidatedDict({})
|
||||
|
||||
retval.append(self.__format_profile(id_to_cards[userid], profile, settings, profile.version == self.version))
|
||||
retval.append(
|
||||
self.__format_profile(
|
||||
id_to_cards[userid],
|
||||
profile,
|
||||
settings,
|
||||
profile.version == self.version,
|
||||
)
|
||||
)
|
||||
|
||||
return retval
|
||||
|
||||
+156
-131
@@ -7,15 +7,14 @@ from bemani.data import Score, UserID
|
||||
|
||||
|
||||
class RecordsObject(BaseObject):
|
||||
|
||||
def __format_ddr_record(self, record: Score) -> Dict[str, Any]:
|
||||
halo = {
|
||||
DBConstants.DDR_HALO_NONE: 'none',
|
||||
DBConstants.DDR_HALO_GOOD_FULL_COMBO: 'gfc',
|
||||
DBConstants.DDR_HALO_GREAT_FULL_COMBO: 'fc',
|
||||
DBConstants.DDR_HALO_PERFECT_FULL_COMBO: 'pfc',
|
||||
DBConstants.DDR_HALO_MARVELOUS_FULL_COMBO: 'mfc',
|
||||
}.get(record.data.get_int('halo'), 'none')
|
||||
DBConstants.DDR_HALO_NONE: "none",
|
||||
DBConstants.DDR_HALO_GOOD_FULL_COMBO: "gfc",
|
||||
DBConstants.DDR_HALO_GREAT_FULL_COMBO: "fc",
|
||||
DBConstants.DDR_HALO_PERFECT_FULL_COMBO: "pfc",
|
||||
DBConstants.DDR_HALO_MARVELOUS_FULL_COMBO: "mfc",
|
||||
}.get(record.data.get_int("halo"), "none")
|
||||
rank = {
|
||||
DBConstants.DDR_RANK_AAA: "AAA",
|
||||
DBConstants.DDR_RANK_AA_PLUS: "AA+",
|
||||
@@ -33,175 +32,175 @@ class RecordsObject(BaseObject):
|
||||
DBConstants.DDR_RANK_D_PLUS: "D+",
|
||||
DBConstants.DDR_RANK_D: "D",
|
||||
DBConstants.DDR_RANK_E: "E",
|
||||
}.get(record.data.get_int('rank'), 'E')
|
||||
}.get(record.data.get_int("rank"), "E")
|
||||
|
||||
if self.version == VersionConstants.DDR_ACE:
|
||||
# DDR Ace is specia
|
||||
ghost = [int(x) for x in record.data.get_str('ghost')]
|
||||
ghost = [int(x) for x in record.data.get_str("ghost")]
|
||||
else:
|
||||
if 'trace' not in record.data:
|
||||
if "trace" not in record.data:
|
||||
ghost = []
|
||||
else:
|
||||
ghost = record.data.get_int_array('trace', len(record.data['trace']))
|
||||
ghost = record.data.get_int_array("trace", len(record.data["trace"]))
|
||||
|
||||
return {
|
||||
'rank': rank,
|
||||
'halo': halo,
|
||||
'combo': record.data.get_int('combo'),
|
||||
'ghost': ghost,
|
||||
"rank": rank,
|
||||
"halo": halo,
|
||||
"combo": record.data.get_int("combo"),
|
||||
"ghost": ghost,
|
||||
}
|
||||
|
||||
def __format_iidx_record(self, record: Score) -> Dict[str, Any]:
|
||||
status = {
|
||||
DBConstants.IIDX_CLEAR_STATUS_NO_PLAY: 'np',
|
||||
DBConstants.IIDX_CLEAR_STATUS_FAILED: 'failed',
|
||||
DBConstants.IIDX_CLEAR_STATUS_ASSIST_CLEAR: 'ac',
|
||||
DBConstants.IIDX_CLEAR_STATUS_EASY_CLEAR: 'ec',
|
||||
DBConstants.IIDX_CLEAR_STATUS_CLEAR: 'nc',
|
||||
DBConstants.IIDX_CLEAR_STATUS_HARD_CLEAR: 'hc',
|
||||
DBConstants.IIDX_CLEAR_STATUS_EX_HARD_CLEAR: 'exhc',
|
||||
DBConstants.IIDX_CLEAR_STATUS_FULL_COMBO: 'fc',
|
||||
}.get(record.data.get_int('clear_status'), 'np')
|
||||
DBConstants.IIDX_CLEAR_STATUS_NO_PLAY: "np",
|
||||
DBConstants.IIDX_CLEAR_STATUS_FAILED: "failed",
|
||||
DBConstants.IIDX_CLEAR_STATUS_ASSIST_CLEAR: "ac",
|
||||
DBConstants.IIDX_CLEAR_STATUS_EASY_CLEAR: "ec",
|
||||
DBConstants.IIDX_CLEAR_STATUS_CLEAR: "nc",
|
||||
DBConstants.IIDX_CLEAR_STATUS_HARD_CLEAR: "hc",
|
||||
DBConstants.IIDX_CLEAR_STATUS_EX_HARD_CLEAR: "exhc",
|
||||
DBConstants.IIDX_CLEAR_STATUS_FULL_COMBO: "fc",
|
||||
}.get(record.data.get_int("clear_status"), "np")
|
||||
|
||||
return {
|
||||
'status': status,
|
||||
'miss': record.data.get_int('miss_count', -1),
|
||||
'ghost': [b for b in record.data.get_bytes('ghost')],
|
||||
'pgreat': record.data.get_int('pgreats', -1),
|
||||
'great': record.data.get_int('greats', -1),
|
||||
"status": status,
|
||||
"miss": record.data.get_int("miss_count", -1),
|
||||
"ghost": [b for b in record.data.get_bytes("ghost")],
|
||||
"pgreat": record.data.get_int("pgreats", -1),
|
||||
"great": record.data.get_int("greats", -1),
|
||||
}
|
||||
|
||||
def __format_jubeat_record(self, record: Score) -> Dict[str, Any]:
|
||||
status = {
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_FAILED: 'failed',
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_CLEARED: 'cleared',
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_FULL_COMBO: 'nfc',
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_FULL_COMBO: 'fc',
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_EXCELLENT: 'nec',
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT: 'exc',
|
||||
}.get(record.data.get_int('medal'), 'failed')
|
||||
if 'ghost' not in record.data:
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_FAILED: "failed",
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_CLEARED: "cleared",
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_FULL_COMBO: "nfc",
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_FULL_COMBO: "fc",
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_EXCELLENT: "nec",
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT: "exc",
|
||||
}.get(record.data.get_int("medal"), "failed")
|
||||
if "ghost" not in record.data:
|
||||
ghost: List[int] = []
|
||||
else:
|
||||
ghost = record.data.get_int_array('ghost', len(record.data['ghost']))
|
||||
ghost = record.data.get_int_array("ghost", len(record.data["ghost"]))
|
||||
|
||||
return {
|
||||
'status': status,
|
||||
'combo': record.data.get_int('combo', -1),
|
||||
'ghost': ghost,
|
||||
'music_rate': record.data.get_int('music_rate'),
|
||||
"status": status,
|
||||
"combo": record.data.get_int("combo", -1),
|
||||
"ghost": ghost,
|
||||
"music_rate": record.data.get_int("music_rate"),
|
||||
}
|
||||
|
||||
def __format_museca_record(self, record: Score) -> Dict[str, Any]:
|
||||
rank = {
|
||||
DBConstants.MUSECA_GRADE_DEATH: 'death',
|
||||
DBConstants.MUSECA_GRADE_POOR: 'poor',
|
||||
DBConstants.MUSECA_GRADE_MEDIOCRE: 'mediocre',
|
||||
DBConstants.MUSECA_GRADE_GOOD: 'good',
|
||||
DBConstants.MUSECA_GRADE_GREAT: 'great',
|
||||
DBConstants.MUSECA_GRADE_EXCELLENT: 'excellent',
|
||||
DBConstants.MUSECA_GRADE_SUPERB: 'superb',
|
||||
DBConstants.MUSECA_GRADE_MASTERPIECE: 'masterpiece',
|
||||
DBConstants.MUSECA_GRADE_PERFECT: 'perfect'
|
||||
}.get(record.data.get_int('grade'), 'death')
|
||||
DBConstants.MUSECA_GRADE_DEATH: "death",
|
||||
DBConstants.MUSECA_GRADE_POOR: "poor",
|
||||
DBConstants.MUSECA_GRADE_MEDIOCRE: "mediocre",
|
||||
DBConstants.MUSECA_GRADE_GOOD: "good",
|
||||
DBConstants.MUSECA_GRADE_GREAT: "great",
|
||||
DBConstants.MUSECA_GRADE_EXCELLENT: "excellent",
|
||||
DBConstants.MUSECA_GRADE_SUPERB: "superb",
|
||||
DBConstants.MUSECA_GRADE_MASTERPIECE: "masterpiece",
|
||||
DBConstants.MUSECA_GRADE_PERFECT: "perfect",
|
||||
}.get(record.data.get_int("grade"), "death")
|
||||
status = {
|
||||
DBConstants.MUSECA_CLEAR_TYPE_FAILED: 'failed',
|
||||
DBConstants.MUSECA_CLEAR_TYPE_CLEARED: 'cleared',
|
||||
DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO: 'fc',
|
||||
}.get(record.data.get_int('clear_type'), 'failed')
|
||||
DBConstants.MUSECA_CLEAR_TYPE_FAILED: "failed",
|
||||
DBConstants.MUSECA_CLEAR_TYPE_CLEARED: "cleared",
|
||||
DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO: "fc",
|
||||
}.get(record.data.get_int("clear_type"), "failed")
|
||||
|
||||
return {
|
||||
'rank': rank,
|
||||
'status': status,
|
||||
'combo': record.data.get_int('combo', -1),
|
||||
'buttonrate': record.data.get_dict('stats').get_int('btn_rate'),
|
||||
'longrate': record.data.get_dict('stats').get_int('long_rate'),
|
||||
'volrate': record.data.get_dict('stats').get_int('vol_rate'),
|
||||
"rank": rank,
|
||||
"status": status,
|
||||
"combo": record.data.get_int("combo", -1),
|
||||
"buttonrate": record.data.get_dict("stats").get_int("btn_rate"),
|
||||
"longrate": record.data.get_dict("stats").get_int("long_rate"),
|
||||
"volrate": record.data.get_dict("stats").get_int("vol_rate"),
|
||||
}
|
||||
|
||||
def __format_popn_record(self, record: Score) -> Dict[str, Any]:
|
||||
status = {
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FAILED: 'cf',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FAILED: 'df',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FAILED: 'sf',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_EASY_CLEAR: 'ec',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_CLEARED: 'cc',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_CLEARED: 'dc',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_CLEARED: 'sc',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FULL_COMBO: 'cfc',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FULL_COMBO: 'dfc',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FULL_COMBO: 'sfc',
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_PERFECT: 'p',
|
||||
}.get(record.data.get_int('medal'), 'cf')
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FAILED: "cf",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FAILED: "df",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FAILED: "sf",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_EASY_CLEAR: "ec",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_CLEARED: "cc",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_CLEARED: "dc",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_CLEARED: "sc",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FULL_COMBO: "cfc",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FULL_COMBO: "dfc",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FULL_COMBO: "sfc",
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_PERFECT: "p",
|
||||
}.get(record.data.get_int("medal"), "cf")
|
||||
|
||||
return {
|
||||
'status': status,
|
||||
'combo': record.data.get_int('combo', -1),
|
||||
"status": status,
|
||||
"combo": record.data.get_int("combo", -1),
|
||||
}
|
||||
|
||||
def __format_reflec_record(self, record: Score) -> Dict[str, Any]:
|
||||
status = {
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY: 'np',
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED: 'failed',
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_CLEARED: 'cleared',
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_HARD_CLEARED: 'hc',
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_S_HARD_CLEARED: 'shc',
|
||||
}.get(record.data.get_int('clear_type'), 'np')
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY: "np",
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED: "failed",
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_CLEARED: "cleared",
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_HARD_CLEARED: "hc",
|
||||
DBConstants.REFLEC_BEAT_CLEAR_TYPE_S_HARD_CLEARED: "shc",
|
||||
}.get(record.data.get_int("clear_type"), "np")
|
||||
halo = {
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_NONE: 'none',
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_ALMOST_COMBO: 'ac',
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO: 'fc',
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO_ALL_JUST: 'fcaj',
|
||||
}.get(record.data.get_int('combo_type'), 'none')
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_NONE: "none",
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_ALMOST_COMBO: "ac",
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO: "fc",
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO_ALL_JUST: "fcaj",
|
||||
}.get(record.data.get_int("combo_type"), "none")
|
||||
|
||||
return {
|
||||
'rate': record.data.get_int('achievement_rate'),
|
||||
'status': status,
|
||||
'halo': halo,
|
||||
'combo': record.data.get_int('combo', -1),
|
||||
'miss': record.data.get_int('miss_count', -1),
|
||||
"rate": record.data.get_int("achievement_rate"),
|
||||
"status": status,
|
||||
"halo": halo,
|
||||
"combo": record.data.get_int("combo", -1),
|
||||
"miss": record.data.get_int("miss_count", -1),
|
||||
}
|
||||
|
||||
def __format_sdvx_record(self, record: Score) -> Dict[str, Any]:
|
||||
status = {
|
||||
DBConstants.SDVX_CLEAR_TYPE_NO_PLAY: 'np',
|
||||
DBConstants.SDVX_CLEAR_TYPE_FAILED: 'failed',
|
||||
DBConstants.SDVX_CLEAR_TYPE_CLEAR: 'cleared',
|
||||
DBConstants.SDVX_CLEAR_TYPE_HARD_CLEAR: 'hc',
|
||||
DBConstants.SDVX_CLEAR_TYPE_ULTIMATE_CHAIN: 'uc',
|
||||
DBConstants.SDVX_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN: 'puc',
|
||||
}.get(record.data.get_int('clear_type'), 'np')
|
||||
DBConstants.SDVX_CLEAR_TYPE_NO_PLAY: "np",
|
||||
DBConstants.SDVX_CLEAR_TYPE_FAILED: "failed",
|
||||
DBConstants.SDVX_CLEAR_TYPE_CLEAR: "cleared",
|
||||
DBConstants.SDVX_CLEAR_TYPE_HARD_CLEAR: "hc",
|
||||
DBConstants.SDVX_CLEAR_TYPE_ULTIMATE_CHAIN: "uc",
|
||||
DBConstants.SDVX_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN: "puc",
|
||||
}.get(record.data.get_int("clear_type"), "np")
|
||||
rank = {
|
||||
DBConstants.SDVX_GRADE_NO_PLAY: 'E',
|
||||
DBConstants.SDVX_GRADE_D: 'D',
|
||||
DBConstants.SDVX_GRADE_C: 'C',
|
||||
DBConstants.SDVX_GRADE_B: 'B',
|
||||
DBConstants.SDVX_GRADE_A: 'A',
|
||||
DBConstants.SDVX_GRADE_A_PLUS: 'A+',
|
||||
DBConstants.SDVX_GRADE_AA: 'AA',
|
||||
DBConstants.SDVX_GRADE_AA_PLUS: 'AA+',
|
||||
DBConstants.SDVX_GRADE_AAA: 'AAA',
|
||||
DBConstants.SDVX_GRADE_AAA_PLUS: 'AAA+',
|
||||
DBConstants.SDVX_GRADE_S: 'S',
|
||||
}.get(record.data.get_int('grade'), 'E')
|
||||
DBConstants.SDVX_GRADE_NO_PLAY: "E",
|
||||
DBConstants.SDVX_GRADE_D: "D",
|
||||
DBConstants.SDVX_GRADE_C: "C",
|
||||
DBConstants.SDVX_GRADE_B: "B",
|
||||
DBConstants.SDVX_GRADE_A: "A",
|
||||
DBConstants.SDVX_GRADE_A_PLUS: "A+",
|
||||
DBConstants.SDVX_GRADE_AA: "AA",
|
||||
DBConstants.SDVX_GRADE_AA_PLUS: "AA+",
|
||||
DBConstants.SDVX_GRADE_AAA: "AAA",
|
||||
DBConstants.SDVX_GRADE_AAA_PLUS: "AAA+",
|
||||
DBConstants.SDVX_GRADE_S: "S",
|
||||
}.get(record.data.get_int("grade"), "E")
|
||||
|
||||
return {
|
||||
'status': status,
|
||||
'rank': rank,
|
||||
'combo': record.data.get_int('combo', -1),
|
||||
'buttonrate': record.data.get_dict('stats').get_int('btn_rate'),
|
||||
'longrate': record.data.get_dict('stats').get_int('long_rate'),
|
||||
'volrate': record.data.get_dict('stats').get_int('vol_rate'),
|
||||
"status": status,
|
||||
"rank": rank,
|
||||
"combo": record.data.get_int("combo", -1),
|
||||
"buttonrate": record.data.get_dict("stats").get_int("btn_rate"),
|
||||
"longrate": record.data.get_dict("stats").get_int("long_rate"),
|
||||
"volrate": record.data.get_dict("stats").get_int("vol_rate"),
|
||||
}
|
||||
|
||||
def __format_record(self, cardids: List[str], record: Score) -> Dict[str, Any]:
|
||||
base = {
|
||||
'cards': cardids,
|
||||
'song': str(record.id),
|
||||
'chart': str(record.chart),
|
||||
'points': record.points,
|
||||
'timestamp': record.timestamp,
|
||||
'updated': record.update,
|
||||
"cards": cardids,
|
||||
"song": str(record.id),
|
||||
"chart": str(record.chart),
|
||||
"points": record.points,
|
||||
"timestamp": record.timestamp,
|
||||
"updated": record.update,
|
||||
}
|
||||
|
||||
if self.game == GameConstants.DDR:
|
||||
@@ -231,9 +230,11 @@ class RecordsObject(BaseObject):
|
||||
else:
|
||||
return self.version
|
||||
|
||||
def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||
since = params.get('since')
|
||||
until = params.get('until')
|
||||
def fetch_v1(
|
||||
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
|
||||
) -> List[Dict[str, Any]]:
|
||||
since = params.get("since")
|
||||
until = params.get("until")
|
||||
|
||||
# Fetch the scores
|
||||
records: List[Tuple[UserID, Score]] = []
|
||||
@@ -241,7 +242,9 @@ class RecordsObject(BaseObject):
|
||||
# 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
|
||||
# incorrectly report records.
|
||||
records.extend(self.data.local.music.get_all_records(self.game, self.music_version))
|
||||
records.extend(
|
||||
self.data.local.music.get_all_records(self.game, self.music_version)
|
||||
)
|
||||
elif idtype == APIConstants.ID_TYPE_SONG:
|
||||
if len(ids) == 1:
|
||||
songid = int(ids[0])
|
||||
@@ -249,14 +252,25 @@ class RecordsObject(BaseObject):
|
||||
else:
|
||||
songid = int(ids[0])
|
||||
chart = int(ids[1])
|
||||
records.extend(self.data.local.music.get_all_scores(self.game, self.music_version, songid=songid, songchart=chart, since=since, until=until))
|
||||
records.extend(
|
||||
self.data.local.music.get_all_scores(
|
||||
self.game,
|
||||
self.music_version,
|
||||
songid=songid,
|
||||
songchart=chart,
|
||||
since=since,
|
||||
until=until,
|
||||
)
|
||||
)
|
||||
elif idtype == APIConstants.ID_TYPE_INSTANCE:
|
||||
songid = int(ids[0])
|
||||
chart = int(ids[1])
|
||||
cardid = ids[2]
|
||||
userid = self.data.local.user.from_cardid(cardid)
|
||||
if userid is not None:
|
||||
score = self.data.local.music.get_score(self.game, self.music_version, userid, songid, chart)
|
||||
score = self.data.local.music.get_score(
|
||||
self.game, self.music_version, userid, songid, chart
|
||||
)
|
||||
if score is not None:
|
||||
records.append((userid, score))
|
||||
elif idtype == APIConstants.ID_TYPE_CARD:
|
||||
@@ -270,9 +284,20 @@ class RecordsObject(BaseObject):
|
||||
continue
|
||||
users.add(userid)
|
||||
|
||||
records.extend([(userid, score) for score in self.data.local.music.get_scores(self.game, self.music_version, userid, since=since, until=until)])
|
||||
records.extend(
|
||||
[
|
||||
(userid, score)
|
||||
for score in self.data.local.music.get_scores(
|
||||
self.game,
|
||||
self.music_version,
|
||||
userid,
|
||||
since=since,
|
||||
until=until,
|
||||
)
|
||||
]
|
||||
)
|
||||
else:
|
||||
raise APIException('Invalid ID type!')
|
||||
raise APIException("Invalid ID type!")
|
||||
|
||||
# Now, fetch the users, and filter out scores belonging to orphaned users
|
||||
id_to_cards: Dict[UserID, List[str]] = {}
|
||||
|
||||
@@ -7,20 +7,21 @@ from bemani.data import Attempt, UserID
|
||||
|
||||
|
||||
class StatisticsObject(BaseObject):
|
||||
|
||||
def __format_statistics(self, stats: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {
|
||||
'cards': [],
|
||||
'song': str(stats['id']),
|
||||
'chart': str(stats['chart']),
|
||||
'plays': stats.get('plays', -1),
|
||||
'clears': stats.get('clears', -1),
|
||||
'combos': stats.get('combos', -1),
|
||||
"cards": [],
|
||||
"song": str(stats["id"]),
|
||||
"chart": str(stats["chart"]),
|
||||
"plays": stats.get("plays", -1),
|
||||
"clears": stats.get("clears", -1),
|
||||
"combos": stats.get("combos", -1),
|
||||
}
|
||||
|
||||
def __format_user_statistics(self, cardids: List[str], stats: Dict[str, Any]) -> Dict[str, Any]:
|
||||
def __format_user_statistics(
|
||||
self, cardids: List[str], stats: Dict[str, Any]
|
||||
) -> Dict[str, Any]:
|
||||
base = self.__format_statistics(stats)
|
||||
base['cards'] = cardids
|
||||
base["cards"] = cardids
|
||||
return base
|
||||
|
||||
@property
|
||||
@@ -42,11 +43,20 @@ class StatisticsObject(BaseObject):
|
||||
}:
|
||||
return True
|
||||
if self.game == GameConstants.IIDX:
|
||||
return attempt.data.get_int('clear_status') != DBConstants.IIDX_CLEAR_STATUS_NO_PLAY
|
||||
return (
|
||||
attempt.data.get_int("clear_status")
|
||||
!= DBConstants.IIDX_CLEAR_STATUS_NO_PLAY
|
||||
)
|
||||
if self.game == GameConstants.REFLEC_BEAT:
|
||||
return attempt.data.get_int('clear_type') != DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY
|
||||
return (
|
||||
attempt.data.get_int("clear_type")
|
||||
!= DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY
|
||||
)
|
||||
if self.game == GameConstants.SDVX:
|
||||
return attempt.data.get_int('clear_type') != DBConstants.SDVX_CLEAR_TYPE_NO_PLAY
|
||||
return (
|
||||
attempt.data.get_int("clear_type")
|
||||
!= DBConstants.SDVX_CLEAR_TYPE_NO_PLAY
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
@@ -55,29 +65,39 @@ class StatisticsObject(BaseObject):
|
||||
return False
|
||||
|
||||
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:
|
||||
return attempt.data.get_int('clear_status') != DBConstants.IIDX_CLEAR_STATUS_FAILED
|
||||
return (
|
||||
attempt.data.get_int("clear_status")
|
||||
!= DBConstants.IIDX_CLEAR_STATUS_FAILED
|
||||
)
|
||||
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:
|
||||
return attempt.data.get_int('clear_type') != DBConstants.MUSECA_CLEAR_TYPE_FAILED
|
||||
return (
|
||||
attempt.data.get_int("clear_type")
|
||||
!= DBConstants.MUSECA_CLEAR_TYPE_FAILED
|
||||
)
|
||||
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_DIAMOND_FAILED,
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FAILED,
|
||||
]
|
||||
if self.game == GameConstants.REFLEC_BEAT:
|
||||
return attempt.data.get_int('clear_type') != DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED
|
||||
if self.game == GameConstants.SDVX:
|
||||
return (
|
||||
attempt.data.get_int('grade') != DBConstants.SDVX_GRADE_NO_PLAY and
|
||||
attempt.data.get_int('clear_type') not in [
|
||||
DBConstants.SDVX_CLEAR_TYPE_NO_PLAY,
|
||||
DBConstants.SDVX_CLEAR_TYPE_FAILED,
|
||||
]
|
||||
attempt.data.get_int("clear_type")
|
||||
!= DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED
|
||||
)
|
||||
if self.game == GameConstants.SDVX:
|
||||
return attempt.data.get_int(
|
||||
"grade"
|
||||
) != DBConstants.SDVX_GRADE_NO_PLAY and attempt.data.get_int(
|
||||
"clear_type"
|
||||
) not in [
|
||||
DBConstants.SDVX_CLEAR_TYPE_NO_PLAY,
|
||||
DBConstants.SDVX_CLEAR_TYPE_FAILED,
|
||||
]
|
||||
|
||||
return False
|
||||
|
||||
@@ -86,31 +106,37 @@ class StatisticsObject(BaseObject):
|
||||
return False
|
||||
|
||||
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:
|
||||
return attempt.data.get_int('clear_status') == DBConstants.IIDX_CLEAR_STATUS_FULL_COMBO
|
||||
return (
|
||||
attempt.data.get_int("clear_status")
|
||||
== DBConstants.IIDX_CLEAR_STATUS_FULL_COMBO
|
||||
)
|
||||
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_NEARLY_EXCELLENT,
|
||||
DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT,
|
||||
]
|
||||
if self.game == GameConstants.MUSECA:
|
||||
return attempt.data.get_int('clear_type') == DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO
|
||||
return (
|
||||
attempt.data.get_int("clear_type")
|
||||
== DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO
|
||||
)
|
||||
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_DIAMOND_FULL_COMBO,
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FULL_COMBO,
|
||||
DBConstants.POPN_MUSIC_PLAY_MEDAL_PERFECT,
|
||||
]
|
||||
if self.game == GameConstants.REFLEC_BEAT:
|
||||
return attempt.data.get_int('combo_type') in [
|
||||
return attempt.data.get_int("combo_type") in [
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO,
|
||||
DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO_ALL_JUST,
|
||||
]
|
||||
if self.game == GameConstants.SDVX:
|
||||
return attempt.data.get_int('clear_type') in [
|
||||
return attempt.data.get_int("clear_type") in [
|
||||
DBConstants.SDVX_CLEAR_TYPE_ULTIMATE_CHAIN,
|
||||
DBConstants.SDVX_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN,
|
||||
]
|
||||
@@ -125,29 +151,31 @@ class StatisticsObject(BaseObject):
|
||||
stats[attempt.id] = {}
|
||||
if attempt.chart not in stats[attempt.id]:
|
||||
stats[attempt.id][attempt.chart] = {
|
||||
'plays': 0,
|
||||
'clears': 0,
|
||||
'combos': 0,
|
||||
"plays": 0,
|
||||
"clears": 0,
|
||||
"combos": 0,
|
||||
}
|
||||
|
||||
if self.__is_play(attempt):
|
||||
stats[attempt.id][attempt.chart]['plays'] += 1
|
||||
stats[attempt.id][attempt.chart]["plays"] += 1
|
||||
if self.__is_clear(attempt):
|
||||
stats[attempt.id][attempt.chart]['clears'] += 1
|
||||
stats[attempt.id][attempt.chart]["clears"] += 1
|
||||
if self.__is_combo(attempt):
|
||||
stats[attempt.id][attempt.chart]['combos'] += 1
|
||||
stats[attempt.id][attempt.chart]["combos"] += 1
|
||||
|
||||
retval = []
|
||||
for songid in stats:
|
||||
for songchart in stats[songid]:
|
||||
stat = stats[songid][songchart]
|
||||
stat['id'] = songid
|
||||
stat['chart'] = songchart
|
||||
stat["id"] = songid
|
||||
stat["chart"] = songchart
|
||||
retval.append(self.__format_statistics(stat))
|
||||
|
||||
return retval
|
||||
|
||||
def __aggregate_local(self, cards: Dict[int, List[str]], attempts: List[Tuple[UserID, Attempt]]) -> List[Dict[str, Any]]:
|
||||
def __aggregate_local(
|
||||
self, cards: Dict[int, List[str]], attempts: List[Tuple[UserID, Attempt]]
|
||||
) -> List[Dict[str, Any]]:
|
||||
stats: Dict[UserID, Dict[int, Dict[int, Dict[str, int]]]] = {}
|
||||
|
||||
for (userid, attempt) in attempts:
|
||||
@@ -157,36 +185,43 @@ class StatisticsObject(BaseObject):
|
||||
stats[userid][attempt.id] = {}
|
||||
if attempt.chart not in stats[userid][attempt.id]:
|
||||
stats[userid][attempt.id][attempt.chart] = {
|
||||
'plays': 0,
|
||||
'clears': 0,
|
||||
'combos': 0,
|
||||
"plays": 0,
|
||||
"clears": 0,
|
||||
"combos": 0,
|
||||
}
|
||||
|
||||
if self.__is_play(attempt):
|
||||
stats[userid][attempt.id][attempt.chart]['plays'] += 1
|
||||
stats[userid][attempt.id][attempt.chart]["plays"] += 1
|
||||
if self.__is_clear(attempt):
|
||||
stats[userid][attempt.id][attempt.chart]['clears'] += 1
|
||||
stats[userid][attempt.id][attempt.chart]["clears"] += 1
|
||||
if self.__is_combo(attempt):
|
||||
stats[userid][attempt.id][attempt.chart]['combos'] += 1
|
||||
stats[userid][attempt.id][attempt.chart]["combos"] += 1
|
||||
|
||||
retval = []
|
||||
for userid in stats:
|
||||
for songid in stats[userid]:
|
||||
for songchart in stats[userid][songid]:
|
||||
stat = stats[userid][songid][songchart]
|
||||
stat['id'] = songid
|
||||
stat['chart'] = songchart
|
||||
stat["id"] = songid
|
||||
stat["chart"] = songchart
|
||||
retval.append(self.__format_user_statistics(cards[userid], stat))
|
||||
|
||||
return retval
|
||||
|
||||
def fetch_v1(self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||
def fetch_v1(
|
||||
self, idtype: APIConstants, ids: List[str], params: Dict[str, Any]
|
||||
) -> List[Dict[str, Any]]:
|
||||
retval: List[Dict[str, Any]] = []
|
||||
|
||||
# Fetch the attempts
|
||||
if idtype == APIConstants.ID_TYPE_SERVER:
|
||||
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:
|
||||
if len(ids) == 1:
|
||||
@@ -196,7 +231,12 @@ class StatisticsObject(BaseObject):
|
||||
songid = int(ids[0])
|
||||
chart = int(ids[1])
|
||||
retval = self.__aggregate_global(
|
||||
[attempt[1] for attempt in self.data.local.music.get_all_attempts(self.game, self.music_version, songid=songid, songchart=chart)]
|
||||
[
|
||||
attempt[1]
|
||||
for attempt in self.data.local.music.get_all_attempts(
|
||||
self.game, self.music_version, songid=songid, songchart=chart
|
||||
)
|
||||
]
|
||||
)
|
||||
elif idtype == APIConstants.ID_TYPE_INSTANCE:
|
||||
songid = int(ids[0])
|
||||
@@ -206,7 +246,13 @@ class StatisticsObject(BaseObject):
|
||||
if userid is not None:
|
||||
retval = self.__aggregate_local(
|
||||
{userid: self.data.local.user.get_cards(userid)},
|
||||
self.data.local.music.get_all_attempts(self.game, self.music_version, songid=songid, songchart=chart, userid=userid)
|
||||
self.data.local.music.get_all_attempts(
|
||||
self.game,
|
||||
self.music_version,
|
||||
songid=songid,
|
||||
songchart=chart,
|
||||
userid=userid,
|
||||
),
|
||||
)
|
||||
elif idtype == APIConstants.ID_TYPE_CARD:
|
||||
id_to_cards: Dict[int, List[str]] = {}
|
||||
@@ -221,10 +267,12 @@ class StatisticsObject(BaseObject):
|
||||
|
||||
id_to_cards[userid] = self.data.local.user.get_cards(userid)
|
||||
attempts.extend(
|
||||
self.data.local.music.get_all_attempts(self.game, self.music_version, userid=userid)
|
||||
self.data.local.music.get_all_attempts(
|
||||
self.game, self.music_version, userid=userid
|
||||
)
|
||||
)
|
||||
retval = self.__aggregate_local(id_to_cards, attempts)
|
||||
else:
|
||||
raise APIException('Invalid ID type!')
|
||||
raise APIException("Invalid ID type!")
|
||||
|
||||
return retval
|
||||
|
||||
Reference in New Issue
Block a user