1
0
mirror of synced 2024-12-15 15:51:15 +01:00
bemaniutils/bemani/backend/jubeat/course.py

543 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# vim: set fileencoding=utf-8
from typing import Any, Dict, List
from typing_extensions import Final
from bemani.data import UserID
from bemani.backend.jubeat.base import JubeatBase
class JubeatCourse(JubeatBase):
COURSE_RATING_FAILED: Final[int] = 100
COURSE_RATING_BRONZE: Final[int] = 200
COURSE_RATING_SILVER: Final[int] = 300
COURSE_RATING_GOLD: Final[int] = 400
COURSE_REQUIREMENT_SCORE: Final[int] = 100
COURSE_REQUIREMENT_FULL_COMBO: Final[int] = 200
COURSE_REQUIREMENT_PERFECT_PERCENT: Final[int] = 300
def get_all_courses(self) -> List[Dict[str, Any]]:
# List of base courses for Saucer Fulfill+ from BemaniWiki
return [
{
'id': 1,
'name': '溢れ出した記憶、特別なあなたにありがとう。',
'level': 1,
'music': [
(50000241, 2),
(10000052, 2),
(30000042, 2),
(50000085, 2),
(50000144, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [850000, 900000, 950000],
self.COURSE_REQUIREMENT_FULL_COMBO: [0, 1, 2],
},
},
{
'id': 2,
'name': 'コースモードが怖いばっかお前TAGがついてるだろ',
'level': 1,
'music': [
(50000121, 1),
(30000122, 1),
(40000159, 1),
(50000089, 1),
(40000051, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [800000, 850000, 900000],
self.COURSE_REQUIREMENT_FULL_COMBO: [0, 1, 2],
},
},
{
'id': 3,
'name': '満月の鐘踊り響くは虚空から成る恋の歌',
'level': 2,
'music': [
(40000121, 2),
(50000188, 2),
(30000047, 2),
(50000237, 2),
(50000176, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [850000, 900000, 950000],
self.COURSE_REQUIREMENT_FULL_COMBO: [1, 2, 3],
},
},
{
'id': 4,
'name': 'スミスゼミナール 夏の陣開講記念 基本編',
'level': 2,
'music': [
(50000267, 1),
(50000233, 1),
(50000228, 1),
(50000268, 1),
(50000291, 1),
],
'requirements': {
self.COURSE_REQUIREMENT_FULL_COMBO: [1, 2, 3],
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [85, 90, 95],
},
},
{
'id': 5,
'name': 'HARDモードじゃないから、絶対、大丈夫だよっ',
'level': 2,
'music': [
(50000144, 2),
(50000188, 2),
(50000070, 2),
(50000151, 2),
(50000152, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [850000, 900000, 950000],
self.COURSE_REQUIREMENT_FULL_COMBO: [0, 1, 2],
},
},
{
'id': 6,
'name': '星明かりの下、愛という名の日替わりランチを君と',
'level': 3,
'music': [
(50000196, 1),
(50000151, 2),
(50000060, 1),
(40000048, 2),
(10000051, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [70, 80, 90],
},
},
{
'id': 7,
'name': '輝く北極星と幸せなヒーロー',
'level': 4,
'music': [
(50000079, 2),
(20000044, 2),
(50000109, 2),
(10000043, 2),
(10000042, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [900000, 950000, 980000],
self.COURSE_REQUIREMENT_FULL_COMBO: [1, 2, 3],
},
},
{
'id': 8,
'name': '花-鳥-藻-夏',
'level': 4,
'music': [
(10000068, 2),
(40000154, 2),
(50000123, 1),
(40000051, 2),
(30000045, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [70, 80, 90],
},
},
{
'id': 9,
'name': 'TAG生誕祭2014 俺の記録を抜いてみろ!',
'level': 4,
'music': [
(30000122, 2),
(50000086, 2),
(50000121, 2),
(50000196, 2),
(40000051, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [900000, 950000, 967252],
self.COURSE_REQUIREMENT_FULL_COMBO: [0, 0, 1],
},
},
{
'id': 10,
'name': 'さよなら、亡くした恋と蝶の舞うヒストリア',
'level': 5,
'music': [
(20000041, 2),
(30000044, 2),
(50000037, 2),
(20000124, 2),
(50000033, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [80, 85, 90],
},
},
{
'id': 11,
'name': 'きらきらほしふるまぼろしなぎさちゃん',
'level': 5,
'music': [
(30000050, 2),
(30000049, 2),
(50000235, 2),
(50000157, 2),
(50000038, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [700000, 800000, 900000],
},
},
{
'id': 12,
'name': 'The Memorial Third: 僕みたいに演奏してね',
'level': 5,
'music': [
(10000037, 2),
(20000048, 1),
(50000253, 1),
(20000121, 2),
(50000133, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [75, 80, 85],
},
},
{
'id': 13,
'name': 'Enjoy! 4thKAC ~ Memories of saucer ~',
'level': 5,
'music': [
(50000206, 1),
(50000023, 1),
(50000078, 1),
(50000203, 1),
(50000323, 1),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [900000, 950000, 980000],
self.COURSE_REQUIREMENT_FULL_COMBO: [1, 2, 4],
},
},
{
'id': 14,
'name': '風に吹かれるキケンなシロクマダンス',
'level': 6,
'music': [
(50000059, 2),
(50000197, 2),
(30000037, 2),
(50000182, 2),
(20000038, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [900000, 950000, 980000],
self.COURSE_REQUIREMENT_FULL_COMBO: [1, 2, 3],
},
},
{
'id': 15,
'name': '君主は視線で友との愛を語るめう',
'level': 6,
'music': [
(40000052, 2),
(50000152, 2),
(50000090, 2),
(20000040, 2),
(50000184, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [85, 90, 95],
},
},
{
'id': 16,
'name': 'スミスゼミナール 夏の陣開講記念 応用編',
'level': 6,
'music': [
(50000233, 2),
(50000267, 2),
(50000268, 2),
(50000228, 2),
(50000291, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [750000, 850000, 900000],
},
},
{
'id': 17,
'name': '天から降り注ぐ星はまるで甘いキャンディ',
'level': 7,
'music': [
(20000044, 2),
(30000050, 2),
(50000080, 2),
(40000126, 2),
(10000067, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [85, 90, 95],
},
},
{
'id': 18,
'name': 'てんとう虫が囁いている「Wow Wow…」',
'level': 7,
'music': [
(50000132, 2),
(40000128, 2),
(10000036, 2),
(50000119, 2),
(50000030, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [85, 90, 95],
},
},
{
'id': 19,
'name': 'HARDモードでも大丈夫だよ絶対、大丈夫だよっ',
'level': 7,
'music': [
(50000144, 2),
(50000070, 2),
(50000188, 2),
(50000151, 2),
(50000152, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [850000, 900000, 950000],
},
},
{
'id': 20,
'name': 'こんなHARDモード、滅べばいい…',
'level': 7,
'music': [
(50000294, 2),
(50000295, 2),
(50000234, 2),
(50000245, 2),
(50000282, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [850000, 900000, 950000],
},
},
{
'id': 21,
'name': 'Challenge! 4thKAC ~ Memories of saucer ~',
'level': 7,
'music': [
(50000206, 2),
(50000023, 2),
(50000078, 2),
(50000203, 2),
(50000323, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [900000, 950000, 980000],
},
},
{
'id': 22,
'name': 'サヨナラ・キングコング ~ 恋のつぼみは愛の虹へ ~',
'level': 8,
'music': [
(50000148, 2),
(50000101, 2),
(10000064, 2),
(50000171, 2),
(50000070, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [900000, 950000, 980000],
},
},
{
'id': 23,
'name': '風に舞う白鳥の翼と花弁、さながら万華鏡のよう',
'level': 8,
'music': [
(30000036, 2),
(50000122, 2),
(10000062, 2),
(50000199, 2),
(40000153, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [90, 95, 98],
},
},
{
'id': 24,
'name': 'The 小さなおぼろガチョウ♪',
'level': 8,
'music': [
(50000049, 2),
(50000071, 2),
(10000041, 2),
(50000031, 2),
(40000129, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [970000, 980000, 990000],
self.COURSE_REQUIREMENT_FULL_COMBO: [2, 3, 4],
},
},
{
'id': 25,
'name': 'TAG生誕祭2014 俺の記録を抜いてみろ!~ HARD編 ~',
'level': 8,
'music': [
(50000089, 2),
(50000083, 2),
(50000210, 2),
(50000030, 2),
(40000159, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [800000, 900000, 931463],
},
},
{
'id': 26,
'name': '凍る世界で見る鳳凰の火の花',
'level': 9,
'music': [
(30000043, 2),
(10000039, 2),
(20000048, 2),
(50000096, 2),
(20000038, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [920000, 950000, 980000],
},
},
{
'id': 27,
'name': '真実の桜が乱れしとき、キルト纏いし君は修羅となる',
'level': 9,
'music': [
(50000113, 2),
(50000184, 2),
(50000177, 2),
(30000124, 2),
(50000078, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_PERFECT_PERCENT: [80, 85, 90],
},
},
{
'id': 28,
'name': 'THE FINAL01 ~ 雷光に月、乙女に花散る祝福を ~',
'level': 10,
'music': [
(10000038, 2),
(20000051, 2),
(30000048, 2),
(40000060, 2),
(50000023, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [920000, 950000, 980000],
},
},
{
'id': 29,
'name': 'The Memorial Third: assimilated all into Nature',
'level': 10,
'music': [
(50000135, 2),
(50000029, 2),
(40000047, 2),
(40000046, 2),
(50000253, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [920000, 950000, 980000],
},
},
{
'id': 30,
'name': '4thKAC ~ Memories of saucer ~',
'level': 10,
'music': [
(50000206, 2),
(50000023, 2),
(50000078, 2),
(50000203, 2),
(50000323, 2),
],
'requirements': {
self.COURSE_REQUIREMENT_SCORE: [920000, 950000, 980000],
},
},
]
def save_course(
self,
userid: UserID,
courseid: int,
rating: int,
scores: List[int],
) -> None:
if len(scores) != 5:
raise Exception('Invalid course scores list!')
if rating not in [
self.COURSE_RATING_FAILED,
self.COURSE_RATING_BRONZE,
self.COURSE_RATING_SILVER,
self.COURSE_RATING_GOLD,
]:
raise Exception('Invalid course rating!')
# Figure out if we should update the rating/scores or not
oldcourse = self.data.local.game.get_achievement(
self.game,
userid,
courseid,
'course',
)
if oldcourse is not None:
# Update the rating if the user did better
rating = max(rating, oldcourse.get_int('rating'))
# Update the scores if the total score was better
if sum(scores) < sum(oldcourse.get_int_array('scores', 5)):
scores = oldcourse.get_int_array('scores', 5)
# Save it as an achievement
self.data.local.game.put_achievement(
self.game,
userid,
courseid,
'course',
{
'rating': rating,
'scores': scores,
},
)
def get_courses(
self,
userid: UserID,
) -> Dict[int, Dict[str, Any]]:
courses = {}
achievements = self.data.local.game.get_achievements(self.game, userid)
for achievement in achievements:
if achievement.type == 'course':
courses[achievement.id] = {
'rating': achievement.data.get_int('rating'),
'scores': achievement.data.get_int_array('scores', 5),
}
return courses