Types, including Final, for all backend classes. Also fixed old-style routing for eacoin.

This commit is contained in:
Jennifer Taylor 2021-09-07 17:56:15 +00:00
parent 63e4a80eba
commit 2f6e116405
71 changed files with 1803 additions and 1780 deletions

View File

@ -13,7 +13,7 @@ class BishiBashiBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
happened.
"""
game = GameConstants.BISHI_BASHI
game: GameConstants = GameConstants.BISHI_BASHI
def previous_version(self) -> Optional['BishiBashiBase']:
"""

View File

@ -1,6 +1,5 @@
# vim: set fileencoding=utf-8
import binascii
import copy
import base64
from collections import Iterable
from typing import Any, Dict, List, Sequence, Union
@ -17,8 +16,8 @@ class TheStarBishiBashi(
BishiBashiBase,
):
name = "The★BishiBashi"
version = VersionConstants.BISHI_BASHI_TSBB
name: str = "The★BishiBashi"
version: int = VersionConstants.BISHI_BASHI_TSBB
@classmethod
def get_settings(cls) -> Dict[str, Any]:
@ -324,7 +323,7 @@ class TheStarBishiBashi(
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile, is_new: bool) -> Profile:
# Profile save request, data values are base64 encoded.
# d is a CSV, and bin1 is binary data.
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
strdatas: List[bytes] = []
bindatas: List[bytes] = []

View File

@ -1,4 +1,4 @@
from typing import Optional
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.bishi.bishi import TheStarBishiBashi
@ -8,7 +8,7 @@ from bemani.data import Config, Data
class BishiBashiFactory(Factory):
MANAGED_CLASSES = [
MANAGED_CLASSES: List[Type[Base]] = [
TheStarBishiBashi,
]

View File

@ -9,6 +9,10 @@ from bemani.common import Time, CardCipher
class PASELIHandler(Base):
"""
A mixin that can be used to provide PASELI services to a game.
Handle PASELI requests. The game will check out a session at the beginning
of the game, make PASELI purchases against that session, and then close it
at the end of of a game. This handler ensures that this works for all games.
"""
INFINITE_PASELI_AMOUNT: Final[int] = 57300
@ -22,12 +26,9 @@ class PASELIHandler(Base):
def handle_eacoin_request(self, request: Node) -> Optional[Node]:
"""
Handle PASELI requests. The game will check out a session at the beginning
of the game, make PASELI purchases against that session, and then close it
ad the end of of a game. This handler ensures that this works for all games.
First, a generic handler to catch if paseli is not enabled, so that each
individual method below doesn't need to handle it.
"""
method = request.attribute('method')
if not self.config.paseli.enabled:
# Refuse to respond, we don't have PASELI enabled
print("PASELI not enabled, ignoring eacoin request")
@ -35,406 +36,406 @@ class PASELIHandler(Base):
root.set_attribute('status', str(Status.NOT_ALLOWED))
return root
if method == 'checkin':
root = Node.void('eacoin')
cardid = request.child_value('cardid')
pin = request.child_value('passwd')
if cardid is None or pin is None:
# Refuse to return anything
print("Invalid eacoin checkin request, missing cardid or pin")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
userid = self.data.local.user.from_cardid(cardid)
if userid is None:
# Refuse to do anything
print("No user for eacoin checkin request")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
valid = self.data.local.user.validate_pin(userid, pin)
if not valid:
# Refuse to do anything
print("User entered invalid pin for eacoin checkin request")
root.set_attribute('status', str(Status.INVALID_PIN))
return root
session = self.data.local.user.create_session(userid)
if self.config.paseli.infinite:
balance = PASELIHandler.INFINITE_PASELI_AMOUNT
else:
if self.config.machine.arcade is None:
# There's no arcade for this machine, but infinite is not
# enabled, so there's no way to find a balance.
balance = 0
else:
balance = self.data.local.user.get_balance(userid, self.config.machine.arcade)
root.add_child(Node.s16('sequence', 0))
root.add_child(Node.u8('acstatus', 0))
root.add_child(Node.string('acid', 'DUMMY_ID'))
root.add_child(Node.string('acname', 'DUMMY_NAME'))
root.add_child(Node.s32('balance', balance))
root.add_child(Node.string('sessid', session))
return root
if method == 'opcheckin':
root = Node.void('eacoin')
passwd = request.child_value('passwd')
if passwd is None:
# Refuse to return anything
print("Invalid eacoin checkin request, missing passwd")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if self.config.machine.arcade is None:
# Machine doesn't belong to an arcade
print("Machine doesn't belong to an arcade")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
arcade = self.data.local.machine.get_arcade(self.config.machine.arcade)
if arcade is None:
# Refuse to do anything
print("No arcade for operator checkin request")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if arcade.pin != passwd:
# Refuse to do anything
print("User entered invalid pin for operator checkin request")
root.set_attribute('status', str(Status.INVALID_PIN))
return root
session = self.data.local.machine.create_session(arcade.id)
root.add_child(Node.string('sessid', session))
return root
elif method == 'consume':
def make_resp(status: int, balance: int) -> Node:
root = Node.void('eacoin')
root.add_child(Node.u8('acstatus', status))
root.add_child(Node.u8('autocharge', 0))
root.add_child(Node.s32('balance', balance))
return root
session = request.child_value('sessid')
payment = request.child_value('payment')
service = request.child_value('service')
details = request.child_value('detail')
if session is None or payment is None:
# Refuse to do anything
print("Invalid eacoin consume request, missing sessid or payment")
return make_resp(2, 0)
userid = self.data.local.user.from_session(session)
if userid is None:
# Refuse to do anything
print("Invalid session for eacoin consume request")
return make_resp(2, 0)
if self.config.paseli.infinite:
balance = PASELIHandler.INFINITE_PASELI_AMOUNT - payment
else:
if self.config.machine.arcade is None:
# There's no arcade for this machine, but infinite is not
# enabled, so there's no way to find a balance, assume failed
# consume payment.
balance = None
else:
# 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.
balance = self.data.local.user.update_balance(userid, self.config.machine.arcade, -payment)
if balance is None:
print("Not enough balance for eacoin consume request")
return make_resp(1, self.data.local.user.get_balance(userid, self.config.machine.arcade))
else:
self.data.local.network.put_event(
'paseli_transaction',
{
'delta': -payment,
'balance': balance,
'service': -service,
'reason': details,
'pcbid': self.config.machine.pcbid,
},
userid=userid,
arcadeid=self.config.machine.arcade,
)
return make_resp(0, balance)
elif method == 'getlog':
root = Node.void('eacoin')
sessid = request.child_value('sessid')
logtype = request.child_value('logtype')
target = request.child_value('target')
limit = request.child_value('perpage')
offset = request.child_value('offset')
# Try to determine whether its a user or an arcade session
userid = self.data.local.user.from_session(sessid)
if userid is None:
arcadeid = self.data.local.machine.from_session(sessid)
else:
arcadeid = None
# Bail out if we don't have any idea what session this is
if userid is None and arcadeid is None:
print("Unable to determine session type")
return root
# If we're a user session, also look up the current arcade
# so we display only entries that happened on this arcade.
if userid is not None:
arcade = self.data.local.machine.get_arcade(self.config.machine.arcade)
if arcade is None:
print("Machine doesn't belong to an arcade")
return root
arcadeid = arcade.id
# Now, look up all transactions for this specific group
events = self.data.local.network.get_events(
userid=userid,
arcadeid=arcadeid,
event='paseli_transaction',
)
# Further filter it down to the current PCBID
events = [event for event in events if event.data.get('pcbid') == target]
# Grab the end of day today as a timestamp
end_of_today = Time.end_of_today()
time_format = '%Y-%m-%d %H:%M:%S'
date_format = '%Y-%m-%d'
# Set up common structure
lognode = Node.void(logtype)
topic = Node.void('topic')
lognode.add_child(topic)
summary = Node.void('summary')
lognode.add_child(summary)
# Display what day we are summed to
topic.add_child(Node.string('sumdate', Time.format(Time.now(), date_format)))
if logtype == 'last7days':
# We show today in the today total, last 7 days prior in the week total
beginning_of_today = end_of_today - Time.SECONDS_IN_DAY
end_of_week = beginning_of_today
beginning_of_week = end_of_week - Time.SECONDS_IN_WEEK
topic.add_child(Node.string('sumfrom', Time.format(beginning_of_week, date_format)))
topic.add_child(Node.string('sumto', Time.format(end_of_week, date_format)))
today_total = sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= beginning_of_today and event.timestamp < end_of_today
])
today_total = sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= beginning_of_today and event.timestamp < end_of_today
])
week_txns = [
-event.data.get_int('delta') for event in events
if event.timestamp >= beginning_of_week and event.timestamp < end_of_week
]
week_total = sum(week_txns)
if len(week_txns) > 0:
week_avg = int(sum(week_txns) / len(week_txns))
else:
week_avg = 0
# We display the totals for each day starting with yesterday and up through 7 days prior.
# Index starts at 0 = yesterday, 1 = the day before, etc...
items = []
for days in range(0, 7):
end_of_day = end_of_week - (days * Time.SECONDS_IN_DAY)
start_of_day = end_of_day - Time.SECONDS_IN_DAY
items.append(sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= start_of_day and event.timestamp < end_of_day
]))
topic.add_child(Node.s32('today', today_total))
topic.add_child(Node.s32('average', week_avg))
topic.add_child(Node.s32('total', week_total))
summary.add_child(Node.s32_array('items', items))
if logtype == 'last52weeks':
# Start one week back, since the operator can look at last7days for newer stuff.
beginning_of_today = end_of_today - Time.SECONDS_IN_DAY
end_of_52_weeks = beginning_of_today - Time.SECONDS_IN_WEEK
topic.add_child(Node.string('sumfrom', Time.format(end_of_52_weeks - (52 * Time.SECONDS_IN_WEEK), date_format)))
topic.add_child(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...
items = []
for weeks in range(0, 52):
end_of_range = end_of_52_weeks - (weeks * Time.SECONDS_IN_WEEK)
beginning_of_range = end_of_range - Time.SECONDS_IN_WEEK
items.append(sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= beginning_of_range and event.timestamp < end_of_range
]))
summary.add_child(Node.s32_array('items', items))
if logtype == 'eachday':
start_ts = Time.now()
end_ts = Time.now()
weekdays = [0] * 7
for event in events:
event_day = Time.days_into_week(event.timestamp)
weekdays[event_day] = weekdays[event_day] - event.data.get_int('delta')
if event.timestamp < start_ts:
start_ts = event.timestamp
topic.add_child(Node.string('sumfrom', Time.format(start_ts, date_format)))
topic.add_child(Node.string('sumto', Time.format(end_ts, date_format)))
summary.add_child(Node.s32_array('items', weekdays))
if logtype == 'eachhour':
start_ts = Time.now()
end_ts = Time.now()
hours = [0] * 24
for event in events:
event_hour = int((event.timestamp % Time.SECONDS_IN_DAY) / Time.SECONDS_IN_HOUR)
hours[event_hour] = hours[event_hour] - event.data.get_int('delta')
if event.timestamp < start_ts:
start_ts = event.timestamp
topic.add_child(Node.string('sumfrom', Time.format(start_ts, date_format)))
topic.add_child(Node.string('sumto', Time.format(end_ts, date_format)))
summary.add_child(Node.s32_array('items', hours))
if logtype == 'detail':
history = Node.void('history')
lognode.add_child(history)
# Respect details paging
if offset is not None:
events = events[offset:]
if limit is not None:
events = events[:limit]
# Output the details themselves
for event in events:
card_no = ''
if event.userid is not None:
user = self.data.local.user.get_user(event.userid)
if user is not None:
cards = self.data.local.user.get_cards(user.id)
if len(cards) > 0:
card_no = CardCipher.encode(cards[0])
item = Node.void('item')
history.add_child(item)
item.add_child(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('service', -event.data.get_int('service')))
item.add_child(Node.string('cardtype', ''))
item.add_child(Node.string('cardno', ' ' * self.paseli_padding + card_no))
item.add_child(Node.string('title', ''))
item.add_child(Node.string('systemid', ''))
if logtype == 'lastmonths':
year, month, _ = Time.todays_date()
this_month = Time.timestamp_from_date(year, month)
last_month = Time.timestamp_from_date(year, month - 1)
month_before = Time.timestamp_from_date(year, month - 2)
topic.add_child(Node.string('sumfrom', Time.format(month_before, 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)]:
year, month, _ = Time.date_from_timestamp(start)
items = []
for day in range(0, 31):
begin_ts = start + (day * Time.SECONDS_IN_DAY)
end_ts = begin_ts + Time.SECONDS_IN_DAY
if begin_ts >= end:
# Passed the end of this month
items.append(0)
else:
# Sum up all the txns for this day
items.append(sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= begin_ts and event.timestamp < end_ts
]))
item = Node.void('item')
summary.add_child(item)
item.add_child(Node.s32('year', year))
item.add_child(Node.s32('month', month))
item.add_child(Node.s32_array('items', items))
root.add_child(Node.u8('processing', 0))
root.add_child(lognode)
return root
elif method == 'opchpass':
root = Node.void('eacoin')
oldpass = request.child_value('passwd')
newpass = request.child_value('newpasswd')
if oldpass is None or newpass is None:
# Refuse to return anything
print("Invalid eacoin pass change request, missing passwd")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if self.config.machine.arcade is None:
# Machine doesn't belong to an arcade
print("Machine doesn't belong to an arcade")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
arcade = self.data.local.machine.get_arcade(self.config.machine.arcade)
if arcade is None:
# Refuse to do anything
print("No arcade for operator pass change request")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if arcade.pin != oldpass:
# Refuse to do anything
print("User entered invalid pin for operator pass change request")
root.set_attribute('status', str(Status.INVALID_PIN))
return root
arcade.pin = newpass
self.data.local.machine.put_arcade(arcade)
return root
elif method == 'checkout':
session = request.child_value('sessid')
if session is not None:
# Destroy the session so it can't be used for any other purchases
self.data.local.user.destroy_session(session)
root = Node.void('eacoin')
return root
elif method == 'opcheckout':
session = request.child_value('sessid')
if session is not None:
# Destroy the session so it can't be used for any other purchases
self.data.local.machine.destroy_session(session)
root = Node.void('eacoin')
return root
# Invalid method
# This is fine, let the individual request handlers handle this packet.
return None
def handle_eacoin_checkin_request(self, request: Node) -> Node:
root = Node.void('eacoin')
cardid = request.child_value('cardid')
pin = request.child_value('passwd')
if cardid is None or pin is None:
# Refuse to return anything
print("Invalid eacoin checkin request, missing cardid or pin")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
userid = self.data.local.user.from_cardid(cardid)
if userid is None:
# Refuse to do anything
print("No user for eacoin checkin request")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
valid = self.data.local.user.validate_pin(userid, pin)
if not valid:
# Refuse to do anything
print("User entered invalid pin for eacoin checkin request")
root.set_attribute('status', str(Status.INVALID_PIN))
return root
session = self.data.local.user.create_session(userid)
if self.config.paseli.infinite:
balance = PASELIHandler.INFINITE_PASELI_AMOUNT
else:
if self.config.machine.arcade is None:
# There's no arcade for this machine, but infinite is not
# enabled, so there's no way to find a balance.
balance = 0
else:
balance = self.data.local.user.get_balance(userid, self.config.machine.arcade)
root.add_child(Node.s16('sequence', 0))
root.add_child(Node.u8('acstatus', 0))
root.add_child(Node.string('acid', 'DUMMY_ID'))
root.add_child(Node.string('acname', 'DUMMY_NAME'))
root.add_child(Node.s32('balance', balance))
root.add_child(Node.string('sessid', session))
return root
def handle_eacoin_opcheckin_request(self, request: Node) -> Node:
root = Node.void('eacoin')
passwd = request.child_value('passwd')
if passwd is None:
# Refuse to return anything
print("Invalid eacoin checkin request, missing passwd")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if self.config.machine.arcade is None:
# Machine doesn't belong to an arcade
print("Machine doesn't belong to an arcade")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
arcade = self.data.local.machine.get_arcade(self.config.machine.arcade)
if arcade is None:
# Refuse to do anything
print("No arcade for operator checkin request")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if arcade.pin != passwd:
# Refuse to do anything
print("User entered invalid pin for operator checkin request")
root.set_attribute('status', str(Status.INVALID_PIN))
return root
session = self.data.local.machine.create_session(arcade.id)
root.add_child(Node.string('sessid', session))
return root
def handle_eacoin_consume_request(self, request: Node) -> Node:
def make_resp(status: int, balance: int) -> Node:
root = Node.void('eacoin')
root.add_child(Node.u8('acstatus', status))
root.add_child(Node.u8('autocharge', 0))
root.add_child(Node.s32('balance', balance))
return root
session = request.child_value('sessid')
payment = request.child_value('payment')
service = request.child_value('service')
details = request.child_value('detail')
if session is None or payment is None:
# Refuse to do anything
print("Invalid eacoin consume request, missing sessid or payment")
return make_resp(2, 0)
userid = self.data.local.user.from_session(session)
if userid is None:
# Refuse to do anything
print("Invalid session for eacoin consume request")
return make_resp(2, 0)
if self.config.paseli.infinite:
balance = PASELIHandler.INFINITE_PASELI_AMOUNT - payment
else:
if self.config.machine.arcade is None:
# There's no arcade for this machine, but infinite is not
# enabled, so there's no way to find a balance, assume failed
# consume payment.
balance = None
else:
# 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.
balance = self.data.local.user.update_balance(userid, self.config.machine.arcade, -payment)
if balance is None:
print("Not enough balance for eacoin consume request")
return make_resp(1, self.data.local.user.get_balance(userid, self.config.machine.arcade))
else:
self.data.local.network.put_event(
'paseli_transaction',
{
'delta': -payment,
'balance': balance,
'service': -service,
'reason': details,
'pcbid': self.config.machine.pcbid,
},
userid=userid,
arcadeid=self.config.machine.arcade,
)
return make_resp(0, balance)
def handle_eacoin_getlog_request(self, request: Node) -> Node:
root = Node.void('eacoin')
sessid = request.child_value('sessid')
logtype = request.child_value('logtype')
target = request.child_value('target')
limit = request.child_value('perpage')
offset = request.child_value('offset')
# Try to determine whether its a user or an arcade session
userid = self.data.local.user.from_session(sessid)
if userid is None:
arcadeid = self.data.local.machine.from_session(sessid)
else:
arcadeid = None
# Bail out if we don't have any idea what session this is
if userid is None and arcadeid is None:
print("Unable to determine session type")
return root
# If we're a user session, also look up the current arcade
# so we display only entries that happened on this arcade.
if userid is not None:
arcade = self.data.local.machine.get_arcade(self.config.machine.arcade)
if arcade is None:
print("Machine doesn't belong to an arcade")
return root
arcadeid = arcade.id
# Now, look up all transactions for this specific group
events = self.data.local.network.get_events(
userid=userid,
arcadeid=arcadeid,
event='paseli_transaction',
)
# Further filter it down to the current PCBID
events = [event for event in events if event.data.get('pcbid') == target]
# Grab the end of day today as a timestamp
end_of_today = Time.end_of_today()
time_format = '%Y-%m-%d %H:%M:%S'
date_format = '%Y-%m-%d'
# Set up common structure
lognode = Node.void(logtype)
topic = Node.void('topic')
lognode.add_child(topic)
summary = Node.void('summary')
lognode.add_child(summary)
# Display what day we are summed to
topic.add_child(Node.string('sumdate', Time.format(Time.now(), date_format)))
if logtype == 'last7days':
# We show today in the today total, last 7 days prior in the week total
beginning_of_today = end_of_today - Time.SECONDS_IN_DAY
end_of_week = beginning_of_today
beginning_of_week = end_of_week - Time.SECONDS_IN_WEEK
topic.add_child(Node.string('sumfrom', Time.format(beginning_of_week, date_format)))
topic.add_child(Node.string('sumto', Time.format(end_of_week, date_format)))
today_total = sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= beginning_of_today and event.timestamp < end_of_today
])
today_total = sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= beginning_of_today and event.timestamp < end_of_today
])
week_txns = [
-event.data.get_int('delta') for event in events
if event.timestamp >= beginning_of_week and event.timestamp < end_of_week
]
week_total = sum(week_txns)
if len(week_txns) > 0:
week_avg = int(sum(week_txns) / len(week_txns))
else:
week_avg = 0
# We display the totals for each day starting with yesterday and up through 7 days prior.
# Index starts at 0 = yesterday, 1 = the day before, etc...
items = []
for days in range(0, 7):
end_of_day = end_of_week - (days * Time.SECONDS_IN_DAY)
start_of_day = end_of_day - Time.SECONDS_IN_DAY
items.append(sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= start_of_day and event.timestamp < end_of_day
]))
topic.add_child(Node.s32('today', today_total))
topic.add_child(Node.s32('average', week_avg))
topic.add_child(Node.s32('total', week_total))
summary.add_child(Node.s32_array('items', items))
if logtype == 'last52weeks':
# Start one week back, since the operator can look at last7days for newer stuff.
beginning_of_today = end_of_today - Time.SECONDS_IN_DAY
end_of_52_weeks = beginning_of_today - Time.SECONDS_IN_WEEK
topic.add_child(Node.string('sumfrom', Time.format(end_of_52_weeks - (52 * Time.SECONDS_IN_WEEK), date_format)))
topic.add_child(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...
items = []
for weeks in range(0, 52):
end_of_range = end_of_52_weeks - (weeks * Time.SECONDS_IN_WEEK)
beginning_of_range = end_of_range - Time.SECONDS_IN_WEEK
items.append(sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= beginning_of_range and event.timestamp < end_of_range
]))
summary.add_child(Node.s32_array('items', items))
if logtype == 'eachday':
start_ts = Time.now()
end_ts = Time.now()
weekdays = [0] * 7
for event in events:
event_day = Time.days_into_week(event.timestamp)
weekdays[event_day] = weekdays[event_day] - event.data.get_int('delta')
if event.timestamp < start_ts:
start_ts = event.timestamp
topic.add_child(Node.string('sumfrom', Time.format(start_ts, date_format)))
topic.add_child(Node.string('sumto', Time.format(end_ts, date_format)))
summary.add_child(Node.s32_array('items', weekdays))
if logtype == 'eachhour':
start_ts = Time.now()
end_ts = Time.now()
hours = [0] * 24
for event in events:
event_hour = int((event.timestamp % Time.SECONDS_IN_DAY) / Time.SECONDS_IN_HOUR)
hours[event_hour] = hours[event_hour] - event.data.get_int('delta')
if event.timestamp < start_ts:
start_ts = event.timestamp
topic.add_child(Node.string('sumfrom', Time.format(start_ts, date_format)))
topic.add_child(Node.string('sumto', Time.format(end_ts, date_format)))
summary.add_child(Node.s32_array('items', hours))
if logtype == 'detail':
history = Node.void('history')
lognode.add_child(history)
# Respect details paging
if offset is not None:
events = events[offset:]
if limit is not None:
events = events[:limit]
# Output the details themselves
for event in events:
card_no = ''
if event.userid is not None:
user = self.data.local.user.get_user(event.userid)
if user is not None:
cards = self.data.local.user.get_cards(user.id)
if len(cards) > 0:
card_no = CardCipher.encode(cards[0])
item = Node.void('item')
history.add_child(item)
item.add_child(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('service', -event.data.get_int('service')))
item.add_child(Node.string('cardtype', ''))
item.add_child(Node.string('cardno', ' ' * self.paseli_padding + card_no))
item.add_child(Node.string('title', ''))
item.add_child(Node.string('systemid', ''))
if logtype == 'lastmonths':
year, month, _ = Time.todays_date()
this_month = Time.timestamp_from_date(year, month)
last_month = Time.timestamp_from_date(year, month - 1)
month_before = Time.timestamp_from_date(year, month - 2)
topic.add_child(Node.string('sumfrom', Time.format(month_before, 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)]:
year, month, _ = Time.date_from_timestamp(start)
items = []
for day in range(0, 31):
begin_ts = start + (day * Time.SECONDS_IN_DAY)
end_ts = begin_ts + Time.SECONDS_IN_DAY
if begin_ts >= end:
# Passed the end of this month
items.append(0)
else:
# Sum up all the txns for this day
items.append(sum([
-event.data.get_int('delta') for event in events
if event.timestamp >= begin_ts and event.timestamp < end_ts
]))
item = Node.void('item')
summary.add_child(item)
item.add_child(Node.s32('year', year))
item.add_child(Node.s32('month', month))
item.add_child(Node.s32_array('items', items))
root.add_child(Node.u8('processing', 0))
root.add_child(lognode)
return root
def handle_eacoin_opchpass_request(self, request: Node) -> Node:
root = Node.void('eacoin')
oldpass = request.child_value('passwd')
newpass = request.child_value('newpasswd')
if oldpass is None or newpass is None:
# Refuse to return anything
print("Invalid eacoin pass change request, missing passwd")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if self.config.machine.arcade is None:
# Machine doesn't belong to an arcade
print("Machine doesn't belong to an arcade")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
arcade = self.data.local.machine.get_arcade(self.config.machine.arcade)
if arcade is None:
# Refuse to do anything
print("No arcade for operator pass change request")
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if arcade.pin != oldpass:
# Refuse to do anything
print("User entered invalid pin for operator pass change request")
root.set_attribute('status', str(Status.INVALID_PIN))
return root
arcade.pin = newpass
self.data.local.machine.put_arcade(arcade)
return root
def handle_eacoin_checkout_request(self, request: Node) -> Node:
session = request.child_value('sessid')
if session is not None:
# Destroy the session so it can't be used for any other purchases
self.data.local.user.destroy_session(session)
root = Node.void('eacoin')
return root
def handle_eacoin_opcheckout_request(self, request: Node) -> Node:
session = request.child_value('sessid')
if session is not None:
# Destroy the session so it can't be used for any other purchases
self.data.local.machine.destroy_session(session)
root = Node.void('eacoin')
return root

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Optional, List
from typing_extensions import Final
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
@ -14,42 +15,42 @@ class DDRBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
profiles based on refid, creating new profiles, looking up and saving scores.
"""
game = GameConstants.DDR
game: GameConstants = GameConstants.DDR
HALO_NONE = DBConstants.DDR_HALO_NONE
HALO_GOOD_FULL_COMBO = DBConstants.DDR_HALO_GOOD_FULL_COMBO
HALO_GREAT_FULL_COMBO = DBConstants.DDR_HALO_GREAT_FULL_COMBO
HALO_PERFECT_FULL_COMBO = DBConstants.DDR_HALO_PERFECT_FULL_COMBO
HALO_MARVELOUS_FULL_COMBO = DBConstants.DDR_HALO_MARVELOUS_FULL_COMBO
HALO_NONE: Final[int] = DBConstants.DDR_HALO_NONE
HALO_GOOD_FULL_COMBO: Final[int] = DBConstants.DDR_HALO_GOOD_FULL_COMBO
HALO_GREAT_FULL_COMBO: Final[int] = DBConstants.DDR_HALO_GREAT_FULL_COMBO
HALO_PERFECT_FULL_COMBO: Final[int] = DBConstants.DDR_HALO_PERFECT_FULL_COMBO
HALO_MARVELOUS_FULL_COMBO: Final[int] = DBConstants.DDR_HALO_MARVELOUS_FULL_COMBO
RANK_E = DBConstants.DDR_RANK_E
RANK_D = DBConstants.DDR_RANK_D
RANK_D_PLUS = DBConstants.DDR_RANK_D_PLUS
RANK_C_MINUS = DBConstants.DDR_RANK_C_MINUS
RANK_C = DBConstants.DDR_RANK_C
RANK_C_PLUS = DBConstants.DDR_RANK_C_PLUS
RANK_B_MINUS = DBConstants.DDR_RANK_B_MINUS
RANK_B = DBConstants.DDR_RANK_B
RANK_B_PLUS = DBConstants.DDR_RANK_B_PLUS
RANK_A_MINUS = DBConstants.DDR_RANK_A_MINUS
RANK_A = DBConstants.DDR_RANK_A
RANK_A_PLUS = DBConstants.DDR_RANK_A_PLUS
RANK_AA_MINUS = DBConstants.DDR_RANK_AA_MINUS
RANK_AA = DBConstants.DDR_RANK_AA
RANK_AA_PLUS = DBConstants.DDR_RANK_AA_PLUS
RANK_AAA = DBConstants.DDR_RANK_AAA
RANK_E: Final[int] = DBConstants.DDR_RANK_E
RANK_D: Final[int] = DBConstants.DDR_RANK_D
RANK_D_PLUS: Final[int] = DBConstants.DDR_RANK_D_PLUS
RANK_C_MINUS: Final[int] = DBConstants.DDR_RANK_C_MINUS
RANK_C: Final[int] = DBConstants.DDR_RANK_C
RANK_C_PLUS: Final[int] = DBConstants.DDR_RANK_C_PLUS
RANK_B_MINUS: Final[int] = DBConstants.DDR_RANK_B_MINUS
RANK_B: Final[int] = DBConstants.DDR_RANK_B
RANK_B_PLUS: Final[int] = DBConstants.DDR_RANK_B_PLUS
RANK_A_MINUS: Final[int] = DBConstants.DDR_RANK_A_MINUS
RANK_A: Final[int] = DBConstants.DDR_RANK_A
RANK_A_PLUS: Final[int] = DBConstants.DDR_RANK_A_PLUS
RANK_AA_MINUS: Final[int] = DBConstants.DDR_RANK_AA_MINUS
RANK_AA: Final[int] = DBConstants.DDR_RANK_AA
RANK_AA_PLUS: Final[int] = DBConstants.DDR_RANK_AA_PLUS
RANK_AAA: Final[int] = DBConstants.DDR_RANK_AAA
# These constants must agree with read.py for importing charts from the game.
CHART_SINGLE_BEGINNER = 0
CHART_SINGLE_BASIC = 1
CHART_SINGLE_DIFFICULT = 2
CHART_SINGLE_EXPERT = 3
CHART_SINGLE_CHALLENGE = 4
CHART_DOUBLE_BEGINNER = 5
CHART_DOUBLE_BASIC = 6
CHART_DOUBLE_DIFFICULT = 7
CHART_DOUBLE_EXPERT = 8
CHART_DOUBLE_CHALLENGE = 9
CHART_SINGLE_BEGINNER: Final[int] = 0
CHART_SINGLE_BASIC: Final[int] = 1
CHART_SINGLE_DIFFICULT: Final[int] = 2
CHART_SINGLE_EXPERT: Final[int] = 3
CHART_SINGLE_CHALLENGE: Final[int] = 4
CHART_DOUBLE_BEGINNER: Final[int] = 5
CHART_DOUBLE_BASIC: Final[int] = 6
CHART_DOUBLE_DIFFICULT: Final[int] = 7
CHART_DOUBLE_EXPERT: Final[int] = 8
CHART_DOUBLE_CHALLENGE: Final[int] = 9
# Return the local2 service so that DDR Ace will send certain packets.
extra_services: List[str] = [

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Dict, List, Optional
from typing_extensions import Final
from bemani.backend.ddr.base import DDRBase
from bemani.backend.ddr.ddrx3 import DDRX3
@ -53,38 +53,38 @@ class DDR2013(
DDRBase,
):
name = 'DanceDanceRevolution 2013'
version = VersionConstants.DDR_2013
name: str = 'DanceDanceRevolution 2013'
version: int = VersionConstants.DDR_2013
GAME_STYLE_SINGLE = 0
GAME_STYLE_DOUBLE = 1
GAME_STYLE_VERSUS = 2
GAME_STYLE_SINGLE: Final[int] = 0
GAME_STYLE_DOUBLE: Final[int] = 1
GAME_STYLE_VERSUS: Final[int] = 2
GAME_RANK_AAA = 1
GAME_RANK_AA = 2
GAME_RANK_A = 3
GAME_RANK_B = 4
GAME_RANK_C = 5
GAME_RANK_D = 6
GAME_RANK_E = 7
GAME_RANK_AAA: Final[int] = 1
GAME_RANK_AA: Final[int] = 2
GAME_RANK_A: Final[int] = 3
GAME_RANK_B: Final[int] = 4
GAME_RANK_C: Final[int] = 5
GAME_RANK_D: Final[int] = 6
GAME_RANK_E: Final[int] = 7
GAME_CHART_SINGLE_BEGINNER = 0
GAME_CHART_SINGLE_BASIC = 1
GAME_CHART_SINGLE_DIFFICULT = 2
GAME_CHART_SINGLE_EXPERT = 3
GAME_CHART_SINGLE_CHALLENGE = 4
GAME_CHART_DOUBLE_BASIC = 5
GAME_CHART_DOUBLE_DIFFICULT = 6
GAME_CHART_DOUBLE_EXPERT = 7
GAME_CHART_DOUBLE_CHALLENGE = 8
GAME_CHART_SINGLE_BEGINNER: Final[int] = 0
GAME_CHART_SINGLE_BASIC: Final[int] = 1
GAME_CHART_SINGLE_DIFFICULT: Final[int] = 2
GAME_CHART_SINGLE_EXPERT: Final[int] = 3
GAME_CHART_SINGLE_CHALLENGE: Final[int] = 4
GAME_CHART_DOUBLE_BASIC: Final[int] = 5
GAME_CHART_DOUBLE_DIFFICULT: Final[int] = 6
GAME_CHART_DOUBLE_EXPERT: Final[int] = 7
GAME_CHART_DOUBLE_CHALLENGE: Final[int] = 8
GAME_HALO_NONE = 0
GAME_HALO_GREAT_COMBO = 1
GAME_HALO_PERFECT_COMBO = 2
GAME_HALO_MARVELOUS_COMBO = 3
GAME_HALO_GOOD_COMBO = 4
GAME_HALO_NONE: Final[int] = 0
GAME_HALO_GREAT_COMBO: Final[int] = 1
GAME_HALO_PERFECT_COMBO: Final[int] = 2
GAME_HALO_MARVELOUS_COMBO: Final[int] = 3
GAME_HALO_GOOD_COMBO: Final[int] = 4
GAME_MAX_SONGS = 700
GAME_MAX_SONGS: Final[int] = 700
def previous_version(self) -> Optional[DDRBase]:
return DDRX3(self.data, self.config, self.model)
@ -468,7 +468,7 @@ class DDR2013(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Grab last node and accessories so we can make decisions based on type

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Dict, List, Optional
from typing_extensions import Final
from bemani.backend.ddr.base import DDRBase
from bemani.backend.ddr.ddr2013 import DDR2013
@ -47,38 +47,38 @@ class DDR2014(
DDRBase,
):
name = 'DanceDanceRevolution 2014'
version = VersionConstants.DDR_2014
name: str = 'DanceDanceRevolution 2014'
version: int = VersionConstants.DDR_2014
GAME_STYLE_SINGLE = 0
GAME_STYLE_DOUBLE = 1
GAME_STYLE_VERSUS = 2
GAME_STYLE_SINGLE: Final[int] = 0
GAME_STYLE_DOUBLE: Final[int] = 1
GAME_STYLE_VERSUS: Final[int] = 2
GAME_RANK_AAA = 1
GAME_RANK_AA = 2
GAME_RANK_A = 3
GAME_RANK_B = 4
GAME_RANK_C = 5
GAME_RANK_D = 6
GAME_RANK_E = 7
GAME_RANK_AAA: Final[int] = 1
GAME_RANK_AA: Final[int] = 2
GAME_RANK_A: Final[int] = 3
GAME_RANK_B: Final[int] = 4
GAME_RANK_C: Final[int] = 5
GAME_RANK_D: Final[int] = 6
GAME_RANK_E: Final[int] = 7
GAME_CHART_SINGLE_BEGINNER = 0
GAME_CHART_SINGLE_BASIC = 1
GAME_CHART_SINGLE_DIFFICULT = 2
GAME_CHART_SINGLE_EXPERT = 3
GAME_CHART_SINGLE_CHALLENGE = 4
GAME_CHART_DOUBLE_BASIC = 5
GAME_CHART_DOUBLE_DIFFICULT = 6
GAME_CHART_DOUBLE_EXPERT = 7
GAME_CHART_DOUBLE_CHALLENGE = 8
GAME_CHART_SINGLE_BEGINNER: Final[int] = 0
GAME_CHART_SINGLE_BASIC: Final[int] = 1
GAME_CHART_SINGLE_DIFFICULT: Final[int] = 2
GAME_CHART_SINGLE_EXPERT: Final[int] = 3
GAME_CHART_SINGLE_CHALLENGE: Final[int] = 4
GAME_CHART_DOUBLE_BASIC: Final[int] = 5
GAME_CHART_DOUBLE_DIFFICULT: Final[int] = 6
GAME_CHART_DOUBLE_EXPERT: Final[int] = 7
GAME_CHART_DOUBLE_CHALLENGE: Final[int] = 8
GAME_HALO_NONE = 0
GAME_HALO_GREAT_COMBO = 1
GAME_HALO_PERFECT_COMBO = 2
GAME_HALO_MARVELOUS_COMBO = 3
GAME_HALO_GOOD_COMBO = 4
GAME_HALO_NONE: Final[int] = 0
GAME_HALO_GREAT_COMBO: Final[int] = 1
GAME_HALO_PERFECT_COMBO: Final[int] = 2
GAME_HALO_MARVELOUS_COMBO: Final[int] = 3
GAME_HALO_GOOD_COMBO: Final[int] = 4
GAME_MAX_SONGS = 800
GAME_MAX_SONGS: Final[int] = 800
def previous_version(self) -> Optional[DDRBase]:
return DDR2013(self.data, self.config, self.model)
@ -529,7 +529,7 @@ class DDR2014(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Grab last node and accessories so we can make decisions based on type

View File

@ -10,8 +10,8 @@ class DDRA20(
DDRBase,
):
name = 'DanceDanceRevolution A20'
version = VersionConstants.DDR_A20
name: str = 'DanceDanceRevolution A20'
version: int = VersionConstants.DDR_A20
def previous_version(self) -> Optional[DDRBase]:
return DDRAce(self.data, self.config, self.model)

View File

@ -1,6 +1,7 @@
# vim: set fileencoding=utf-8
import base64
from typing import Dict, List, Optional
from typing_extensions import Final
from bemani.backend.ess import EventLogHandler
from bemani.backend.ddr.base import DDRBase
@ -15,91 +16,91 @@ class DDRAce(
EventLogHandler,
):
name = 'DanceDanceRevolution A'
version = VersionConstants.DDR_ACE
name: str = 'DanceDanceRevolution A'
version: int = VersionConstants.DDR_ACE
GAME_STYLE_SINGLE = 0
GAME_STYLE_DOUBLE = 1
GAME_STYLE_VERSUS = 2
GAME_STYLE_SINGLE: Final[int] = 0
GAME_STYLE_DOUBLE: Final[int] = 1
GAME_STYLE_VERSUS: Final[int] = 2
GAME_RIVAL_TYPE_RIVAL3 = 32
GAME_RIVAL_TYPE_RIVAL2 = 16
GAME_RIVAL_TYPE_RIVAL1 = 8
GAME_RIVAL_TYPE_WORLD = 4
GAME_RIVAL_TYPE_AREA = 2
GAME_RIVAL_TYPE_MACHINE = 1
GAME_RIVAL_TYPE_RIVAL3: Final[int] = 32
GAME_RIVAL_TYPE_RIVAL2: Final[int] = 16
GAME_RIVAL_TYPE_RIVAL1: Final[int] = 8
GAME_RIVAL_TYPE_WORLD: Final[int] = 4
GAME_RIVAL_TYPE_AREA: Final[int] = 2
GAME_RIVAL_TYPE_MACHINE: Final[int] = 1
GAME_CHART_SINGLE_BEGINNER = 0
GAME_CHART_SINGLE_BASIC = 1
GAME_CHART_SINGLE_DIFFICULT = 2
GAME_CHART_SINGLE_EXPERT = 3
GAME_CHART_SINGLE_CHALLENGE = 4
GAME_CHART_DOUBLE_BASIC = 5
GAME_CHART_DOUBLE_DIFFICULT = 6
GAME_CHART_DOUBLE_EXPERT = 7
GAME_CHART_DOUBLE_CHALLENGE = 8
GAME_CHART_SINGLE_BEGINNER: Final[int] = 0
GAME_CHART_SINGLE_BASIC: Final[int] = 1
GAME_CHART_SINGLE_DIFFICULT: Final[int] = 2
GAME_CHART_SINGLE_EXPERT: Final[int] = 3
GAME_CHART_SINGLE_CHALLENGE: Final[int] = 4
GAME_CHART_DOUBLE_BASIC: Final[int] = 5
GAME_CHART_DOUBLE_DIFFICULT: Final[int] = 6
GAME_CHART_DOUBLE_EXPERT: Final[int] = 7
GAME_CHART_DOUBLE_CHALLENGE: Final[int] = 8
GAME_HALO_NONE = 6
GAME_HALO_GOOD_COMBO = 7
GAME_HALO_GREAT_COMBO = 8
GAME_HALO_PERFECT_COMBO = 9
GAME_HALO_MARVELOUS_COMBO = 10
GAME_HALO_NONE: Final[int] = 6
GAME_HALO_GOOD_COMBO: Final[int] = 7
GAME_HALO_GREAT_COMBO: Final[int] = 8
GAME_HALO_PERFECT_COMBO: Final[int] = 9
GAME_HALO_MARVELOUS_COMBO: Final[int] = 10
GAME_RANK_E = 15
GAME_RANK_D = 14
GAME_RANK_D_PLUS = 13
GAME_RANK_C_MINUS = 12
GAME_RANK_C = 11
GAME_RANK_C_PLUS = 10
GAME_RANK_B_MINUS = 9
GAME_RANK_B = 8
GAME_RANK_B_PLUS = 7
GAME_RANK_A_MINUS = 6
GAME_RANK_A = 5
GAME_RANK_A_PLUS = 4
GAME_RANK_AA_MINUS = 3
GAME_RANK_AA = 2
GAME_RANK_AA_PLUS = 1
GAME_RANK_AAA = 0
GAME_RANK_E: Final[int] = 15
GAME_RANK_D: Final[int] = 14
GAME_RANK_D_PLUS: Final[int] = 13
GAME_RANK_C_MINUS: Final[int] = 12
GAME_RANK_C: Final[int] = 11
GAME_RANK_C_PLUS: Final[int] = 10
GAME_RANK_B_MINUS: Final[int] = 9
GAME_RANK_B: Final[int] = 8
GAME_RANK_B_PLUS: Final[int] = 7
GAME_RANK_A_MINUS: Final[int] = 6
GAME_RANK_A: Final[int] = 5
GAME_RANK_A_PLUS: Final[int] = 4
GAME_RANK_AA_MINUS: Final[int] = 3
GAME_RANK_AA: Final[int] = 2
GAME_RANK_AA_PLUS: Final[int] = 1
GAME_RANK_AAA: Final[int] = 0
GAME_MAX_SONGS = 1024
GAME_MAX_SONGS: Final[int] = 1024
GAME_COMMON_AREA_OFFSET = 1
GAME_COMMON_WEIGHT_DISPLAY_OFFSET = 3
GAME_COMMON_CHARACTER_OFFSET = 4
GAME_COMMON_EXTRA_CHARGE_OFFSET = 5
GAME_COMMON_TOTAL_PLAYS_OFFSET = 9
GAME_COMMON_SINGLE_PLAYS_OFFSET = 11
GAME_COMMON_DOUBLE_PLAYS_OFFSET = 12
GAME_COMMON_WEIGHT_OFFSET = 17
GAME_COMMON_NAME_OFFSET = 25
GAME_COMMON_SEQ_OFFSET = 26
GAME_COMMON_AREA_OFFSET: Final[int] = 1
GAME_COMMON_WEIGHT_DISPLAY_OFFSET: Final[int] = 3
GAME_COMMON_CHARACTER_OFFSET: Final[int] = 4
GAME_COMMON_EXTRA_CHARGE_OFFSET: Final[int] = 5
GAME_COMMON_TOTAL_PLAYS_OFFSET: Final[int] = 9
GAME_COMMON_SINGLE_PLAYS_OFFSET: Final[int] = 11
GAME_COMMON_DOUBLE_PLAYS_OFFSET: Final[int] = 12
GAME_COMMON_WEIGHT_OFFSET: Final[int] = 17
GAME_COMMON_NAME_OFFSET: Final[int] = 25
GAME_COMMON_SEQ_OFFSET: Final[int] = 26
GAME_OPTION_SCROLL_OFFSET = 1
GAME_OPTION_BOOST_OFFSET = 2
GAME_OPTION_APPEARANCE_OFFSET = 3
GAME_OPTION_TURN_OFFSET = 4
GAME_OPTION_STEP_ZONE_OFFSET = 5
GAME_OPTION_SCROLL_OFFSET = 6
GAME_OPTION_ARROW_COLOR_OFFSET = 7
GAME_OPTION_CUT_OFFSET = 8
GAME_OPTION_FREEZE_OFFSET = 9
GAME_OPTION_JUMPS_OFFSET = 10
GAME_OPTION_ARROW_SKIN_OFFSET = 11
GAME_OPTION_FILTER_OFFSET = 12
GAME_OPTION_GUIDELINE_OFFSET = 13
GAME_OPTION_GAUGE_OFFSET = 14
GAME_OPTION_COMBO_POSITION_OFFSET = 15
GAME_OPTION_FAST_SLOW_OFFSET = 16
GAME_OPTION_SPEED_OFFSET: Final[int] = 1
GAME_OPTION_BOOST_OFFSET: Final[int] = 2
GAME_OPTION_APPEARANCE_OFFSET: Final[int] = 3
GAME_OPTION_TURN_OFFSET: Final[int] = 4
GAME_OPTION_STEP_ZONE_OFFSET: Final[int] = 5
GAME_OPTION_SCROLL_OFFSET: Final[int] = 6
GAME_OPTION_ARROW_COLOR_OFFSET: Final[int] = 7
GAME_OPTION_CUT_OFFSET: Final[int] = 8
GAME_OPTION_FREEZE_OFFSET: Final[int] = 9
GAME_OPTION_JUMPS_OFFSET: Final[int] = 10
GAME_OPTION_ARROW_SKIN_OFFSET: Final[int] = 11
GAME_OPTION_FILTER_OFFSET: Final[int] = 12
GAME_OPTION_GUIDELINE_OFFSET: Final[int] = 13
GAME_OPTION_GAUGE_OFFSET: Final[int] = 14
GAME_OPTION_COMBO_POSITION_OFFSET: Final[int] = 15
GAME_OPTION_FAST_SLOW_OFFSET: Final[int] = 16
GAME_LAST_CALORIES_OFFSET = 10
GAME_LAST_CALORIES_OFFSET: Final[int] = 10
GAME_RIVAL_SLOT_1_ACTIVE_OFFSET = 1
GAME_RIVAL_SLOT_2_ACTIVE_OFFSET = 2
GAME_RIVAL_SLOT_3_ACTIVE_OFFSET = 3
GAME_RIVAL_SLOT_1_DDRCODE_OFFSET = 9
GAME_RIVAL_SLOT_2_DDRCODE_OFFSET = 10
GAME_RIVAL_SLOT_3_DDRCODE_OFFSET = 11
GAME_RIVAL_SLOT_1_ACTIVE_OFFSET: Final[int] = 1
GAME_RIVAL_SLOT_2_ACTIVE_OFFSET: Final[int] = 2
GAME_RIVAL_SLOT_3_ACTIVE_OFFSET: Final[int] = 3
GAME_RIVAL_SLOT_1_DDRCODE_OFFSET: Final[int] = 9
GAME_RIVAL_SLOT_2_DDRCODE_OFFSET: Final[int] = 10
GAME_RIVAL_SLOT_3_DDRCODE_OFFSET: Final[int] = 11
def previous_version(self) -> Optional[DDRBase]:
return DDR2014(self.data, self.config, self.model)

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Dict, List, Optional, Tuple
from typing_extensions import Final
from bemani.backend.ddr.base import DDRBase
from bemani.backend.ddr.stubs import DDRX
@ -43,37 +43,37 @@ class DDRX2(
DDRBase,
):
name = 'DanceDanceRevolution X2'
version = VersionConstants.DDR_X2
name: str = 'DanceDanceRevolution X2'
version: int = VersionConstants.DDR_X2
GAME_STYLE_SINGLE = 0
GAME_STYLE_DOUBLE = 1
GAME_STYLE_VERSUS = 2
GAME_STYLE_SINGLE: Final[int] = 0
GAME_STYLE_DOUBLE: Final[int] = 1
GAME_STYLE_VERSUS: Final[int] = 2
GAME_RANK_AAA = 1
GAME_RANK_AA = 2
GAME_RANK_A = 3
GAME_RANK_B = 4
GAME_RANK_C = 5
GAME_RANK_D = 6
GAME_RANK_E = 7
GAME_RANK_AAA: Final[int] = 1
GAME_RANK_AA: Final[int] = 2
GAME_RANK_A: Final[int] = 3
GAME_RANK_B: Final[int] = 4
GAME_RANK_C: Final[int] = 5
GAME_RANK_D: Final[int] = 6
GAME_RANK_E: Final[int] = 7
GAME_CHART_SINGLE_BEGINNER = 0
GAME_CHART_SINGLE_BASIC = 1
GAME_CHART_SINGLE_DIFFICULT = 2
GAME_CHART_SINGLE_EXPERT = 3
GAME_CHART_SINGLE_CHALLENGE = 4
GAME_CHART_DOUBLE_BASIC = 5
GAME_CHART_DOUBLE_DIFFICULT = 6
GAME_CHART_DOUBLE_EXPERT = 7
GAME_CHART_DOUBLE_CHALLENGE = 8
GAME_CHART_SINGLE_BEGINNER: Final[int] = 0
GAME_CHART_SINGLE_BASIC: Final[int] = 1
GAME_CHART_SINGLE_DIFFICULT: Final[int] = 2
GAME_CHART_SINGLE_EXPERT: Final[int] = 3
GAME_CHART_SINGLE_CHALLENGE: Final[int] = 4
GAME_CHART_DOUBLE_BASIC: Final[int] = 5
GAME_CHART_DOUBLE_DIFFICULT: Final[int] = 6
GAME_CHART_DOUBLE_EXPERT: Final[int] = 7
GAME_CHART_DOUBLE_CHALLENGE: Final[int] = 8
GAME_HALO_NONE = 0
GAME_HALO_FULL_COMBO = 1
GAME_HALO_PERFECT_COMBO = 2
GAME_HALO_MARVELOUS_COMBO = 3
GAME_HALO_NONE: Final[int] = 0
GAME_HALO_FULL_COMBO: Final[int] = 1
GAME_HALO_PERFECT_COMBO: Final[int] = 2
GAME_HALO_MARVELOUS_COMBO: Final[int] = 3
GAME_MAX_SONGS = 600
GAME_MAX_SONGS: Final[int] = 600
def previous_version(self) -> Optional[DDRBase]:
return DDRX(self.data, self.config, self.model)
@ -517,7 +517,7 @@ class DDRX2(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Grab last node and accessories so we can make decisions based on type

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Dict, List, Optional, Union
from typing_extensions import Final
from bemani.backend.ddr.base import DDRBase
from bemani.backend.ddr.ddrx2 import DDRX2
@ -49,40 +49,40 @@ class DDRX3(
DDRBase,
):
name = 'DanceDanceRevolution X3 VS 2ndMIX'
version = VersionConstants.DDR_X3_VS_2NDMIX
name: str = 'DanceDanceRevolution X3 VS 2ndMIX'
version: int = VersionConstants.DDR_X3_VS_2NDMIX
GAME_STYLE_SINGLE = 0
GAME_STYLE_DOUBLE = 1
GAME_STYLE_VERSUS = 2
GAME_STYLE_SINGLE: Final[int] = 0
GAME_STYLE_DOUBLE: Final[int] = 1
GAME_STYLE_VERSUS: Final[int] = 2
GAME_RANK_AAA = 1
GAME_RANK_AA = 2
GAME_RANK_A = 3
GAME_RANK_B = 4
GAME_RANK_C = 5
GAME_RANK_D = 6
GAME_RANK_E = 7
GAME_RANK_AAA: Final[int] = 1
GAME_RANK_AA: Final[int] = 2
GAME_RANK_A: Final[int] = 3
GAME_RANK_B: Final[int] = 4
GAME_RANK_C: Final[int] = 5
GAME_RANK_D: Final[int] = 6
GAME_RANK_E: Final[int] = 7
GAME_CHART_SINGLE_BEGINNER = 0
GAME_CHART_SINGLE_BASIC = 1
GAME_CHART_SINGLE_DIFFICULT = 2
GAME_CHART_SINGLE_EXPERT = 3
GAME_CHART_SINGLE_CHALLENGE = 4
GAME_CHART_DOUBLE_BASIC = 5
GAME_CHART_DOUBLE_DIFFICULT = 6
GAME_CHART_DOUBLE_EXPERT = 7
GAME_CHART_DOUBLE_CHALLENGE = 8
GAME_CHART_SINGLE_BEGINNER: Final[int] = 0
GAME_CHART_SINGLE_BASIC: Final[int] = 1
GAME_CHART_SINGLE_DIFFICULT: Final[int] = 2
GAME_CHART_SINGLE_EXPERT: Final[int] = 3
GAME_CHART_SINGLE_CHALLENGE: Final[int] = 4
GAME_CHART_DOUBLE_BASIC: Final[int] = 5
GAME_CHART_DOUBLE_DIFFICULT: Final[int] = 6
GAME_CHART_DOUBLE_EXPERT: Final[int] = 7
GAME_CHART_DOUBLE_CHALLENGE: Final[int] = 8
GAME_HALO_NONE = 0
GAME_HALO_FULL_COMBO = 1
GAME_HALO_PERFECT_COMBO = 2
GAME_HALO_MARVELOUS_COMBO = 3
GAME_HALO_NONE: Final[int] = 0
GAME_HALO_FULL_COMBO: Final[int] = 1
GAME_HALO_PERFECT_COMBO: Final[int] = 2
GAME_HALO_MARVELOUS_COMBO: Final[int] = 3
GAME_PLAY_MODE_NORMAL = 1
GAME_PLAY_MODE_2NDMIX = 5
GAME_PLAY_MODE_NORMAL: Final[int] = 1
GAME_PLAY_MODE_2NDMIX: Final[int] = 5
GAME_MAX_SONGS = 700
GAME_MAX_SONGS: Final[int] = 700
def previous_version(self) -> Optional[DDRBase]:
return DDRX2(self.data, self.config, self.model)
@ -543,7 +543,7 @@ class DDRX3(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Grab last node and accessories so we can make decisions based on type

View File

@ -1,4 +1,4 @@
from typing import Optional
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.ddr.stubs import (
@ -26,7 +26,7 @@ from bemani.data import Config, Data
class DDRFactory(Factory):
MANAGED_CLASSES = [
MANAGED_CLASSES: List[Type[Base]] = [
DDR1stMix,
DDR2ndMix,
DDR4thMix,

View File

@ -7,8 +7,8 @@ from bemani.common import VersionConstants
class DDRX(DDRBase):
name = 'DanceDanceRevolution X'
version = VersionConstants.DDR_X
name: str = 'DanceDanceRevolution X'
version: int = VersionConstants.DDR_X
def previous_version(self) -> Optional[DDRBase]:
return DDRSuperNova2(self.data, self.config, self.model)
@ -16,8 +16,8 @@ class DDRX(DDRBase):
class DDRSuperNova2(DDRBase):
name = 'DanceDanceRevolution SuperNova 2'
version = VersionConstants.DDR_SUPERNOVA_2
name: str = 'DanceDanceRevolution SuperNova 2'
version: int = VersionConstants.DDR_SUPERNOVA_2
def previous_version(self) -> Optional[DDRBase]:
return DDRSuperNova(self.data, self.config, self.model)
@ -25,8 +25,8 @@ class DDRSuperNova2(DDRBase):
class DDRSuperNova(DDRBase):
name = 'DanceDanceRevolution SuperNova'
version = VersionConstants.DDR_SUPERNOVA
name: str = 'DanceDanceRevolution SuperNova'
version: int = VersionConstants.DDR_SUPERNOVA
def previous_version(self) -> Optional[DDRBase]:
return DDRExtreme(self.data, self.config, self.model)
@ -34,8 +34,8 @@ class DDRSuperNova(DDRBase):
class DDRExtreme(DDRBase):
name = 'DanceDanceRevolution Extreme'
version = VersionConstants.DDR_EXTREME
name: str = 'DanceDanceRevolution Extreme'
version: int = VersionConstants.DDR_EXTREME
def previous_version(self) -> Optional[DDRBase]:
return DDR7thMix(self.data, self.config, self.model)
@ -43,8 +43,8 @@ class DDRExtreme(DDRBase):
class DDR7thMix(DDRBase):
name = 'DanceDanceRevolution 7thMix'
version = VersionConstants.DDR_7THMIX
name: str = 'DanceDanceRevolution 7thMix'
version: int = VersionConstants.DDR_7THMIX
def previous_version(self) -> Optional[DDRBase]:
return DDR6thMix(self.data, self.config, self.model)
@ -52,8 +52,8 @@ class DDR7thMix(DDRBase):
class DDR6thMix(DDRBase):
name = 'DanceDanceRevolution 6thMix'
version = VersionConstants.DDR_6THMIX
name: str = 'DanceDanceRevolution 6thMix'
version: int = VersionConstants.DDR_6THMIX
def previous_version(self) -> Optional[DDRBase]:
return DDR5thMix(self.data, self.config, self.model)
@ -61,8 +61,8 @@ class DDR6thMix(DDRBase):
class DDR5thMix(DDRBase):
name = 'DanceDanceRevolution 5thMix'
version = VersionConstants.DDR_5THMIX
name: str = 'DanceDanceRevolution 5thMix'
version: int = VersionConstants.DDR_5THMIX
def previous_version(self) -> Optional[DDRBase]:
return DDR4thMix(self.data, self.config, self.model)
@ -70,8 +70,8 @@ class DDR5thMix(DDRBase):
class DDR4thMix(DDRBase):
name = 'DanceDanceRevolution 4thMix'
version = VersionConstants.DDR_4THMIX
name: str = 'DanceDanceRevolution 4thMix'
version: int = VersionConstants.DDR_4THMIX
def previous_version(self) -> Optional[DDRBase]:
return DDR3rdMix(self.data, self.config, self.model)
@ -79,8 +79,8 @@ class DDR4thMix(DDRBase):
class DDR3rdMix(DDRBase):
name = 'DanceDanceRevolution 3rdMix'
version = VersionConstants.DDR_3RDMIX
name: str = 'DanceDanceRevolution 3rdMix'
version: int = VersionConstants.DDR_3RDMIX
def previous_version(self) -> Optional[DDRBase]:
return DDR2ndMix(self.data, self.config, self.model)
@ -88,8 +88,8 @@ class DDR3rdMix(DDRBase):
class DDR2ndMix(DDRBase):
name = 'DanceDanceRevolution 2ndMix'
version = VersionConstants.DDR_2NDMIX
name: str = 'DanceDanceRevolution 2ndMix'
version: int = VersionConstants.DDR_2NDMIX
def previous_version(self) -> Optional[DDRBase]:
return DDR1stMix(self.data, self.config, self.model)
@ -97,5 +97,5 @@ class DDR2ndMix(DDRBase):
class DDR1stMix(DDRBase):
name = 'DanceDanceRevolution 1stMix'
version = VersionConstants.DDR_1STMIX
name: str = 'DanceDanceRevolution 1stMix'
version: int = VersionConstants.DDR_1STMIX

View File

@ -1,6 +1,7 @@
# vim: set fileencoding=utf-8
import struct
from typing import Optional, Dict, Any, List, Tuple
from typing_extensions import Final
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
@ -16,64 +17,64 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
scores.
"""
game = GameConstants.IIDX
game: GameConstants = GameConstants.IIDX
paseli_padding = 15
paseli_padding: int = 15
CLEAR_TYPE_SINGLE = 1
CLEAR_TYPE_DOUBLE = 2
CLEAR_TYPE_SINGLE: Final[int] = 1
CLEAR_TYPE_DOUBLE: Final[int] = 2
CLEAR_STATUS_NO_PLAY = DBConstants.IIDX_CLEAR_STATUS_NO_PLAY
CLEAR_STATUS_FAILED = DBConstants.IIDX_CLEAR_STATUS_FAILED
CLEAR_STATUS_ASSIST_CLEAR = DBConstants.IIDX_CLEAR_STATUS_ASSIST_CLEAR
CLEAR_STATUS_EASY_CLEAR = DBConstants.IIDX_CLEAR_STATUS_EASY_CLEAR
CLEAR_STATUS_CLEAR = DBConstants.IIDX_CLEAR_STATUS_CLEAR
CLEAR_STATUS_HARD_CLEAR = DBConstants.IIDX_CLEAR_STATUS_HARD_CLEAR
CLEAR_STATUS_EX_HARD_CLEAR = DBConstants.IIDX_CLEAR_STATUS_EX_HARD_CLEAR
CLEAR_STATUS_FULL_COMBO = DBConstants.IIDX_CLEAR_STATUS_FULL_COMBO
CLEAR_STATUS_NO_PLAY: Final[int] = DBConstants.IIDX_CLEAR_STATUS_NO_PLAY
CLEAR_STATUS_FAILED: Final[int] = DBConstants.IIDX_CLEAR_STATUS_FAILED
CLEAR_STATUS_ASSIST_CLEAR: Final[int] = DBConstants.IIDX_CLEAR_STATUS_ASSIST_CLEAR
CLEAR_STATUS_EASY_CLEAR: Final[int] = DBConstants.IIDX_CLEAR_STATUS_EASY_CLEAR
CLEAR_STATUS_CLEAR: Final[int] = DBConstants.IIDX_CLEAR_STATUS_CLEAR
CLEAR_STATUS_HARD_CLEAR: Final[int] = DBConstants.IIDX_CLEAR_STATUS_HARD_CLEAR
CLEAR_STATUS_EX_HARD_CLEAR: Final[int] = DBConstants.IIDX_CLEAR_STATUS_EX_HARD_CLEAR
CLEAR_STATUS_FULL_COMBO: Final[int] = DBConstants.IIDX_CLEAR_STATUS_FULL_COMBO
CHART_TYPE_N7 = 0
CHART_TYPE_H7 = 1
CHART_TYPE_A7 = 2
CHART_TYPE_N14 = 3
CHART_TYPE_H14 = 4
CHART_TYPE_A14 = 5
CHART_TYPE_N7: Final[int] = 0
CHART_TYPE_H7: Final[int] = 1
CHART_TYPE_A7: Final[int] = 2
CHART_TYPE_N14: Final[int] = 3
CHART_TYPE_H14: Final[int] = 4
CHART_TYPE_A14: Final[int] = 5
# Beginner charts only save status
CHART_TYPE_B7 = 6
CHART_TYPE_B7: Final[int] = 6
DAN_RANK_7_KYU = DBConstants.IIDX_DAN_RANK_7_KYU
DAN_RANK_6_KYU = DBConstants.IIDX_DAN_RANK_6_KYU
DAN_RANK_5_KYU = DBConstants.IIDX_DAN_RANK_5_KYU
DAN_RANK_4_KYU = DBConstants.IIDX_DAN_RANK_4_KYU
DAN_RANK_3_KYU = DBConstants.IIDX_DAN_RANK_3_KYU
DAN_RANK_2_KYU = DBConstants.IIDX_DAN_RANK_2_KYU
DAN_RANK_1_KYU = DBConstants.IIDX_DAN_RANK_1_KYU
DAN_RANK_1_DAN = DBConstants.IIDX_DAN_RANK_1_DAN
DAN_RANK_2_DAN = DBConstants.IIDX_DAN_RANK_2_DAN
DAN_RANK_3_DAN = DBConstants.IIDX_DAN_RANK_3_DAN
DAN_RANK_4_DAN = DBConstants.IIDX_DAN_RANK_4_DAN
DAN_RANK_5_DAN = DBConstants.IIDX_DAN_RANK_5_DAN
DAN_RANK_6_DAN = DBConstants.IIDX_DAN_RANK_6_DAN
DAN_RANK_7_DAN = DBConstants.IIDX_DAN_RANK_7_DAN
DAN_RANK_8_DAN = DBConstants.IIDX_DAN_RANK_8_DAN
DAN_RANK_9_DAN = DBConstants.IIDX_DAN_RANK_9_DAN
DAN_RANK_10_DAN = DBConstants.IIDX_DAN_RANK_10_DAN
DAN_RANK_CHUDEN = DBConstants.IIDX_DAN_RANK_CHUDEN
DAN_RANK_KAIDEN = DBConstants.IIDX_DAN_RANK_KAIDEN
DAN_RANK_7_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_7_KYU
DAN_RANK_6_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_6_KYU
DAN_RANK_5_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_5_KYU
DAN_RANK_4_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_4_KYU
DAN_RANK_3_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_3_KYU
DAN_RANK_2_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_2_KYU
DAN_RANK_1_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_1_KYU
DAN_RANK_1_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_1_DAN
DAN_RANK_2_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_2_DAN
DAN_RANK_3_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_3_DAN
DAN_RANK_4_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_4_DAN
DAN_RANK_5_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_5_DAN
DAN_RANK_6_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_6_DAN
DAN_RANK_7_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_7_DAN
DAN_RANK_8_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_8_DAN
DAN_RANK_9_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_9_DAN
DAN_RANK_10_DAN: Final[int] = DBConstants.IIDX_DAN_RANK_10_DAN
DAN_RANK_CHUDEN: Final[int] = DBConstants.IIDX_DAN_RANK_CHUDEN
DAN_RANK_KAIDEN: Final[int] = DBConstants.IIDX_DAN_RANK_KAIDEN
DAN_RANKING_SINGLE = 'sgrade'
DAN_RANKING_DOUBLE = 'dgrade'
DAN_RANKING_SINGLE: Final[str] = 'sgrade'
DAN_RANKING_DOUBLE: Final[str] = 'dgrade'
GHOST_TYPE_NONE = 0
GHOST_TYPE_RIVAL = 100
GHOST_TYPE_GLOBAL_TOP = 200
GHOST_TYPE_GLOBAL_AVERAGE = 300
GHOST_TYPE_LOCAL_TOP = 400
GHOST_TYPE_LOCAL_AVERAGE = 500
GHOST_TYPE_DAN_TOP = 600
GHOST_TYPE_DAN_AVERAGE = 700
GHOST_TYPE_RIVAL_TOP = 800
GHOST_TYPE_RIVAL_AVERAGE = 900
GHOST_TYPE_NONE: Final[int] = 0
GHOST_TYPE_RIVAL: Final[int] = 100
GHOST_TYPE_GLOBAL_TOP: Final[int] = 200
GHOST_TYPE_GLOBAL_AVERAGE: Final[int] = 300
GHOST_TYPE_LOCAL_TOP: Final[int] = 400
GHOST_TYPE_LOCAL_AVERAGE: Final[int] = 500
GHOST_TYPE_DAN_TOP: Final[int] = 600
GHOST_TYPE_DAN_AVERAGE: Final[int] = 700
GHOST_TYPE_RIVAL_TOP: Final[int] = 800
GHOST_TYPE_RIVAL_AVERAGE: Final[int] = 900
# Return the local2 service so that Copula and above will send certain packets.
extra_services: List[str] = [

View File

@ -8,10 +8,10 @@ from bemani.common import VersionConstants
class IIDXBistrover(IIDXBase):
name = 'Beatmania IIDX BISTROVER'
version = VersionConstants.IIDX_BISTROVER
name: str = 'Beatmania IIDX BISTROVER'
version: int = VersionConstants.IIDX_BISTROVER
requires_extended_regions = True
requires_extended_regions: bool = True
def previous_version(self) -> Optional[IIDXBase]:
return IIDXHeroicVerse(self.data, self.config, self.model)

View File

@ -1,8 +1,8 @@
# vim: set fileencoding=utf-8
import copy
import random
import struct
from typing import Optional, Dict, Any, List, Tuple
from typing_extensions import Final
from bemani.backend.iidx.base import IIDXBase
from bemani.backend.iidx.course import IIDXCourse
@ -15,76 +15,76 @@ from bemani.protocol import Node
class IIDXCannonBallers(IIDXCourse, IIDXBase):
name = 'Beatmania IIDX CANNON BALLERS'
version = VersionConstants.IIDX_CANNON_BALLERS
name: str = 'Beatmania IIDX CANNON BALLERS'
version: int = VersionConstants.IIDX_CANNON_BALLERS
GAME_CLTYPE_SINGLE = 0
GAME_CLTYPE_DOUBLE = 1
GAME_CLTYPE_SINGLE: Final[int] = 0
GAME_CLTYPE_DOUBLE: Final[int] = 1
DAN_STAGES = 4
DAN_STAGES: Final[int] = 4
GAME_CLEAR_STATUS_NO_PLAY = 0
GAME_CLEAR_STATUS_FAILED = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR = 2
GAME_CLEAR_STATUS_EASY_CLEAR = 3
GAME_CLEAR_STATUS_CLEAR = 4
GAME_CLEAR_STATUS_HARD_CLEAR = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR = 6
GAME_CLEAR_STATUS_FULL_COMBO = 7
GAME_CLEAR_STATUS_NO_PLAY: Final[int] = 0
GAME_CLEAR_STATUS_FAILED: Final[int] = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR: Final[int] = 2
GAME_CLEAR_STATUS_EASY_CLEAR: Final[int] = 3
GAME_CLEAR_STATUS_CLEAR: Final[int] = 4
GAME_CLEAR_STATUS_HARD_CLEAR: Final[int] = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR: Final[int] = 6
GAME_CLEAR_STATUS_FULL_COMBO: Final[int] = 7
GAME_GHOST_TYPE_RIVAL = 1
GAME_GHOST_TYPE_GLOBAL_TOP = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE = 3
GAME_GHOST_TYPE_LOCAL_TOP = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE = 5
GAME_GHOST_TYPE_DAN_TOP = 6
GAME_GHOST_TYPE_DAN_AVERAGE = 7
GAME_GHOST_TYPE_RIVAL_TOP = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE = 9
GAME_GHOST_TYPE_RIVAL: Final[int] = 1
GAME_GHOST_TYPE_GLOBAL_TOP: Final[int] = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE: Final[int] = 3
GAME_GHOST_TYPE_LOCAL_TOP: Final[int] = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE: Final[int] = 5
GAME_GHOST_TYPE_DAN_TOP: Final[int] = 6
GAME_GHOST_TYPE_DAN_AVERAGE: Final[int] = 7
GAME_GHOST_TYPE_RIVAL_TOP: Final[int] = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE: Final[int] = 9
GAME_GHOST_LENGTH = 64
GAME_GHOST_LENGTH: Final[int] = 64
GAME_SP_DAN_RANK_7_KYU = 0
GAME_SP_DAN_RANK_6_KYU = 1
GAME_SP_DAN_RANK_5_KYU = 2
GAME_SP_DAN_RANK_4_KYU = 3
GAME_SP_DAN_RANK_3_KYU = 4
GAME_SP_DAN_RANK_2_KYU = 5
GAME_SP_DAN_RANK_1_KYU = 6
GAME_SP_DAN_RANK_1_DAN = 7
GAME_SP_DAN_RANK_2_DAN = 8
GAME_SP_DAN_RANK_3_DAN = 9
GAME_SP_DAN_RANK_4_DAN = 10
GAME_SP_DAN_RANK_5_DAN = 11
GAME_SP_DAN_RANK_6_DAN = 12
GAME_SP_DAN_RANK_7_DAN = 13
GAME_SP_DAN_RANK_8_DAN = 14
GAME_SP_DAN_RANK_9_DAN = 15
GAME_SP_DAN_RANK_10_DAN = 16
GAME_SP_DAN_RANK_CHUDEN = 17
GAME_SP_DAN_RANK_KAIDEN = 18
GAME_SP_DAN_RANK_7_KYU: Final[int] = 0
GAME_SP_DAN_RANK_6_KYU: Final[int] = 1
GAME_SP_DAN_RANK_5_KYU: Final[int] = 2
GAME_SP_DAN_RANK_4_KYU: Final[int] = 3
GAME_SP_DAN_RANK_3_KYU: Final[int] = 4
GAME_SP_DAN_RANK_2_KYU: Final[int] = 5
GAME_SP_DAN_RANK_1_KYU: Final[int] = 6
GAME_SP_DAN_RANK_1_DAN: Final[int] = 7
GAME_SP_DAN_RANK_2_DAN: Final[int] = 8
GAME_SP_DAN_RANK_3_DAN: Final[int] = 9
GAME_SP_DAN_RANK_4_DAN: Final[int] = 10
GAME_SP_DAN_RANK_5_DAN: Final[int] = 11
GAME_SP_DAN_RANK_6_DAN: Final[int] = 12
GAME_SP_DAN_RANK_7_DAN: Final[int] = 13
GAME_SP_DAN_RANK_8_DAN: Final[int] = 14
GAME_SP_DAN_RANK_9_DAN: Final[int] = 15
GAME_SP_DAN_RANK_10_DAN: Final[int] = 16
GAME_SP_DAN_RANK_CHUDEN: Final[int] = 17
GAME_SP_DAN_RANK_KAIDEN: Final[int] = 18
GAME_DP_DAN_RANK_7_KYU = 0
GAME_DP_DAN_RANK_6_KYU = 1
GAME_DP_DAN_RANK_5_KYU = 2
GAME_DP_DAN_RANK_4_KYU = 3
GAME_DP_DAN_RANK_3_KYU = 4
GAME_DP_DAN_RANK_2_KYU = 5
GAME_DP_DAN_RANK_1_KYU = 6
GAME_DP_DAN_RANK_1_DAN = 7
GAME_DP_DAN_RANK_2_DAN = 8
GAME_DP_DAN_RANK_3_DAN = 9
GAME_DP_DAN_RANK_4_DAN = 10
GAME_DP_DAN_RANK_5_DAN = 11
GAME_DP_DAN_RANK_6_DAN = 12
GAME_DP_DAN_RANK_7_DAN = 13
GAME_DP_DAN_RANK_8_DAN = 14
GAME_DP_DAN_RANK_9_DAN = 15
GAME_DP_DAN_RANK_10_DAN = 16
GAME_DP_DAN_RANK_CHUDEN = 17
GAME_DP_DAN_RANK_KAIDEN = 18
GAME_DP_DAN_RANK_7_KYU: Final[int] = 0
GAME_DP_DAN_RANK_6_KYU: Final[int] = 1
GAME_DP_DAN_RANK_5_KYU: Final[int] = 2
GAME_DP_DAN_RANK_4_KYU: Final[int] = 3
GAME_DP_DAN_RANK_3_KYU: Final[int] = 4
GAME_DP_DAN_RANK_2_KYU: Final[int] = 5
GAME_DP_DAN_RANK_1_KYU: Final[int] = 6
GAME_DP_DAN_RANK_1_DAN: Final[int] = 7
GAME_DP_DAN_RANK_2_DAN: Final[int] = 8
GAME_DP_DAN_RANK_3_DAN: Final[int] = 9
GAME_DP_DAN_RANK_4_DAN: Final[int] = 10
GAME_DP_DAN_RANK_5_DAN: Final[int] = 11
GAME_DP_DAN_RANK_6_DAN: Final[int] = 12
GAME_DP_DAN_RANK_7_DAN: Final[int] = 13
GAME_DP_DAN_RANK_8_DAN: Final[int] = 14
GAME_DP_DAN_RANK_9_DAN: Final[int] = 15
GAME_DP_DAN_RANK_10_DAN: Final[int] = 16
GAME_DP_DAN_RANK_CHUDEN: Final[int] = 17
GAME_DP_DAN_RANK_KAIDEN: Final[int] = 18
FAVORITE_LIST_LENGTH = 20
FAVORITE_LIST_LENGTH: Final[int] = 20
requires_extended_regions: bool = True
@ -1865,7 +1865,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Track play counts

View File

@ -1,8 +1,8 @@
# vim: set fileencoding=utf-8
import copy
import random
import struct
from typing import Optional, Dict, Any, List, Tuple
from typing_extensions import Final
from bemani.backend.iidx.base import IIDXBase
from bemani.backend.iidx.course import IIDXCourse
@ -15,76 +15,76 @@ from bemani.protocol import Node
class IIDXCopula(IIDXCourse, IIDXBase):
name = 'Beatmania IIDX copula'
version = VersionConstants.IIDX_COPULA
name: str = 'Beatmania IIDX copula'
version: int = VersionConstants.IIDX_COPULA
GAME_CLTYPE_SINGLE = 0
GAME_CLTYPE_DOUBLE = 1
GAME_CLTYPE_SINGLE: Final[int] = 0
GAME_CLTYPE_DOUBLE: Final[int] = 1
DAN_STAGES = 4
DAN_STAGES: Final[int] = 4
GAME_CLEAR_STATUS_NO_PLAY = 0
GAME_CLEAR_STATUS_FAILED = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR = 2
GAME_CLEAR_STATUS_EASY_CLEAR = 3
GAME_CLEAR_STATUS_CLEAR = 4
GAME_CLEAR_STATUS_HARD_CLEAR = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR = 6
GAME_CLEAR_STATUS_FULL_COMBO = 7
GAME_CLEAR_STATUS_NO_PLAY: Final[int] = 0
GAME_CLEAR_STATUS_FAILED: Final[int] = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR: Final[int] = 2
GAME_CLEAR_STATUS_EASY_CLEAR: Final[int] = 3
GAME_CLEAR_STATUS_CLEAR: Final[int] = 4
GAME_CLEAR_STATUS_HARD_CLEAR: Final[int] = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR: Final[int] = 6
GAME_CLEAR_STATUS_FULL_COMBO: Final[int] = 7
GAME_GHOST_TYPE_RIVAL = 1
GAME_GHOST_TYPE_GLOBAL_TOP = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE = 3
GAME_GHOST_TYPE_LOCAL_TOP = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE = 5
GAME_GHOST_TYPE_DAN_TOP = 6
GAME_GHOST_TYPE_DAN_AVERAGE = 7
GAME_GHOST_TYPE_RIVAL_TOP = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE = 9
GAME_GHOST_TYPE_RIVAL: Final[int] = 1
GAME_GHOST_TYPE_GLOBAL_TOP: Final[int] = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE: Final[int] = 3
GAME_GHOST_TYPE_LOCAL_TOP: Final[int] = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE: Final[int] = 5
GAME_GHOST_TYPE_DAN_TOP: Final[int] = 6
GAME_GHOST_TYPE_DAN_AVERAGE: Final[int] = 7
GAME_GHOST_TYPE_RIVAL_TOP: Final[int] = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE: Final[int] = 9
GAME_GHOST_LENGTH = 64
GAME_GHOST_LENGTH: Final[int] = 64
GAME_SP_DAN_RANK_7_KYU = 0
GAME_SP_DAN_RANK_6_KYU = 1
GAME_SP_DAN_RANK_5_KYU = 2
GAME_SP_DAN_RANK_4_KYU = 3
GAME_SP_DAN_RANK_3_KYU = 4
GAME_SP_DAN_RANK_2_KYU = 5
GAME_SP_DAN_RANK_1_KYU = 6
GAME_SP_DAN_RANK_1_DAN = 7
GAME_SP_DAN_RANK_2_DAN = 8
GAME_SP_DAN_RANK_3_DAN = 9
GAME_SP_DAN_RANK_4_DAN = 10
GAME_SP_DAN_RANK_5_DAN = 11
GAME_SP_DAN_RANK_6_DAN = 12
GAME_SP_DAN_RANK_7_DAN = 13
GAME_SP_DAN_RANK_8_DAN = 14
GAME_SP_DAN_RANK_9_DAN = 15
GAME_SP_DAN_RANK_10_DAN = 16
GAME_SP_DAN_RANK_CHUDEN = 17
GAME_SP_DAN_RANK_KAIDEN = 18
GAME_SP_DAN_RANK_7_KYU: Final[int] = 0
GAME_SP_DAN_RANK_6_KYU: Final[int] = 1
GAME_SP_DAN_RANK_5_KYU: Final[int] = 2
GAME_SP_DAN_RANK_4_KYU: Final[int] = 3
GAME_SP_DAN_RANK_3_KYU: Final[int] = 4
GAME_SP_DAN_RANK_2_KYU: Final[int] = 5
GAME_SP_DAN_RANK_1_KYU: Final[int] = 6
GAME_SP_DAN_RANK_1_DAN: Final[int] = 7
GAME_SP_DAN_RANK_2_DAN: Final[int] = 8
GAME_SP_DAN_RANK_3_DAN: Final[int] = 9
GAME_SP_DAN_RANK_4_DAN: Final[int] = 10
GAME_SP_DAN_RANK_5_DAN: Final[int] = 11
GAME_SP_DAN_RANK_6_DAN: Final[int] = 12
GAME_SP_DAN_RANK_7_DAN: Final[int] = 13
GAME_SP_DAN_RANK_8_DAN: Final[int] = 14
GAME_SP_DAN_RANK_9_DAN: Final[int] = 15
GAME_SP_DAN_RANK_10_DAN: Final[int] = 16
GAME_SP_DAN_RANK_CHUDEN: Final[int] = 17
GAME_SP_DAN_RANK_KAIDEN: Final[int] = 18
GAME_DP_DAN_RANK_7_KYU = 0
GAME_DP_DAN_RANK_6_KYU = 1
GAME_DP_DAN_RANK_5_KYU = 2
GAME_DP_DAN_RANK_4_KYU = 3
GAME_DP_DAN_RANK_3_KYU = 4
GAME_DP_DAN_RANK_2_KYU = 5
GAME_DP_DAN_RANK_1_KYU = 6
GAME_DP_DAN_RANK_1_DAN = 7
GAME_DP_DAN_RANK_2_DAN = 8
GAME_DP_DAN_RANK_3_DAN = 9
GAME_DP_DAN_RANK_4_DAN = 10
GAME_DP_DAN_RANK_5_DAN = 11
GAME_DP_DAN_RANK_6_DAN = 12
GAME_DP_DAN_RANK_7_DAN = 13
GAME_DP_DAN_RANK_8_DAN = 14
GAME_DP_DAN_RANK_9_DAN = 15
GAME_DP_DAN_RANK_10_DAN = 16
GAME_DP_DAN_RANK_CHUDEN = 17
GAME_DP_DAN_RANK_KAIDEN = 18
GAME_DP_DAN_RANK_7_KYU: Final[int] = 0
GAME_DP_DAN_RANK_6_KYU: Final[int] = 1
GAME_DP_DAN_RANK_5_KYU: Final[int] = 2
GAME_DP_DAN_RANK_4_KYU: Final[int] = 3
GAME_DP_DAN_RANK_3_KYU: Final[int] = 4
GAME_DP_DAN_RANK_2_KYU: Final[int] = 5
GAME_DP_DAN_RANK_1_KYU: Final[int] = 6
GAME_DP_DAN_RANK_1_DAN: Final[int] = 7
GAME_DP_DAN_RANK_2_DAN: Final[int] = 8
GAME_DP_DAN_RANK_3_DAN: Final[int] = 9
GAME_DP_DAN_RANK_4_DAN: Final[int] = 10
GAME_DP_DAN_RANK_5_DAN: Final[int] = 11
GAME_DP_DAN_RANK_6_DAN: Final[int] = 12
GAME_DP_DAN_RANK_7_DAN: Final[int] = 13
GAME_DP_DAN_RANK_8_DAN: Final[int] = 14
GAME_DP_DAN_RANK_9_DAN: Final[int] = 15
GAME_DP_DAN_RANK_10_DAN: Final[int] = 16
GAME_DP_DAN_RANK_CHUDEN: Final[int] = 17
GAME_DP_DAN_RANK_KAIDEN: Final[int] = 18
FAVORITE_LIST_LENGTH = 20
FAVORITE_LIST_LENGTH: Final[int] = 20
def previous_version(self) -> Optional[IIDXBase]:
return IIDXPendual(self.data, self.config, self.model)
@ -1872,7 +1872,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Track play counts

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Tuple
from typing_extensions import Final
from bemani.backend.iidx.base import IIDXBase
from bemani.common import ValidatedDict
@ -8,9 +9,9 @@ from bemani.data import UserID
class IIDXCourse(IIDXBase):
COURSE_TYPE_SECRET = 'secret_course'
COURSE_TYPE_INTERNET_RANKING = 'ir_course'
COURSE_TYPE_CLASSIC = 'classic_course'
COURSE_TYPE_SECRET: Final[str] = 'secret_course'
COURSE_TYPE_INTERNET_RANKING: Final[str] = 'ir_course'
COURSE_TYPE_CLASSIC: Final[str] = 'classic_course'
def id_and_chart_from_courseid(self, courseid: int) -> Tuple[int, int]:
return (int(courseid / 6), courseid % 6)

View File

@ -1,4 +1,4 @@
from typing import Optional
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.iidx.stubs import (
@ -37,7 +37,7 @@ from bemani.data import Config, Data
class IIDXFactory(Factory):
MANAGED_CLASSES = [
MANAGED_CLASSES: List[Type[Base]] = [
IIDX1stStyle,
IIDX2ndStyle,
IIDX3rdStyle,

View File

@ -8,10 +8,10 @@ from bemani.common import VersionConstants
class IIDXHeroicVerse(IIDXBase):
name = 'Beatmania IIDX HEROIC VERSE'
version = VersionConstants.IIDX_HEROIC_VERSE
name: str = 'Beatmania IIDX HEROIC VERSE'
version: int = VersionConstants.IIDX_HEROIC_VERSE
requires_extended_regions = True
requires_extended_regions: bool = True
def previous_version(self) -> Optional[IIDXBase]:
return IIDXRootage(self.data, self.config, self.model)

View File

@ -1,8 +1,8 @@
# vim: set fileencoding=utf-8
import copy
import random
import struct
from typing import Optional, Dict, Any, List, Tuple
from typing_extensions import Final
from bemani.backend.iidx.base import IIDXBase
from bemani.backend.iidx.course import IIDXCourse
@ -15,73 +15,73 @@ from bemani.protocol import Node
class IIDXPendual(IIDXCourse, IIDXBase):
name = 'Beatmania IIDX PENDUAL'
version = VersionConstants.IIDX_PENDUAL
name: str = 'Beatmania IIDX PENDUAL'
version: int = VersionConstants.IIDX_PENDUAL
GAME_CLTYPE_SINGLE = 0
GAME_CLTYPE_DOUBLE = 1
GAME_CLTYPE_SINGLE: Final[int] = 0
GAME_CLTYPE_DOUBLE: Final[int] = 1
DAN_STAGES_SINGLE = 4
DAN_STAGES_DOUBLE = 3
DAN_STAGES_SINGLE: Final[int] = 4
DAN_STAGES_DOUBLE: Final[int] = 3
GAME_CLEAR_STATUS_NO_PLAY = 0
GAME_CLEAR_STATUS_FAILED = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR = 2
GAME_CLEAR_STATUS_EASY_CLEAR = 3
GAME_CLEAR_STATUS_CLEAR = 4
GAME_CLEAR_STATUS_HARD_CLEAR = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR = 6
GAME_CLEAR_STATUS_FULL_COMBO = 7
GAME_CLEAR_STATUS_NO_PLAY: Final[int] = 0
GAME_CLEAR_STATUS_FAILED: Final[int] = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR: Final[int] = 2
GAME_CLEAR_STATUS_EASY_CLEAR: Final[int] = 3
GAME_CLEAR_STATUS_CLEAR: Final[int] = 4
GAME_CLEAR_STATUS_HARD_CLEAR: Final[int] = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR: Final[int] = 6
GAME_CLEAR_STATUS_FULL_COMBO: Final[int] = 7
GAME_GHOST_TYPE_RIVAL = 1
GAME_GHOST_TYPE_GLOBAL_TOP = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE = 3
GAME_GHOST_TYPE_LOCAL_TOP = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE = 5
GAME_GHOST_TYPE_DAN_TOP = 6
GAME_GHOST_TYPE_DAN_AVERAGE = 7
GAME_GHOST_TYPE_RIVAL_TOP = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE = 9
GAME_GHOST_TYPE_RIVAL: Final[int] = 1
GAME_GHOST_TYPE_GLOBAL_TOP: Final[int] = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE: Final[int] = 3
GAME_GHOST_TYPE_LOCAL_TOP: Final[int] = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE: Final[int] = 5
GAME_GHOST_TYPE_DAN_TOP: Final[int] = 6
GAME_GHOST_TYPE_DAN_AVERAGE: Final[int] = 7
GAME_GHOST_TYPE_RIVAL_TOP: Final[int] = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE: Final[int] = 9
GAME_GHOST_LENGTH = 64
GAME_GHOST_LENGTH: Final[int] = 64
GAME_SP_DAN_RANK_7_KYU = 0
GAME_SP_DAN_RANK_6_KYU = 1
GAME_SP_DAN_RANK_5_KYU = 2
GAME_SP_DAN_RANK_4_KYU = 3
GAME_SP_DAN_RANK_3_KYU = 4
GAME_SP_DAN_RANK_2_KYU = 5
GAME_SP_DAN_RANK_1_KYU = 6
GAME_SP_DAN_RANK_1_DAN = 7
GAME_SP_DAN_RANK_2_DAN = 8
GAME_SP_DAN_RANK_3_DAN = 9
GAME_SP_DAN_RANK_4_DAN = 10
GAME_SP_DAN_RANK_5_DAN = 11
GAME_SP_DAN_RANK_6_DAN = 12
GAME_SP_DAN_RANK_7_DAN = 13
GAME_SP_DAN_RANK_8_DAN = 14
GAME_SP_DAN_RANK_9_DAN = 15
GAME_SP_DAN_RANK_10_DAN = 16
GAME_SP_DAN_RANK_KAIDEN = 17
GAME_SP_DAN_RANK_7_KYU: Final[int] = 0
GAME_SP_DAN_RANK_6_KYU: Final[int] = 1
GAME_SP_DAN_RANK_5_KYU: Final[int] = 2
GAME_SP_DAN_RANK_4_KYU: Final[int] = 3
GAME_SP_DAN_RANK_3_KYU: Final[int] = 4
GAME_SP_DAN_RANK_2_KYU: Final[int] = 5
GAME_SP_DAN_RANK_1_KYU: Final[int] = 6
GAME_SP_DAN_RANK_1_DAN: Final[int] = 7
GAME_SP_DAN_RANK_2_DAN: Final[int] = 8
GAME_SP_DAN_RANK_3_DAN: Final[int] = 9
GAME_SP_DAN_RANK_4_DAN: Final[int] = 10
GAME_SP_DAN_RANK_5_DAN: Final[int] = 11
GAME_SP_DAN_RANK_6_DAN: Final[int] = 12
GAME_SP_DAN_RANK_7_DAN: Final[int] = 13
GAME_SP_DAN_RANK_8_DAN: Final[int] = 14
GAME_SP_DAN_RANK_9_DAN: Final[int] = 15
GAME_SP_DAN_RANK_10_DAN: Final[int] = 16
GAME_SP_DAN_RANK_KAIDEN: Final[int] = 17
GAME_DP_DAN_RANK_5_KYU = 0
GAME_DP_DAN_RANK_4_KYU = 1
GAME_DP_DAN_RANK_3_KYU = 2
GAME_DP_DAN_RANK_2_KYU = 3
GAME_DP_DAN_RANK_1_KYU = 4
GAME_DP_DAN_RANK_1_DAN = 5
GAME_DP_DAN_RANK_2_DAN = 6
GAME_DP_DAN_RANK_3_DAN = 7
GAME_DP_DAN_RANK_4_DAN = 8
GAME_DP_DAN_RANK_5_DAN = 9
GAME_DP_DAN_RANK_6_DAN = 10
GAME_DP_DAN_RANK_7_DAN = 11
GAME_DP_DAN_RANK_8_DAN = 12
GAME_DP_DAN_RANK_9_DAN = 13
GAME_DP_DAN_RANK_10_DAN = 14
GAME_DP_DAN_RANK_KAIDEN = 15
GAME_DP_DAN_RANK_5_KYU: Final[int] = 0
GAME_DP_DAN_RANK_4_KYU: Final[int] = 1
GAME_DP_DAN_RANK_3_KYU: Final[int] = 2
GAME_DP_DAN_RANK_2_KYU: Final[int] = 3
GAME_DP_DAN_RANK_1_KYU: Final[int] = 4
GAME_DP_DAN_RANK_1_DAN: Final[int] = 5
GAME_DP_DAN_RANK_2_DAN: Final[int] = 6
GAME_DP_DAN_RANK_3_DAN: Final[int] = 7
GAME_DP_DAN_RANK_4_DAN: Final[int] = 8
GAME_DP_DAN_RANK_5_DAN: Final[int] = 9
GAME_DP_DAN_RANK_6_DAN: Final[int] = 10
GAME_DP_DAN_RANK_7_DAN: Final[int] = 11
GAME_DP_DAN_RANK_8_DAN: Final[int] = 12
GAME_DP_DAN_RANK_9_DAN: Final[int] = 13
GAME_DP_DAN_RANK_10_DAN: Final[int] = 14
GAME_DP_DAN_RANK_KAIDEN: Final[int] = 15
FAVORITE_LIST_LENGTH = 20
FAVORITE_LIST_LENGTH: Final[int] = 20
def previous_version(self) -> Optional[IIDXBase]:
return IIDXSpada(self.data, self.config, self.model)
@ -1718,7 +1718,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Track play counts

View File

@ -1,8 +1,8 @@
# vim: set fileencoding=utf-8
import copy
import random
import struct
from typing import Optional, Dict, Any, List, Tuple
from typing_extensions import Final
from bemani.backend.iidx.base import IIDXBase
from bemani.backend.iidx.course import IIDXCourse
@ -15,76 +15,76 @@ from bemani.protocol import Node
class IIDXRootage(IIDXCourse, IIDXBase):
name = 'Beatmania IIDX ROOTAGE'
version = VersionConstants.IIDX_ROOTAGE
name: str = 'Beatmania IIDX ROOTAGE'
version: int = VersionConstants.IIDX_ROOTAGE
GAME_CLTYPE_SINGLE = 0
GAME_CLTYPE_DOUBLE = 1
GAME_CLTYPE_SINGLE: Final[int] = 0
GAME_CLTYPE_DOUBLE: Final[int] = 1
DAN_STAGES = 4
DAN_STAGES: Final[int] = 4
GAME_CLEAR_STATUS_NO_PLAY = 0
GAME_CLEAR_STATUS_FAILED = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR = 2
GAME_CLEAR_STATUS_EASY_CLEAR = 3
GAME_CLEAR_STATUS_CLEAR = 4
GAME_CLEAR_STATUS_HARD_CLEAR = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR = 6
GAME_CLEAR_STATUS_FULL_COMBO = 7
GAME_CLEAR_STATUS_NO_PLAY: Final[int] = 0
GAME_CLEAR_STATUS_FAILED: Final[int] = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR: Final[int] = 2
GAME_CLEAR_STATUS_EASY_CLEAR: Final[int] = 3
GAME_CLEAR_STATUS_CLEAR: Final[int] = 4
GAME_CLEAR_STATUS_HARD_CLEAR: Final[int] = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR: Final[int] = 6
GAME_CLEAR_STATUS_FULL_COMBO: Final[int] = 7
GAME_GHOST_TYPE_RIVAL = 1
GAME_GHOST_TYPE_GLOBAL_TOP = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE = 3
GAME_GHOST_TYPE_LOCAL_TOP = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE = 5
GAME_GHOST_TYPE_DAN_TOP = 6
GAME_GHOST_TYPE_DAN_AVERAGE = 7
GAME_GHOST_TYPE_RIVAL_TOP = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE = 9
GAME_GHOST_TYPE_RIVAL: Final[int] = 1
GAME_GHOST_TYPE_GLOBAL_TOP: Final[int] = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE: Final[int] = 3
GAME_GHOST_TYPE_LOCAL_TOP: Final[int] = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE: Final[int] = 5
GAME_GHOST_TYPE_DAN_TOP: Final[int] = 6
GAME_GHOST_TYPE_DAN_AVERAGE: Final[int] = 7
GAME_GHOST_TYPE_RIVAL_TOP: Final[int] = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE: Final[int] = 9
GAME_GHOST_LENGTH = 64
GAME_GHOST_LENGTH: Final[int] = 64
GAME_SP_DAN_RANK_7_KYU = 0
GAME_SP_DAN_RANK_6_KYU = 1
GAME_SP_DAN_RANK_5_KYU = 2
GAME_SP_DAN_RANK_4_KYU = 3
GAME_SP_DAN_RANK_3_KYU = 4
GAME_SP_DAN_RANK_2_KYU = 5
GAME_SP_DAN_RANK_1_KYU = 6
GAME_SP_DAN_RANK_1_DAN = 7
GAME_SP_DAN_RANK_2_DAN = 8
GAME_SP_DAN_RANK_3_DAN = 9
GAME_SP_DAN_RANK_4_DAN = 10
GAME_SP_DAN_RANK_5_DAN = 11
GAME_SP_DAN_RANK_6_DAN = 12
GAME_SP_DAN_RANK_7_DAN = 13
GAME_SP_DAN_RANK_8_DAN = 14
GAME_SP_DAN_RANK_9_DAN = 15
GAME_SP_DAN_RANK_10_DAN = 16
GAME_SP_DAN_RANK_CHUDEN = 17
GAME_SP_DAN_RANK_KAIDEN = 18
GAME_SP_DAN_RANK_7_KYU: Final[int] = 0
GAME_SP_DAN_RANK_6_KYU: Final[int] = 1
GAME_SP_DAN_RANK_5_KYU: Final[int] = 2
GAME_SP_DAN_RANK_4_KYU: Final[int] = 3
GAME_SP_DAN_RANK_3_KYU: Final[int] = 4
GAME_SP_DAN_RANK_2_KYU: Final[int] = 5
GAME_SP_DAN_RANK_1_KYU: Final[int] = 6
GAME_SP_DAN_RANK_1_DAN: Final[int] = 7
GAME_SP_DAN_RANK_2_DAN: Final[int] = 8
GAME_SP_DAN_RANK_3_DAN: Final[int] = 9
GAME_SP_DAN_RANK_4_DAN: Final[int] = 10
GAME_SP_DAN_RANK_5_DAN: Final[int] = 11
GAME_SP_DAN_RANK_6_DAN: Final[int] = 12
GAME_SP_DAN_RANK_7_DAN: Final[int] = 13
GAME_SP_DAN_RANK_8_DAN: Final[int] = 14
GAME_SP_DAN_RANK_9_DAN: Final[int] = 15
GAME_SP_DAN_RANK_10_DAN: Final[int] = 16
GAME_SP_DAN_RANK_CHUDEN: Final[int] = 17
GAME_SP_DAN_RANK_KAIDEN: Final[int] = 18
GAME_DP_DAN_RANK_7_KYU = 0
GAME_DP_DAN_RANK_6_KYU = 1
GAME_DP_DAN_RANK_5_KYU = 2
GAME_DP_DAN_RANK_4_KYU = 3
GAME_DP_DAN_RANK_3_KYU = 4
GAME_DP_DAN_RANK_2_KYU = 5
GAME_DP_DAN_RANK_1_KYU = 6
GAME_DP_DAN_RANK_1_DAN = 7
GAME_DP_DAN_RANK_2_DAN = 8
GAME_DP_DAN_RANK_3_DAN = 9
GAME_DP_DAN_RANK_4_DAN = 10
GAME_DP_DAN_RANK_5_DAN = 11
GAME_DP_DAN_RANK_6_DAN = 12
GAME_DP_DAN_RANK_7_DAN = 13
GAME_DP_DAN_RANK_8_DAN = 14
GAME_DP_DAN_RANK_9_DAN = 15
GAME_DP_DAN_RANK_10_DAN = 16
GAME_DP_DAN_RANK_CHUDEN = 17
GAME_DP_DAN_RANK_KAIDEN = 18
GAME_DP_DAN_RANK_7_KYU: Final[int] = 0
GAME_DP_DAN_RANK_6_KYU: Final[int] = 1
GAME_DP_DAN_RANK_5_KYU: Final[int] = 2
GAME_DP_DAN_RANK_4_KYU: Final[int] = 3
GAME_DP_DAN_RANK_3_KYU: Final[int] = 4
GAME_DP_DAN_RANK_2_KYU: Final[int] = 5
GAME_DP_DAN_RANK_1_KYU: Final[int] = 6
GAME_DP_DAN_RANK_1_DAN: Final[int] = 7
GAME_DP_DAN_RANK_2_DAN: Final[int] = 8
GAME_DP_DAN_RANK_3_DAN: Final[int] = 9
GAME_DP_DAN_RANK_4_DAN: Final[int] = 10
GAME_DP_DAN_RANK_5_DAN: Final[int] = 11
GAME_DP_DAN_RANK_6_DAN: Final[int] = 12
GAME_DP_DAN_RANK_7_DAN: Final[int] = 13
GAME_DP_DAN_RANK_8_DAN: Final[int] = 14
GAME_DP_DAN_RANK_9_DAN: Final[int] = 15
GAME_DP_DAN_RANK_10_DAN: Final[int] = 16
GAME_DP_DAN_RANK_CHUDEN: Final[int] = 17
GAME_DP_DAN_RANK_KAIDEN: Final[int] = 18
FAVORITE_LIST_LENGTH = 20
FAVORITE_LIST_LENGTH: Final[int] = 20
requires_extended_regions = True
@ -1577,7 +1577,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Track play counts

View File

@ -1,8 +1,8 @@
# vim: set fileencoding=utf-8
import copy
import random
import struct
from typing import Optional, Dict, Any, List, Tuple
from typing_extensions import Final
from bemani.backend.iidx.base import IIDXBase
from bemani.backend.iidx.course import IIDXCourse
@ -15,76 +15,76 @@ from bemani.protocol import Node
class IIDXSinobuz(IIDXCourse, IIDXBase):
name = 'Beatmania IIDX SINOBUZ'
version = VersionConstants.IIDX_SINOBUZ
name: str = 'Beatmania IIDX SINOBUZ'
version: int = VersionConstants.IIDX_SINOBUZ
GAME_CLTYPE_SINGLE = 0
GAME_CLTYPE_DOUBLE = 1
GAME_CLTYPE_SINGLE: Final[int] = 0
GAME_CLTYPE_DOUBLE: Final[int] = 1
DAN_STAGES = 4
DAN_STAGES: Final[int] = 4
GAME_CLEAR_STATUS_NO_PLAY = 0
GAME_CLEAR_STATUS_FAILED = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR = 2
GAME_CLEAR_STATUS_EASY_CLEAR = 3
GAME_CLEAR_STATUS_CLEAR = 4
GAME_CLEAR_STATUS_HARD_CLEAR = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR = 6
GAME_CLEAR_STATUS_FULL_COMBO = 7
GAME_CLEAR_STATUS_NO_PLAY: Final[int] = 0
GAME_CLEAR_STATUS_FAILED: Final[int] = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR: Final[int] = 2
GAME_CLEAR_STATUS_EASY_CLEAR: Final[int] = 3
GAME_CLEAR_STATUS_CLEAR: Final[int] = 4
GAME_CLEAR_STATUS_HARD_CLEAR: Final[int] = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR: Final[int] = 6
GAME_CLEAR_STATUS_FULL_COMBO: Final[int] = 7
GAME_GHOST_TYPE_RIVAL = 1
GAME_GHOST_TYPE_GLOBAL_TOP = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE = 3
GAME_GHOST_TYPE_LOCAL_TOP = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE = 5
GAME_GHOST_TYPE_DAN_TOP = 6
GAME_GHOST_TYPE_DAN_AVERAGE = 7
GAME_GHOST_TYPE_RIVAL_TOP = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE = 9
GAME_GHOST_TYPE_RIVAL: Final[int] = 1
GAME_GHOST_TYPE_GLOBAL_TOP: Final[int] = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE: Final[int] = 3
GAME_GHOST_TYPE_LOCAL_TOP: Final[int] = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE: Final[int] = 5
GAME_GHOST_TYPE_DAN_TOP: Final[int] = 6
GAME_GHOST_TYPE_DAN_AVERAGE: Final[int] = 7
GAME_GHOST_TYPE_RIVAL_TOP: Final[int] = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE: Final[int] = 9
GAME_GHOST_LENGTH = 64
GAME_GHOST_LENGTH: Final[int] = 64
GAME_SP_DAN_RANK_7_KYU = 0
GAME_SP_DAN_RANK_6_KYU = 1
GAME_SP_DAN_RANK_5_KYU = 2
GAME_SP_DAN_RANK_4_KYU = 3
GAME_SP_DAN_RANK_3_KYU = 4
GAME_SP_DAN_RANK_2_KYU = 5
GAME_SP_DAN_RANK_1_KYU = 6
GAME_SP_DAN_RANK_1_DAN = 7
GAME_SP_DAN_RANK_2_DAN = 8
GAME_SP_DAN_RANK_3_DAN = 9
GAME_SP_DAN_RANK_4_DAN = 10
GAME_SP_DAN_RANK_5_DAN = 11
GAME_SP_DAN_RANK_6_DAN = 12
GAME_SP_DAN_RANK_7_DAN = 13
GAME_SP_DAN_RANK_8_DAN = 14
GAME_SP_DAN_RANK_9_DAN = 15
GAME_SP_DAN_RANK_10_DAN = 16
GAME_SP_DAN_RANK_CHUDEN = 17
GAME_SP_DAN_RANK_KAIDEN = 18
GAME_SP_DAN_RANK_7_KYU: Final[int] = 0
GAME_SP_DAN_RANK_6_KYU: Final[int] = 1
GAME_SP_DAN_RANK_5_KYU: Final[int] = 2
GAME_SP_DAN_RANK_4_KYU: Final[int] = 3
GAME_SP_DAN_RANK_3_KYU: Final[int] = 4
GAME_SP_DAN_RANK_2_KYU: Final[int] = 5
GAME_SP_DAN_RANK_1_KYU: Final[int] = 6
GAME_SP_DAN_RANK_1_DAN: Final[int] = 7
GAME_SP_DAN_RANK_2_DAN: Final[int] = 8
GAME_SP_DAN_RANK_3_DAN: Final[int] = 9
GAME_SP_DAN_RANK_4_DAN: Final[int] = 10
GAME_SP_DAN_RANK_5_DAN: Final[int] = 11
GAME_SP_DAN_RANK_6_DAN: Final[int] = 12
GAME_SP_DAN_RANK_7_DAN: Final[int] = 13
GAME_SP_DAN_RANK_8_DAN: Final[int] = 14
GAME_SP_DAN_RANK_9_DAN: Final[int] = 15
GAME_SP_DAN_RANK_10_DAN: Final[int] = 16
GAME_SP_DAN_RANK_CHUDEN: Final[int] = 17
GAME_SP_DAN_RANK_KAIDEN: Final[int] = 18
GAME_DP_DAN_RANK_7_KYU = 0
GAME_DP_DAN_RANK_6_KYU = 1
GAME_DP_DAN_RANK_5_KYU = 2
GAME_DP_DAN_RANK_4_KYU = 3
GAME_DP_DAN_RANK_3_KYU = 4
GAME_DP_DAN_RANK_2_KYU = 5
GAME_DP_DAN_RANK_1_KYU = 6
GAME_DP_DAN_RANK_1_DAN = 7
GAME_DP_DAN_RANK_2_DAN = 8
GAME_DP_DAN_RANK_3_DAN = 9
GAME_DP_DAN_RANK_4_DAN = 10
GAME_DP_DAN_RANK_5_DAN = 11
GAME_DP_DAN_RANK_6_DAN = 12
GAME_DP_DAN_RANK_7_DAN = 13
GAME_DP_DAN_RANK_8_DAN = 14
GAME_DP_DAN_RANK_9_DAN = 15
GAME_DP_DAN_RANK_10_DAN = 16
GAME_DP_DAN_RANK_CHUDEN = 17
GAME_DP_DAN_RANK_KAIDEN = 18
GAME_DP_DAN_RANK_7_KYU: Final[int] = 0
GAME_DP_DAN_RANK_6_KYU: Final[int] = 1
GAME_DP_DAN_RANK_5_KYU: Final[int] = 2
GAME_DP_DAN_RANK_4_KYU: Final[int] = 3
GAME_DP_DAN_RANK_3_KYU: Final[int] = 4
GAME_DP_DAN_RANK_2_KYU: Final[int] = 5
GAME_DP_DAN_RANK_1_KYU: Final[int] = 6
GAME_DP_DAN_RANK_1_DAN: Final[int] = 7
GAME_DP_DAN_RANK_2_DAN: Final[int] = 8
GAME_DP_DAN_RANK_3_DAN: Final[int] = 9
GAME_DP_DAN_RANK_4_DAN: Final[int] = 10
GAME_DP_DAN_RANK_5_DAN: Final[int] = 11
GAME_DP_DAN_RANK_6_DAN: Final[int] = 12
GAME_DP_DAN_RANK_7_DAN: Final[int] = 13
GAME_DP_DAN_RANK_8_DAN: Final[int] = 14
GAME_DP_DAN_RANK_9_DAN: Final[int] = 15
GAME_DP_DAN_RANK_10_DAN: Final[int] = 16
GAME_DP_DAN_RANK_CHUDEN: Final[int] = 17
GAME_DP_DAN_RANK_KAIDEN: Final[int] = 18
FAVORITE_LIST_LENGTH = 20
FAVORITE_LIST_LENGTH: Final[int] = 20
def previous_version(self) -> Optional[IIDXBase]:
return IIDXCopula(self.data, self.config, self.model)
@ -1883,7 +1883,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Track play counts

View File

@ -1,8 +1,8 @@
# vim: set fileencoding=utf-8
import copy
import random
import struct
from typing import Optional, Dict, List, Tuple, Any
from typing_extensions import Final
from bemani.backend.iidx.base import IIDXBase
from bemani.backend.iidx.tricoro import IIDXTricoro
@ -14,73 +14,73 @@ from bemani.protocol import Node
class IIDXSpada(IIDXBase):
name = 'Beatmania IIDX SPADA'
version = VersionConstants.IIDX_SPADA
name: str = 'Beatmania IIDX SPADA'
version: int = VersionConstants.IIDX_SPADA
GAME_CLTYPE_SINGLE = 0
GAME_CLTYPE_DOUBLE = 1
GAME_CLTYPE_SINGLE: Final[int] = 0
GAME_CLTYPE_DOUBLE: Final[int] = 1
DAN_STAGES_SINGLE = 4
DAN_STAGES_DOUBLE = 3
DAN_STAGES_SINGLE: Final[int] = 4
DAN_STAGES_DOUBLE: Final[int] = 3
GAME_CLEAR_STATUS_NO_PLAY = 0
GAME_CLEAR_STATUS_FAILED = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR = 2
GAME_CLEAR_STATUS_EASY_CLEAR = 3
GAME_CLEAR_STATUS_CLEAR = 4
GAME_CLEAR_STATUS_HARD_CLEAR = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR = 6
GAME_CLEAR_STATUS_FULL_COMBO = 7
GAME_CLEAR_STATUS_NO_PLAY: Final[int] = 0
GAME_CLEAR_STATUS_FAILED: Final[int] = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR: Final[int] = 2
GAME_CLEAR_STATUS_EASY_CLEAR: Final[int] = 3
GAME_CLEAR_STATUS_CLEAR: Final[int] = 4
GAME_CLEAR_STATUS_HARD_CLEAR: Final[int] = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR: Final[int] = 6
GAME_CLEAR_STATUS_FULL_COMBO: Final[int] = 7
GAME_GHOST_TYPE_RIVAL = 1
GAME_GHOST_TYPE_GLOBAL_TOP = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE = 3
GAME_GHOST_TYPE_LOCAL_TOP = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE = 5
GAME_GHOST_TYPE_DAN_TOP = 6
GAME_GHOST_TYPE_DAN_AVERAGE = 7
GAME_GHOST_TYPE_RIVAL_TOP = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE = 9
GAME_GHOST_TYPE_RIVAL: Final[int] = 1
GAME_GHOST_TYPE_GLOBAL_TOP: Final[int] = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE: Final[int] = 3
GAME_GHOST_TYPE_LOCAL_TOP: Final[int] = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE: Final[int] = 5
GAME_GHOST_TYPE_DAN_TOP: Final[int] = 6
GAME_GHOST_TYPE_DAN_AVERAGE: Final[int] = 7
GAME_GHOST_TYPE_RIVAL_TOP: Final[int] = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE: Final[int] = 9
GAME_GHOST_LENGTH = 64
GAME_GHOST_LENGTH: Final[int] = 64
GAME_SP_DAN_RANK_7_KYU = 0
GAME_SP_DAN_RANK_6_KYU = 1
GAME_SP_DAN_RANK_5_KYU = 2
GAME_SP_DAN_RANK_4_KYU = 3
GAME_SP_DAN_RANK_3_KYU = 4
GAME_SP_DAN_RANK_2_KYU = 5
GAME_SP_DAN_RANK_1_KYU = 6
GAME_SP_DAN_RANK_1_DAN = 7
GAME_SP_DAN_RANK_2_DAN = 8
GAME_SP_DAN_RANK_3_DAN = 9
GAME_SP_DAN_RANK_4_DAN = 10
GAME_SP_DAN_RANK_5_DAN = 11
GAME_SP_DAN_RANK_6_DAN = 12
GAME_SP_DAN_RANK_7_DAN = 13
GAME_SP_DAN_RANK_8_DAN = 14
GAME_SP_DAN_RANK_9_DAN = 15
GAME_SP_DAN_RANK_10_DAN = 16
GAME_SP_DAN_RANK_KAIDEN = 17
GAME_SP_DAN_RANK_7_KYU: Final[int] = 0
GAME_SP_DAN_RANK_6_KYU: Final[int] = 1
GAME_SP_DAN_RANK_5_KYU: Final[int] = 2
GAME_SP_DAN_RANK_4_KYU: Final[int] = 3
GAME_SP_DAN_RANK_3_KYU: Final[int] = 4
GAME_SP_DAN_RANK_2_KYU: Final[int] = 5
GAME_SP_DAN_RANK_1_KYU: Final[int] = 6
GAME_SP_DAN_RANK_1_DAN: Final[int] = 7
GAME_SP_DAN_RANK_2_DAN: Final[int] = 8
GAME_SP_DAN_RANK_3_DAN: Final[int] = 9
GAME_SP_DAN_RANK_4_DAN: Final[int] = 10
GAME_SP_DAN_RANK_5_DAN: Final[int] = 11
GAME_SP_DAN_RANK_6_DAN: Final[int] = 12
GAME_SP_DAN_RANK_7_DAN: Final[int] = 13
GAME_SP_DAN_RANK_8_DAN: Final[int] = 14
GAME_SP_DAN_RANK_9_DAN: Final[int] = 15
GAME_SP_DAN_RANK_10_DAN: Final[int] = 16
GAME_SP_DAN_RANK_KAIDEN: Final[int] = 17
GAME_DP_DAN_RANK_5_KYU = 0
GAME_DP_DAN_RANK_4_KYU = 1
GAME_DP_DAN_RANK_3_KYU = 2
GAME_DP_DAN_RANK_2_KYU = 3
GAME_DP_DAN_RANK_1_KYU = 4
GAME_DP_DAN_RANK_1_DAN = 5
GAME_DP_DAN_RANK_2_DAN = 6
GAME_DP_DAN_RANK_3_DAN = 7
GAME_DP_DAN_RANK_4_DAN = 8
GAME_DP_DAN_RANK_5_DAN = 9
GAME_DP_DAN_RANK_6_DAN = 10
GAME_DP_DAN_RANK_7_DAN = 11
GAME_DP_DAN_RANK_8_DAN = 12
GAME_DP_DAN_RANK_9_DAN = 13
GAME_DP_DAN_RANK_10_DAN = 14
GAME_DP_DAN_RANK_KAIDEN = 15
GAME_DP_DAN_RANK_5_KYU: Final[int] = 0
GAME_DP_DAN_RANK_4_KYU: Final[int] = 1
GAME_DP_DAN_RANK_3_KYU: Final[int] = 2
GAME_DP_DAN_RANK_2_KYU: Final[int] = 3
GAME_DP_DAN_RANK_1_KYU: Final[int] = 4
GAME_DP_DAN_RANK_1_DAN: Final[int] = 5
GAME_DP_DAN_RANK_2_DAN: Final[int] = 6
GAME_DP_DAN_RANK_3_DAN: Final[int] = 7
GAME_DP_DAN_RANK_4_DAN: Final[int] = 8
GAME_DP_DAN_RANK_5_DAN: Final[int] = 9
GAME_DP_DAN_RANK_6_DAN: Final[int] = 10
GAME_DP_DAN_RANK_7_DAN: Final[int] = 11
GAME_DP_DAN_RANK_8_DAN: Final[int] = 12
GAME_DP_DAN_RANK_9_DAN: Final[int] = 13
GAME_DP_DAN_RANK_10_DAN: Final[int] = 14
GAME_DP_DAN_RANK_KAIDEN: Final[int] = 15
FAVORITE_LIST_LENGTH = 20
FAVORITE_LIST_LENGTH: Final[int] = 20
def previous_version(self) -> Optional[IIDXBase]:
return IIDXTricoro(self.data, self.config, self.model)
@ -1467,7 +1467,7 @@ class IIDXSpada(IIDXBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Track play counts

View File

@ -7,14 +7,14 @@ from bemani.common import VersionConstants
class IIDX1stStyle(IIDXBase):
name = 'Beatmania IIDX 1st style & substream'
version = VersionConstants.IIDX
name: str = 'Beatmania IIDX 1st style & substream'
version: int = VersionConstants.IIDX
class IIDX2ndStyle(IIDXBase):
name = 'Beatmania IIDX 2nd style'
version = VersionConstants.IIDX_2ND_STYLE
name: str = 'Beatmania IIDX 2nd style'
version: int = VersionConstants.IIDX_2ND_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX1stStyle(self.data, self.config, self.model)
@ -22,8 +22,8 @@ class IIDX2ndStyle(IIDXBase):
class IIDX3rdStyle(IIDXBase):
name = 'Beatmania IIDX 3rd style'
version = VersionConstants.IIDX_3RD_STYLE
name: str = 'Beatmania IIDX 3rd style'
version: int = VersionConstants.IIDX_3RD_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX2ndStyle(self.data, self.config, self.model)
@ -31,8 +31,8 @@ class IIDX3rdStyle(IIDXBase):
class IIDX4thStyle(IIDXBase):
name = 'Beatmania IIDX 4th style'
version = VersionConstants.IIDX_4TH_STYLE
name: str = 'Beatmania IIDX 4th style'
version: int = VersionConstants.IIDX_4TH_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX3rdStyle(self.data, self.config, self.model)
@ -40,8 +40,8 @@ class IIDX4thStyle(IIDXBase):
class IIDX5thStyle(IIDXBase):
name = 'Beatmania IIDX 5th style'
version = VersionConstants.IIDX_5TH_STYLE
name: str = 'Beatmania IIDX 5th style'
version: int = VersionConstants.IIDX_5TH_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX4thStyle(self.data, self.config, self.model)
@ -49,8 +49,8 @@ class IIDX5thStyle(IIDXBase):
class IIDX6thStyle(IIDXBase):
name = 'Beatmania IIDX 6th style'
version = VersionConstants.IIDX_6TH_STYLE
name: str = 'Beatmania IIDX 6th style'
version: int = VersionConstants.IIDX_6TH_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX5thStyle(self.data, self.config, self.model)
@ -58,8 +58,8 @@ class IIDX6thStyle(IIDXBase):
class IIDX7thStyle(IIDXBase):
name = 'Beatmania IIDX 7th style'
version = VersionConstants.IIDX_7TH_STYLE
name: str = 'Beatmania IIDX 7th style'
version: int = VersionConstants.IIDX_7TH_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX6thStyle(self.data, self.config, self.model)
@ -67,8 +67,8 @@ class IIDX7thStyle(IIDXBase):
class IIDX8thStyle(IIDXBase):
name = 'Beatmania IIDX 8th style'
version = VersionConstants.IIDX_8TH_STYLE
name: str = 'Beatmania IIDX 8th style'
version: int = VersionConstants.IIDX_8TH_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX7thStyle(self.data, self.config, self.model)
@ -76,8 +76,8 @@ class IIDX8thStyle(IIDXBase):
class IIDX9thStyle(IIDXBase):
name = 'Beatmania IIDX 9th style'
version = VersionConstants.IIDX_9TH_STYLE
name: str = 'Beatmania IIDX 9th style'
version: int = VersionConstants.IIDX_9TH_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX8thStyle(self.data, self.config, self.model)
@ -85,8 +85,8 @@ class IIDX9thStyle(IIDXBase):
class IIDX10thStyle(IIDXBase):
name = 'Beatmania IIDX 10th style'
version = VersionConstants.IIDX_10TH_STYLE
name: str = 'Beatmania IIDX 10th style'
version: int = VersionConstants.IIDX_10TH_STYLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDX9thStyle(self.data, self.config, self.model)
@ -94,8 +94,8 @@ class IIDX10thStyle(IIDXBase):
class IIDXRed(IIDXBase):
name = 'Beatmania IIDX RED'
version = VersionConstants.IIDX_RED
name: str = 'Beatmania IIDX RED'
version: int = VersionConstants.IIDX_RED
def previous_version(self) -> Optional[IIDXBase]:
return IIDX10thStyle(self.data, self.config, self.model)
@ -103,8 +103,8 @@ class IIDXRed(IIDXBase):
class IIDXHappySky(IIDXBase):
name = 'Beatmania IIDX HAPPY SKY'
version = VersionConstants.IIDX_HAPPY_SKY
name: str = 'Beatmania IIDX HAPPY SKY'
version: int = VersionConstants.IIDX_HAPPY_SKY
def previous_version(self) -> Optional[IIDXBase]:
return IIDXRed(self.data, self.config, self.model)
@ -112,8 +112,8 @@ class IIDXHappySky(IIDXBase):
class IIDXDistorted(IIDXBase):
name = 'Beatmania IIDX DistorteD'
version = VersionConstants.IIDX_DISTORTED
name: str = 'Beatmania IIDX DistorteD'
version: int = VersionConstants.IIDX_DISTORTED
def previous_version(self) -> Optional[IIDXBase]:
return IIDXHappySky(self.data, self.config, self.model)
@ -121,8 +121,8 @@ class IIDXDistorted(IIDXBase):
class IIDXGold(IIDXBase):
name = 'Beatmania IIDX GOLD'
version = VersionConstants.IIDX_GOLD
name: str = 'Beatmania IIDX GOLD'
version: int = VersionConstants.IIDX_GOLD
def previous_version(self) -> Optional[IIDXBase]:
return IIDXDistorted(self.data, self.config, self.model)
@ -130,8 +130,8 @@ class IIDXGold(IIDXBase):
class IIDXDJTroopers(IIDXBase):
name = 'Beatmania IIDX DJ TROOPERS'
version = VersionConstants.IIDX_DJ_TROOPERS
name: str = 'Beatmania IIDX DJ TROOPERS'
version: int = VersionConstants.IIDX_DJ_TROOPERS
def previous_version(self) -> Optional[IIDXBase]:
return IIDXGold(self.data, self.config, self.model)
@ -139,8 +139,8 @@ class IIDXDJTroopers(IIDXBase):
class IIDXEmpress(IIDXBase):
name = 'Beatmania IIDX EMPRESS'
version = VersionConstants.IIDX_EMPRESS
name: str = 'Beatmania IIDX EMPRESS'
version: int = VersionConstants.IIDX_EMPRESS
def previous_version(self) -> Optional[IIDXBase]:
return IIDXDJTroopers(self.data, self.config, self.model)
@ -148,8 +148,8 @@ class IIDXEmpress(IIDXBase):
class IIDXSirius(IIDXBase):
name = 'Beatmania IIDX SIRIUS'
version = VersionConstants.IIDX_SIRIUS
name: str = 'Beatmania IIDX SIRIUS'
version: int = VersionConstants.IIDX_SIRIUS
def previous_version(self) -> Optional[IIDXBase]:
return IIDXEmpress(self.data, self.config, self.model)
@ -157,8 +157,8 @@ class IIDXSirius(IIDXBase):
class IIDXResortAnthem(IIDXBase):
name = 'Beatmania IIDX Resort Anthem'
version = VersionConstants.IIDX_RESORT_ANTHEM
name: str = 'Beatmania IIDX Resort Anthem'
version: int = VersionConstants.IIDX_RESORT_ANTHEM
def previous_version(self) -> Optional[IIDXBase]:
return IIDXSirius(self.data, self.config, self.model)
@ -166,8 +166,8 @@ class IIDXResortAnthem(IIDXBase):
class IIDXLincle(IIDXBase):
name = 'Beatmania IIDX Lincle'
version = VersionConstants.IIDX_LINCLE
name: str = 'Beatmania IIDX Lincle'
version: int = VersionConstants.IIDX_LINCLE
def previous_version(self) -> Optional[IIDXBase]:
return IIDXResortAnthem(self.data, self.config, self.model)

View File

@ -1,7 +1,7 @@
# vim: set fileencoding=utf-8
import copy
import random
from typing import Optional, Dict, List, Tuple, Any
from typing_extensions import Final
from bemani.backend.iidx.base import IIDXBase
from bemani.backend.iidx.stubs import IIDXLincle
@ -13,73 +13,73 @@ from bemani.protocol import Node
class IIDXTricoro(IIDXBase):
name = 'Beatmania IIDX Tricoro'
version = VersionConstants.IIDX_TRICORO
name: str = 'Beatmania IIDX Tricoro'
version: int = VersionConstants.IIDX_TRICORO
GAME_CLTYPE_SINGLE = 0
GAME_CLTYPE_DOUBLE = 1
GAME_CLTYPE_SINGLE: Final[int] = 0
GAME_CLTYPE_DOUBLE: Final[int] = 1
DAN_STAGES_SINGLE = 4
DAN_STAGES_DOUBLE = 3
DAN_STAGES_SINGLE: Final[int] = 4
DAN_STAGES_DOUBLE: Final[int] = 3
GAME_CLEAR_STATUS_NO_PLAY = 0
GAME_CLEAR_STATUS_FAILED = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR = 2
GAME_CLEAR_STATUS_EASY_CLEAR = 3
GAME_CLEAR_STATUS_CLEAR = 4
GAME_CLEAR_STATUS_HARD_CLEAR = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR = 6
GAME_CLEAR_STATUS_FULL_COMBO = 7
GAME_CLEAR_STATUS_NO_PLAY: Final[int] = 0
GAME_CLEAR_STATUS_FAILED: Final[int] = 1
GAME_CLEAR_STATUS_ASSIST_CLEAR: Final[int] = 2
GAME_CLEAR_STATUS_EASY_CLEAR: Final[int] = 3
GAME_CLEAR_STATUS_CLEAR: Final[int] = 4
GAME_CLEAR_STATUS_HARD_CLEAR: Final[int] = 5
GAME_CLEAR_STATUS_EX_HARD_CLEAR: Final[int] = 6
GAME_CLEAR_STATUS_FULL_COMBO: Final[int] = 7
GAME_GHOST_TYPE_RIVAL = 1
GAME_GHOST_TYPE_GLOBAL_TOP = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE = 3
GAME_GHOST_TYPE_LOCAL_TOP = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE = 5
GAME_GHOST_TYPE_DAN_TOP = 6
GAME_GHOST_TYPE_DAN_AVERAGE = 7
GAME_GHOST_TYPE_RIVAL_TOP = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE = 9
GAME_GHOST_TYPE_RIVAL: Final[int] = 1
GAME_GHOST_TYPE_GLOBAL_TOP: Final[int] = 2
GAME_GHOST_TYPE_GLOBAL_AVERAGE: Final[int] = 3
GAME_GHOST_TYPE_LOCAL_TOP: Final[int] = 4
GAME_GHOST_TYPE_LOCAL_AVERAGE: Final[int] = 5
GAME_GHOST_TYPE_DAN_TOP: Final[int] = 6
GAME_GHOST_TYPE_DAN_AVERAGE: Final[int] = 7
GAME_GHOST_TYPE_RIVAL_TOP: Final[int] = 8
GAME_GHOST_TYPE_RIVAL_AVERAGE: Final[int] = 9
GAME_GHOST_LENGTH = 64
GAME_GHOST_LENGTH: Final[int] = 64
GAME_SP_DAN_RANK_7_KYU = 0
GAME_SP_DAN_RANK_6_KYU = 1
GAME_SP_DAN_RANK_5_KYU = 2
GAME_SP_DAN_RANK_4_KYU = 3
GAME_SP_DAN_RANK_3_KYU = 4
GAME_SP_DAN_RANK_2_KYU = 5
GAME_SP_DAN_RANK_1_KYU = 6
GAME_SP_DAN_RANK_1_DAN = 7
GAME_SP_DAN_RANK_2_DAN = 8
GAME_SP_DAN_RANK_3_DAN = 9
GAME_SP_DAN_RANK_4_DAN = 10
GAME_SP_DAN_RANK_5_DAN = 11
GAME_SP_DAN_RANK_6_DAN = 12
GAME_SP_DAN_RANK_7_DAN = 13
GAME_SP_DAN_RANK_8_DAN = 14
GAME_SP_DAN_RANK_9_DAN = 15
GAME_SP_DAN_RANK_10_DAN = 16
GAME_SP_DAN_RANK_KAIDEN = 17
GAME_SP_DAN_RANK_7_KYU: Final[int] = 0
GAME_SP_DAN_RANK_6_KYU: Final[int] = 1
GAME_SP_DAN_RANK_5_KYU: Final[int] = 2
GAME_SP_DAN_RANK_4_KYU: Final[int] = 3
GAME_SP_DAN_RANK_3_KYU: Final[int] = 4
GAME_SP_DAN_RANK_2_KYU: Final[int] = 5
GAME_SP_DAN_RANK_1_KYU: Final[int] = 6
GAME_SP_DAN_RANK_1_DAN: Final[int] = 7
GAME_SP_DAN_RANK_2_DAN: Final[int] = 8
GAME_SP_DAN_RANK_3_DAN: Final[int] = 9
GAME_SP_DAN_RANK_4_DAN: Final[int] = 10
GAME_SP_DAN_RANK_5_DAN: Final[int] = 11
GAME_SP_DAN_RANK_6_DAN: Final[int] = 12
GAME_SP_DAN_RANK_7_DAN: Final[int] = 13
GAME_SP_DAN_RANK_8_DAN: Final[int] = 14
GAME_SP_DAN_RANK_9_DAN: Final[int] = 15
GAME_SP_DAN_RANK_10_DAN: Final[int] = 16
GAME_SP_DAN_RANK_KAIDEN: Final[int] = 17
GAME_DP_DAN_RANK_5_KYU = 0
GAME_DP_DAN_RANK_4_KYU = 1
GAME_DP_DAN_RANK_3_KYU = 2
GAME_DP_DAN_RANK_2_KYU = 3
GAME_DP_DAN_RANK_1_KYU = 4
GAME_DP_DAN_RANK_1_DAN = 5
GAME_DP_DAN_RANK_2_DAN = 6
GAME_DP_DAN_RANK_3_DAN = 7
GAME_DP_DAN_RANK_4_DAN = 8
GAME_DP_DAN_RANK_5_DAN = 9
GAME_DP_DAN_RANK_6_DAN = 10
GAME_DP_DAN_RANK_7_DAN = 11
GAME_DP_DAN_RANK_8_DAN = 12
GAME_DP_DAN_RANK_9_DAN = 13
GAME_DP_DAN_RANK_10_DAN = 14
GAME_DP_DAN_RANK_KAIDEN = 15
GAME_DP_DAN_RANK_5_KYU: Final[int] = 0
GAME_DP_DAN_RANK_4_KYU: Final[int] = 1
GAME_DP_DAN_RANK_3_KYU: Final[int] = 2
GAME_DP_DAN_RANK_2_KYU: Final[int] = 3
GAME_DP_DAN_RANK_1_KYU: Final[int] = 4
GAME_DP_DAN_RANK_1_DAN: Final[int] = 5
GAME_DP_DAN_RANK_2_DAN: Final[int] = 6
GAME_DP_DAN_RANK_3_DAN: Final[int] = 7
GAME_DP_DAN_RANK_4_DAN: Final[int] = 8
GAME_DP_DAN_RANK_5_DAN: Final[int] = 9
GAME_DP_DAN_RANK_6_DAN: Final[int] = 10
GAME_DP_DAN_RANK_7_DAN: Final[int] = 11
GAME_DP_DAN_RANK_8_DAN: Final[int] = 12
GAME_DP_DAN_RANK_9_DAN: Final[int] = 13
GAME_DP_DAN_RANK_10_DAN: Final[int] = 14
GAME_DP_DAN_RANK_KAIDEN: Final[int] = 15
FAVORITE_LIST_LENGTH = 20
FAVORITE_LIST_LENGTH: Final[int] = 20
def previous_version(self) -> Optional[IIDXBase]:
return IIDXLincle(self.data, self.config, self.model)
@ -1259,7 +1259,7 @@ class IIDXTricoro(IIDXBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
play_stats = self.get_play_statistics(userid)
# Track play counts, DJ points and options

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Dict, List, Optional
from typing_extensions import Final
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
@ -14,27 +15,27 @@ class JubeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
profiles based on refid, creating new profiles, looking up and saving scores.
"""
game = GameConstants.JUBEAT
game: GameConstants = GameConstants.JUBEAT
GAME_FLAG_BIT_PLAYED = 0x1
GAME_FLAG_BIT_CLEARED = 0x2
GAME_FLAG_BIT_FULL_COMBO = 0x4
GAME_FLAG_BIT_EXCELLENT = 0x8
GAME_FLAG_BIT_NEARLY_FULL_COMBO = 0x10
GAME_FLAG_BIT_NEARLY_EXCELLENT = 0x20
GAME_FLAG_BIT_NO_GRAY = 0x40
GAME_FLAG_BIT_NO_YELLOW = 0x80
GAME_FLAG_BIT_PLAYED: Final[int] = 0x1
GAME_FLAG_BIT_CLEARED: Final[int] = 0x2
GAME_FLAG_BIT_FULL_COMBO: Final[int] = 0x4
GAME_FLAG_BIT_EXCELLENT: Final[int] = 0x8
GAME_FLAG_BIT_NEARLY_FULL_COMBO: Final[int] = 0x10
GAME_FLAG_BIT_NEARLY_EXCELLENT: Final[int] = 0x20
GAME_FLAG_BIT_NO_GRAY: Final[int] = 0x40
GAME_FLAG_BIT_NO_YELLOW: Final[int] = 0x80
PLAY_MEDAL_FAILED = DBConstants.JUBEAT_PLAY_MEDAL_FAILED
PLAY_MEDAL_CLEARED = DBConstants.JUBEAT_PLAY_MEDAL_CLEARED
PLAY_MEDAL_NEARLY_FULL_COMBO = DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_FULL_COMBO
PLAY_MEDAL_FULL_COMBO = DBConstants.JUBEAT_PLAY_MEDAL_FULL_COMBO
PLAY_MEDAL_NEARLY_EXCELLENT = DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_EXCELLENT
PLAY_MEDAL_EXCELLENT = DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT
PLAY_MEDAL_FAILED: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_FAILED
PLAY_MEDAL_CLEARED: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_CLEARED
PLAY_MEDAL_NEARLY_FULL_COMBO: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_FULL_COMBO
PLAY_MEDAL_FULL_COMBO: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_FULL_COMBO
PLAY_MEDAL_NEARLY_EXCELLENT: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_NEARLY_EXCELLENT
PLAY_MEDAL_EXCELLENT: Final[int] = DBConstants.JUBEAT_PLAY_MEDAL_EXCELLENT
CHART_TYPE_BASIC = 0
CHART_TYPE_ADVANCED = 1
CHART_TYPE_EXTREME = 2
CHART_TYPE_BASIC: Final[int] = 0
CHART_TYPE_ADVANCED: Final[int] = 1
CHART_TYPE_EXTREME: Final[int] = 2
def previous_version(self) -> Optional['JubeatBase']:
"""

View File

@ -1,7 +1,7 @@
# vim: set fileencoding=utf-8
import copy
import random
from typing import Any, Dict, List, Optional, Set, Tuple
from typing_extensions import Final
from bemani.backend.jubeat.base import JubeatBase
from bemani.backend.jubeat.common import (
@ -30,16 +30,16 @@ class JubeatClan(
JubeatBase,
):
name = 'Jubeat Clan'
version = VersionConstants.JUBEAT_CLAN
name: str = 'Jubeat Clan'
version: int = VersionConstants.JUBEAT_CLAN
JBOX_EMBLEM_NORMAL = 1
JBOX_EMBLEM_PREMIUM = 2
JBOX_EMBLEM_NORMAL: Final[int] = 1
JBOX_EMBLEM_PREMIUM: Final[int] = 2
EVENT_STATUS_OPEN = 0x1
EVENT_STATUS_COMPLETE = 0x2
EVENT_STATUS_OPEN: Final[int] = 0x1
EVENT_STATUS_COMPLETE: Final[int] = 0x2
EVENTS = {
EVENTS: Dict[int, Dict[str, bool]] = {
5: {
'enabled': False,
},
@ -60,25 +60,25 @@ class JubeatClan(
},
}
FIVE_PLAYS_UNLOCK_EVENT_SONG_IDS = set(range(80000301, 80000348))
FIVE_PLAYS_UNLOCK_EVENT_SONG_IDS: Set[int] = set(range(80000301, 80000348))
COURSE_STATUS_SEEN = 0x01
COURSE_STATUS_PLAYED = 0x02
COURSE_STATUS_CLEARED = 0x04
COURSE_STATUS_SEEN: Final[int] = 0x01
COURSE_STATUS_PLAYED: Final[int] = 0x02
COURSE_STATUS_CLEARED: Final[int] = 0x04
COURSE_TYPE_PERMANENT = 1
COURSE_TYPE_TIME_BASED = 2
COURSE_TYPE_PERMANENT: Final[int] = 1
COURSE_TYPE_TIME_BASED: Final[int] = 2
COURSE_CLEAR_SCORE = 1
COURSE_CLEAR_COMBINED_SCORE = 2
COURSE_CLEAR_HAZARD = 3
COURSE_CLEAR_SCORE: Final[int] = 1
COURSE_CLEAR_COMBINED_SCORE: Final[int] = 2
COURSE_CLEAR_HAZARD: Final[int] = 3
COURSE_HAZARD_EXC1 = 1
COURSE_HAZARD_EXC2 = 2
COURSE_HAZARD_EXC3 = 3
COURSE_HAZARD_FC1 = 4
COURSE_HAZARD_FC2 = 5
COURSE_HAZARD_FC3 = 6
COURSE_HAZARD_EXC1: Final[int] = 1
COURSE_HAZARD_EXC2: Final[int] = 2
COURSE_HAZARD_EXC3: Final[int] = 3
COURSE_HAZARD_FC1: Final[int] = 4
COURSE_HAZARD_FC2: Final[int] = 5
COURSE_HAZARD_FC3: Final[int] = 6
def previous_version(self) -> Optional[JubeatBase]:
return JubeatQubell(self.data, self.config, self.model)
@ -1449,7 +1449,7 @@ class JubeatClan(
for chart in [0, 1, 2]:
entry = achievement.data.get_dict(str(chart))
if entry.get_int("value") >= bestentry.get_int("value"):
bestentry = copy.deepcopy(entry)
bestentry = entry.clone()
bestentry.replace_int("songid", achievement.id)
bestentry.replace_int("chart", chart)
jubeat_entries.append(bestentry)
@ -1579,7 +1579,7 @@ class JubeatClan(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
data = request.child('data')
# Grab system information

View File

@ -1,5 +1,6 @@
# 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
@ -7,14 +8,14 @@ from bemani.backend.jubeat.base import JubeatBase
class JubeatCourse(JubeatBase):
COURSE_RATING_FAILED = 100
COURSE_RATING_BRONZE = 200
COURSE_RATING_SILVER = 300
COURSE_RATING_GOLD = 400
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 = 100
COURSE_REQUIREMENT_FULL_COMBO = 200
COURSE_REQUIREMENT_PERFECT_PERCENT = 300
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

View File

@ -1,4 +1,4 @@
from typing import Optional
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.jubeat.stubs import (
@ -22,7 +22,7 @@ from bemani.data import Config, Data
class JubeatFactory(Factory):
MANAGED_CLASSES = [
MANAGED_CLASSES: List[Type[Base]] = [
Jubeat,
JubeatRipples,
JubeatRipplesAppend,

View File

@ -9,8 +9,8 @@ from bemani.common import VersionConstants
class JubeatFesto(JubeatBase):
name = 'Jubeat Festo'
version = VersionConstants.JUBEAT_FESTO
name: str = 'Jubeat Festo'
version: int = VersionConstants.JUBEAT_FESTO
def previous_version(self) -> Optional[JubeatBase]:
return JubeatClan(self.data, self.config, self.model)

View File

@ -1,8 +1,8 @@
# vim: set fileencoding=utf-8
import copy
import math
import random
from typing import Optional, Dict, List, Any, Set, Tuple
from typing_extensions import Final
from bemani.backend.base import Status
from bemani.backend.jubeat.common import (
@ -32,22 +32,22 @@ class JubeatProp(
JubeatBase,
):
name = 'Jubeat Prop'
version = VersionConstants.JUBEAT_PROP
name: str = 'Jubeat Prop'
version: int = VersionConstants.JUBEAT_PROP
GAME_COURSE_REQUIREMENT_SCORE = 1
GAME_COURSE_REQUIREMENT_FULL_COMBO = 2
GAME_COURSE_REQUIREMENT_PERFECT_PERCENT = 3
GAME_COURSE_REQUIREMENT_SCORE: Final[int] = 1
GAME_COURSE_REQUIREMENT_FULL_COMBO: Final[int] = 2
GAME_COURSE_REQUIREMENT_PERFECT_PERCENT: Final[int] = 3
GAME_COURSE_RATING_FAILED = 1
GAME_COURSE_RATING_BRONZE = 2
GAME_COURSE_RATING_SILVER = 3
GAME_COURSE_RATING_GOLD = 4
GAME_COURSE_RATING_FAILED: Final[int] = 1
GAME_COURSE_RATING_BRONZE: Final[int] = 2
GAME_COURSE_RATING_SILVER: Final[int] = 3
GAME_COURSE_RATING_GOLD: Final[int] = 4
JBOX_EMBLEM_NORMAL = 1
JBOX_EMBLEM_PREMIUM = 2
JBOX_EMBLEM_NORMAL: Final[int] = 1
JBOX_EMBLEM_PREMIUM: Final[int] = 2
EVENTS = {
EVENTS: Dict[int, Dict[str, bool]] = {
5: {
'enabled': False,
},
@ -1085,7 +1085,7 @@ class JubeatProp(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
data = request.child('data')
# Grab system information

View File

@ -1,7 +1,7 @@
# vim: set fileencoding=utf-8
import copy
import random
from typing import Any, Dict, List, Optional, Set, Tuple
from typing_extensions import Final
from bemani.backend.base import Status
from bemani.backend.jubeat.base import JubeatBase
@ -30,15 +30,15 @@ class JubeatQubell(
JubeatBase,
):
name = 'Jubeat Qubell'
version = VersionConstants.JUBEAT_QUBELL
name: str = 'Jubeat Qubell'
version: int = VersionConstants.JUBEAT_QUBELL
JBOX_EMBLEM_NORMAL = 1
JBOX_EMBLEM_PREMIUM = 2
JBOX_EMBLEM_NORMAL: Final[int] = 1
JBOX_EMBLEM_PREMIUM: Final[int] = 2
ENABLE_GARNET = False
ENABLE_GARNET: Final[bool] = False
EVENTS = {
EVENTS: Dict[int, Dict[str, bool]] = {
5: {
'enabled': False,
},
@ -921,7 +921,7 @@ class JubeatQubell(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
data = request.child('data')
# Grab system information

View File

@ -1,5 +1,4 @@
# vim: set fileencoding=utf-8
import copy
import random
from typing import Any, Dict, List, Optional, Tuple
@ -29,8 +28,8 @@ class JubeatSaucer(
JubeatBase,
):
name = 'Jubeat Saucer'
version = VersionConstants.JUBEAT_SAUCER
name: str = 'Jubeat Saucer'
version: int = VersionConstants.JUBEAT_SAUCER
def previous_version(self) -> Optional[JubeatBase]:
return JubeatCopiousAppend(self.data, self.config, self.model)
@ -519,7 +518,7 @@ class JubeatSaucer(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
data = request.child('data')
# Grab player information

View File

@ -1,7 +1,7 @@
# vim: set fileencoding=utf-8
import copy
import random
from typing import Any, Dict, List, Optional, Tuple
from typing_extensions import Final
from bemani.backend.base import Status
from bemani.backend.jubeat.base import JubeatBase
@ -31,17 +31,17 @@ class JubeatSaucerFulfill(
JubeatBase,
):
name = 'Jubeat Saucer Fulfill'
version = VersionConstants.JUBEAT_SAUCER_FULFILL
name: str = 'Jubeat Saucer Fulfill'
version: int = VersionConstants.JUBEAT_SAUCER_FULFILL
GAME_COURSE_REQUIREMENT_SCORE = 1
GAME_COURSE_REQUIREMENT_FULL_COMBO = 2
GAME_COURSE_REQUIREMENT_PERFECT_PERCENT = 3
GAME_COURSE_REQUIREMENT_SCORE: Final[int] = 1
GAME_COURSE_REQUIREMENT_FULL_COMBO: Final[int] = 2
GAME_COURSE_REQUIREMENT_PERFECT_PERCENT: Final[int] = 3
GAME_COURSE_RATING_FAILED = 1
GAME_COURSE_RATING_BRONZE = 2
GAME_COURSE_RATING_SILVER = 3
GAME_COURSE_RATING_GOLD = 4
GAME_COURSE_RATING_FAILED: Final[int] = 1
GAME_COURSE_RATING_BRONZE: Final[int] = 2
GAME_COURSE_RATING_SILVER: Final[int] = 3
GAME_COURSE_RATING_GOLD: Final[int] = 4
def previous_version(self) -> Optional[JubeatBase]:
return JubeatSaucer(self.data, self.config, self.model)
@ -600,7 +600,7 @@ class JubeatSaucerFulfill(
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
data = request.child('data')
# Grab player information

View File

@ -7,14 +7,14 @@ from bemani.common import VersionConstants
class Jubeat(JubeatBase):
name = 'Jubeat'
version = VersionConstants.JUBEAT
name: str = 'Jubeat'
version: int = VersionConstants.JUBEAT
class JubeatRipples(JubeatBase):
name = 'Jubeat Ripples'
version = VersionConstants.JUBEAT_RIPPLES
name: str = 'Jubeat Ripples'
version: int = VersionConstants.JUBEAT_RIPPLES
def previous_version(self) -> Optional[JubeatBase]:
return Jubeat(self.data, self.config, self.model)
@ -22,8 +22,8 @@ class JubeatRipples(JubeatBase):
class JubeatRipplesAppend(JubeatBase):
name = 'Jubeat Ripples Append'
version = VersionConstants.JUBEAT_RIPPLES_APPEND
name: str = 'Jubeat Ripples Append'
version: int = VersionConstants.JUBEAT_RIPPLES_APPEND
def previous_version(self) -> Optional[JubeatBase]:
return JubeatRipples(self.data, self.config, self.model)
@ -31,8 +31,8 @@ class JubeatRipplesAppend(JubeatBase):
class JubeatKnit(JubeatBase):
name = 'Jubeat Knit'
version = VersionConstants.JUBEAT_KNIT
name: str = 'Jubeat Knit'
version: int = VersionConstants.JUBEAT_KNIT
def previous_version(self) -> Optional[JubeatBase]:
return JubeatRipplesAppend(self.data, self.config, self.model)
@ -40,8 +40,8 @@ class JubeatKnit(JubeatBase):
class JubeatKnitAppend(JubeatBase):
name = 'Jubeat Knit Append'
version = VersionConstants.JUBEAT_KNIT_APPEND
name: str = 'Jubeat Knit Append'
version: int = VersionConstants.JUBEAT_KNIT_APPEND
def previous_version(self) -> Optional[JubeatBase]:
return JubeatKnit(self.data, self.config, self.model)
@ -49,8 +49,8 @@ class JubeatKnitAppend(JubeatBase):
class JubeatCopious(JubeatBase):
name = 'Jubeat Copious'
version = VersionConstants.JUBEAT_COPIOUS
name: str = 'Jubeat Copious'
version: int = VersionConstants.JUBEAT_COPIOUS
def previous_version(self) -> Optional[JubeatBase]:
return JubeatKnitAppend(self.data, self.config, self.model)
@ -58,8 +58,8 @@ class JubeatCopious(JubeatBase):
class JubeatCopiousAppend(JubeatBase):
name = 'Jubeat Copious Append'
version = VersionConstants.JUBEAT_COPIOUS_APPEND
name: str = 'Jubeat Copious Append'
version: int = VersionConstants.JUBEAT_COPIOUS_APPEND
def previous_version(self) -> Optional[JubeatBase]:
return JubeatCopious(self.data, self.config, self.model)

View File

@ -11,7 +11,7 @@ class MetalGearArcadeBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
Base game class for Metal Gear Arcade.
"""
game = GameConstants.MGA
game: GameConstants = GameConstants.MGA
def previous_version(self) -> Optional['MetalGearArcadeBase']:
"""

View File

@ -1,4 +1,4 @@
from typing import Optional
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.mga.mga import MetalGearArcade
@ -8,7 +8,7 @@ from bemani.data import Config, Data
class MetalGearArcadeFactory(Factory):
MANAGED_CLASSES = [
MANAGED_CLASSES: List[Type[Base]] = [
MetalGearArcade,
]

View File

@ -1,5 +1,4 @@
# vim: set fileencoding=utf-8
import copy
import base64
from typing import List
@ -15,8 +14,8 @@ class MetalGearArcade(
MetalGearArcadeBase,
):
name = "Metal Gear Arcade"
version = VersionConstants.MGA
name: str = "Metal Gear Arcade"
version: int = VersionConstants.MGA
def __update_shop_name(self, profiledata: bytes) -> None:
# Figure out the profile type
@ -150,7 +149,7 @@ class MetalGearArcade(
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile, is_new: bool) -> Profile:
# Profile save request, data values are base64 encoded.
# d is a CSV, and bin1 is binary data.
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
strdatas: List[bytes] = []
bindatas: List[bytes] = []

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Dict, Optional
from typing_extensions import Final
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
@ -13,25 +14,25 @@ class MusecaBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
Base game class for all Museca version that we support.
"""
game = GameConstants.MUSECA
game: GameConstants = GameConstants.MUSECA
CHART_TYPE_GREEN = 0
CHART_TYPE_ORANGE = 1
CHART_TYPE_RED = 2
CHART_TYPE_GREEN: Final[int] = 0
CHART_TYPE_ORANGE: Final[int] = 1
CHART_TYPE_RED: Final[int] = 2
GRADE_DEATH = DBConstants.MUSECA_GRADE_DEATH
GRADE_POOR = DBConstants.MUSECA_GRADE_POOR
GRADE_MEDIOCRE = DBConstants.MUSECA_GRADE_MEDIOCRE
GRADE_GOOD = DBConstants.MUSECA_GRADE_GOOD
GRADE_GREAT = DBConstants.MUSECA_GRADE_GREAT
GRADE_EXCELLENT = DBConstants.MUSECA_GRADE_EXCELLENT
GRADE_SUPERB = DBConstants.MUSECA_GRADE_SUPERB
GRADE_MASTERPIECE = DBConstants.MUSECA_GRADE_MASTERPIECE
GRADE_PERFECT = DBConstants.MUSECA_GRADE_PERFECT
GRADE_DEATH: Final[int] = DBConstants.MUSECA_GRADE_DEATH
GRADE_POOR: Final[int] = DBConstants.MUSECA_GRADE_POOR
GRADE_MEDIOCRE: Final[int] = DBConstants.MUSECA_GRADE_MEDIOCRE
GRADE_GOOD: Final[int] = DBConstants.MUSECA_GRADE_GOOD
GRADE_GREAT: Final[int] = DBConstants.MUSECA_GRADE_GREAT
GRADE_EXCELLENT: Final[int] = DBConstants.MUSECA_GRADE_EXCELLENT
GRADE_SUPERB: Final[int] = DBConstants.MUSECA_GRADE_SUPERB
GRADE_MASTERPIECE: Final[int] = DBConstants.MUSECA_GRADE_MASTERPIECE
GRADE_PERFECT: Final[int] = DBConstants.MUSECA_GRADE_PERFECT
CLEAR_TYPE_FAILED = DBConstants.MUSECA_CLEAR_TYPE_FAILED
CLEAR_TYPE_CLEARED = DBConstants.MUSECA_CLEAR_TYPE_CLEARED
CLEAR_TYPE_FULL_COMBO = DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO
CLEAR_TYPE_FAILED: Final[int] = DBConstants.MUSECA_CLEAR_TYPE_FAILED
CLEAR_TYPE_CLEARED: Final[int] = DBConstants.MUSECA_CLEAR_TYPE_CLEARED
CLEAR_TYPE_FULL_COMBO: Final[int] = DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO
def __init__(self, data: Data, config: Config, model: Model) -> None:
super().__init__(data, config, model)

View File

@ -1,4 +1,3 @@
from bemani.backend.museca.base import MusecaBase
from bemani.common import ID
from bemani.protocol import Node

View File

@ -1,5 +1,5 @@
import copy
from typing import Any, Dict
from typing_extensions import Final
from bemani.backend.ess import EventLogHandler
from bemani.backend.museca.base import MusecaBase
@ -29,29 +29,29 @@ class Museca1(
MusecaBase,
):
name = "MÚSECA"
version = VersionConstants.MUSECA
name: str = "MÚSECA"
version: int = VersionConstants.MUSECA
GAME_LIMITED_LOCKED = 1
GAME_LIMITED_UNLOCKABLE = 2
GAME_LIMITED_UNLOCKED = 3
GAME_LIMITED_LOCKED: Final[int] = 1
GAME_LIMITED_UNLOCKABLE: Final[int] = 2
GAME_LIMITED_UNLOCKED: Final[int] = 3
GAME_CATALOG_TYPE_SONG = 0
GAME_CATALOG_TYPE_GRAFICA = 15
GAME_CATALOG_TYPE_MISSION = 16
GAME_CATALOG_TYPE_SONG: Final[int] = 0
GAME_CATALOG_TYPE_GRAFICA: Final[int] = 15
GAME_CATALOG_TYPE_MISSION: Final[int] = 16
GAME_GRADE_DEATH = 0
GAME_GRADE_POOR = 1
GAME_GRADE_MEDIOCRE = 2
GAME_GRADE_GOOD = 3
GAME_GRADE_GREAT = 4
GAME_GRADE_EXCELLENT = 5
GAME_GRADE_SUPERB = 6
GAME_GRADE_MASTERPIECE = 7
GAME_GRADE_DEATH: Final[int] = 0
GAME_GRADE_POOR: Final[int] = 1
GAME_GRADE_MEDIOCRE: Final[int] = 2
GAME_GRADE_GOOD: Final[int] = 3
GAME_GRADE_GREAT: Final[int] = 4
GAME_GRADE_EXCELLENT: Final[int] = 5
GAME_GRADE_SUPERB: Final[int] = 6
GAME_GRADE_MASTERPIECE: Final[int] = 7
GAME_CLEAR_TYPE_FAILED = 1
GAME_CLEAR_TYPE_CLEARED = 2
GAME_CLEAR_TYPE_FULL_COMBO = 4
GAME_CLEAR_TYPE_FAILED: Final[int] = 1
GAME_CLEAR_TYPE_CLEARED: Final[int] = 2
GAME_CLEAR_TYPE_FULL_COMBO: Final[int] = 4
@classmethod
def get_settings(cls) -> Dict[str, Any]:
@ -280,7 +280,7 @@ class Museca1(
return game
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value('earned_gamecoin_packet')

View File

@ -1,5 +1,5 @@
import copy
from typing import Optional, Dict, Any
from typing_extensions import Final
from bemani.backend.ess import EventLogHandler
from bemani.backend.museca.base import MusecaBase
@ -30,30 +30,30 @@ class Museca1Plus(
MusecaBase,
):
name = "MÚSECA 1+1/2"
version = VersionConstants.MUSECA_1_PLUS
name: str = "MÚSECA 1+1/2"
version: int = VersionConstants.MUSECA_1_PLUS
GAME_LIMITED_LOCKED = 1
GAME_LIMITED_UNLOCKABLE = 2
GAME_LIMITED_UNLOCKED = 3
GAME_LIMITED_LOCKED: Final[int] = 1
GAME_LIMITED_UNLOCKABLE: Final[int] = 2
GAME_LIMITED_UNLOCKED: Final[int] = 3
GAME_CATALOG_TYPE_SONG = 0
GAME_CATALOG_TYPE_GRAFICA = 15
GAME_CATALOG_TYPE_MISSION = 16
GAME_CATALOG_TYPE_SONG: Final[int] = 0
GAME_CATALOG_TYPE_GRAFICA: Final[int] = 15
GAME_CATALOG_TYPE_MISSION: Final[int] = 16
GAME_GRADE_DEATH = 0
GAME_GRADE_POOR = 1
GAME_GRADE_MEDIOCRE = 2
GAME_GRADE_GOOD = 3
GAME_GRADE_GREAT = 4
GAME_GRADE_EXCELLENT = 5
GAME_GRADE_SUPERB = 6
GAME_GRADE_MASTERPIECE = 7
GAME_GRADE_PERFECT = 8
GAME_GRADE_DEATH: Final[int] = 0
GAME_GRADE_POOR: Final[int] = 1
GAME_GRADE_MEDIOCRE: Final[int] = 2
GAME_GRADE_GOOD: Final[int] = 3
GAME_GRADE_GREAT: Final[int] = 4
GAME_GRADE_EXCELLENT: Final[int] = 5
GAME_GRADE_SUPERB: Final[int] = 6
GAME_GRADE_MASTERPIECE: Final[int] = 7
GAME_GRADE_PERFECT: Final[int] = 8
GAME_CLEAR_TYPE_FAILED = 1
GAME_CLEAR_TYPE_CLEARED = 2
GAME_CLEAR_TYPE_FULL_COMBO = 4
GAME_CLEAR_TYPE_FAILED: Final[int] = 1
GAME_CLEAR_TYPE_CLEARED: Final[int] = 2
GAME_CLEAR_TYPE_FULL_COMBO: Final[int] = 4
def previous_version(self) -> Optional[MusecaBase]:
return Museca1(self.data, self.config, self.model)
@ -418,7 +418,7 @@ class Museca1Plus(
return game
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value('earned_gamecoin_packet')

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Dict, Optional, Sequence
from typing_extensions import Final
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
@ -15,36 +16,36 @@ class PopnMusicBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
scores.
"""
game = GameConstants.POPN_MUSIC
game: GameConstants = GameConstants.POPN_MUSIC
# Play medals, as saved into/loaded from the DB
PLAY_MEDAL_NO_PLAY = DBConstants.POPN_MUSIC_PLAY_MEDAL_NO_PLAY
PLAY_MEDAL_CIRCLE_FAILED = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FAILED
PLAY_MEDAL_DIAMOND_FAILED = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FAILED
PLAY_MEDAL_STAR_FAILED = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FAILED
PLAY_MEDAL_EASY_CLEAR = DBConstants.POPN_MUSIC_PLAY_MEDAL_EASY_CLEAR
PLAY_MEDAL_CIRCLE_CLEARED = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_CLEARED
PLAY_MEDAL_DIAMOND_CLEARED = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_CLEARED
PLAY_MEDAL_STAR_CLEARED = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_CLEARED
PLAY_MEDAL_CIRCLE_FULL_COMBO = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_FULL_COMBO
PLAY_MEDAL_DIAMOND_FULL_COMBO = DBConstants.POPN_MUSIC_PLAY_MEDAL_DIAMOND_FULL_COMBO
PLAY_MEDAL_STAR_FULL_COMBO = DBConstants.POPN_MUSIC_PLAY_MEDAL_STAR_FULL_COMBO
PLAY_MEDAL_PERFECT = DBConstants.POPN_MUSIC_PLAY_MEDAL_PERFECT
PLAY_MEDAL_NO_PLAY: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_NO_PLAY
PLAY_MEDAL_CIRCLE_FAILED: Final[int] = 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_EASY_CLEAR: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_EASY_CLEAR
PLAY_MEDAL_CIRCLE_CLEARED: Final[int] = 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_CIRCLE_FULL_COMBO: Final[int] = DBConstants.POPN_MUSIC_PLAY_MEDAL_CIRCLE_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
# Chart type, as saved into/loaded from the DB, and returned to game
CHART_TYPE_EASY = 0
CHART_TYPE_NORMAL = 1
CHART_TYPE_HYPER = 2
CHART_TYPE_EX = 3
CHART_TYPE_EASY: Final[int] = 0
CHART_TYPE_NORMAL: Final[int] = 1
CHART_TYPE_HYPER: Final[int] = 2
CHART_TYPE_EX: Final[int] = 3
# Old profile lookup type, for loading profile by ID
NEW_PROFILE_ONLY = 0
OLD_PROFILE_ONLY = 1
OLD_PROFILE_FALLTHROUGH = 2
NEW_PROFILE_ONLY: Final[int] = 0
OLD_PROFILE_ONLY: Final[int] = 1
OLD_PROFILE_FALLTHROUGH: Final[int] = 2
# Pop'n Music in particular requires non-expired profiles to do conversions
# properly.
supports_expired_profiles = False
supports_expired_profiles: bool = False
def previous_version(self) -> Optional['PopnMusicBase']:
"""

View File

@ -1,7 +1,6 @@
# vim: set fileencoding=utf-8
from abc import ABCMeta, abstractmethod
from abc import ABC, abstractmethod
import binascii
import copy
import random
from typing import Any, Dict, List, Optional, Tuple
from typing_extensions import Final
@ -12,7 +11,7 @@ from bemani.data import Data, UserID, Achievement, Link
from bemani.protocol import Node
class PopnMusicModernBase(PopnMusicBase, metaclass=ABCMeta):
class PopnMusicModernBase(PopnMusicBase, ABC):
# Chart type, as returned from the game
GAME_CHART_TYPE_EASY: Final[int] = 0
@ -1119,7 +1118,7 @@ class PopnMusicModernBase(PopnMusicBase, metaclass=ABCMeta):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
account = request.child('account')
if account is not None:

View File

@ -1,7 +1,7 @@
# vim: set fileencoding=utf-8
import binascii
import copy
from typing import Dict, List
from typing_extensions import Final
from bemani.backend.popn.base import PopnMusicBase
from bemani.backend.popn.lapistoria import PopnMusicLapistoria
@ -13,30 +13,30 @@ from bemani.protocol import Node
class PopnMusicEclale(PopnMusicBase):
name = "Pop'n Music éclale"
version = VersionConstants.POPN_MUSIC_ECLALE
name: str = "Pop'n Music éclale"
version: int = VersionConstants.POPN_MUSIC_ECLALE
# Chart type, as returned from the game
GAME_CHART_TYPE_EASY = 0
GAME_CHART_TYPE_NORMAL = 1
GAME_CHART_TYPE_HYPER = 2
GAME_CHART_TYPE_EX = 3
GAME_CHART_TYPE_EASY: Final[int] = 0
GAME_CHART_TYPE_NORMAL: Final[int] = 1
GAME_CHART_TYPE_HYPER: Final[int] = 2
GAME_CHART_TYPE_EX: Final[int] = 3
# Medal type, as returned from the game
GAME_PLAY_MEDAL_CIRCLE_FAILED = 1
GAME_PLAY_MEDAL_DIAMOND_FAILED = 2
GAME_PLAY_MEDAL_STAR_FAILED = 3
GAME_PLAY_MEDAL_EASY_CLEAR = 4
GAME_PLAY_MEDAL_CIRCLE_CLEARED = 5
GAME_PLAY_MEDAL_DIAMOND_CLEARED = 6
GAME_PLAY_MEDAL_STAR_CLEARED = 7
GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO = 8
GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO = 9
GAME_PLAY_MEDAL_STAR_FULL_COMBO = 10
GAME_PLAY_MEDAL_PERFECT = 11
GAME_PLAY_MEDAL_CIRCLE_FAILED: Final[int] = 1
GAME_PLAY_MEDAL_DIAMOND_FAILED: Final[int] = 2
GAME_PLAY_MEDAL_STAR_FAILED: Final[int] = 3
GAME_PLAY_MEDAL_EASY_CLEAR: Final[int] = 4
GAME_PLAY_MEDAL_CIRCLE_CLEARED: Final[int] = 5
GAME_PLAY_MEDAL_DIAMOND_CLEARED: Final[int] = 6
GAME_PLAY_MEDAL_STAR_CLEARED: Final[int] = 7
GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO: Final[int] = 8
GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO: Final[int] = 9
GAME_PLAY_MEDAL_STAR_FULL_COMBO: Final[int] = 10
GAME_PLAY_MEDAL_PERFECT: Final[int] = 11
# Biggest ID in the music DB
GAME_MAX_MUSIC_ID = 1550
GAME_MAX_MUSIC_ID: Final[int] = 1550
def previous_version(self) -> PopnMusicBase:
return PopnMusicLapistoria(self.data, self.config, self.model)
@ -700,7 +700,7 @@ class PopnMusicEclale(PopnMusicBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
account = request.child('account')
if account is not None:

View File

@ -1,4 +1,4 @@
from typing import Optional
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.popn.stubs import (
@ -34,7 +34,7 @@ from bemani.data import Config, Data
class PopnMusicFactory(Factory):
MANAGED_CLASSES = [
MANAGED_CLASSES: List[Type[Base]] = [
PopnMusic,
PopnMusic2,
PopnMusic3,

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Any, Dict, List
from typing_extensions import Final
from bemani.backend.popn.base import PopnMusicBase
from bemani.backend.popn.tunestreet import PopnMusicTuneStreet
@ -13,35 +13,35 @@ from bemani.protocol import Node
class PopnMusicFantasia(PopnMusicBase):
name = "Pop'n Music fantasia"
version = VersionConstants.POPN_MUSIC_FANTASIA
name: str = "Pop'n Music fantasia"
version: int = VersionConstants.POPN_MUSIC_FANTASIA
# Chart type, as returned from the game
GAME_CHART_TYPE_EASY = 2
GAME_CHART_TYPE_NORMAL = 0
GAME_CHART_TYPE_HYPER = 1
GAME_CHART_TYPE_EX = 3
GAME_CHART_TYPE_EASY: Final[int] = 2
GAME_CHART_TYPE_NORMAL: Final[int] = 0
GAME_CHART_TYPE_HYPER: Final[int] = 1
GAME_CHART_TYPE_EX: Final[int] = 3
# Chart type, as packed into a hiscore binary
GAME_CHART_TYPE_EASY_POSITION = 0
GAME_CHART_TYPE_NORMAL_POSITION = 1
GAME_CHART_TYPE_HYPER_POSITION = 2
GAME_CHART_TYPE_EX_POSITION = 3
GAME_CHART_TYPE_EASY_POSITION: Final[int] = 0
GAME_CHART_TYPE_NORMAL_POSITION: Final[int] = 1
GAME_CHART_TYPE_HYPER_POSITION: Final[int] = 2
GAME_CHART_TYPE_EX_POSITION: Final[int] = 3
# Medal type, as returned from the game
GAME_PLAY_MEDAL_CIRCLE_FAILED = 1
GAME_PLAY_MEDAL_DIAMOND_FAILED = 2
GAME_PLAY_MEDAL_STAR_FAILED = 3
GAME_PLAY_MEDAL_CIRCLE_CLEARED = 5
GAME_PLAY_MEDAL_DIAMOND_CLEARED = 6
GAME_PLAY_MEDAL_STAR_CLEARED = 7
GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO = 9
GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO = 10
GAME_PLAY_MEDAL_STAR_FULL_COMBO = 11
GAME_PLAY_MEDAL_PERFECT = 15
GAME_PLAY_MEDAL_CIRCLE_FAILED: Final[int] = 1
GAME_PLAY_MEDAL_DIAMOND_FAILED: Final[int] = 2
GAME_PLAY_MEDAL_STAR_FAILED: Final[int] = 3
GAME_PLAY_MEDAL_CIRCLE_CLEARED: Final[int] = 5
GAME_PLAY_MEDAL_DIAMOND_CLEARED: Final[int] = 6
GAME_PLAY_MEDAL_STAR_CLEARED: Final[int] = 7
GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO: Final[int] = 9
GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO: Final[int] = 10
GAME_PLAY_MEDAL_STAR_FULL_COMBO: Final[int] = 11
GAME_PLAY_MEDAL_PERFECT: Final[int] = 15
# Maximum music ID for this game
GAME_MAX_MUSIC_ID = 1150
GAME_MAX_MUSIC_ID: Final[int] = 1150
def previous_version(self) -> PopnMusicBase:
return PopnMusicTuneStreet(self.data, self.config, self.model)
@ -320,7 +320,7 @@ class PopnMusicFantasia(PopnMusicBase):
if request.child_value('is_not_gameover') == 1:
return oldprofile
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
newprofile.replace_int('option', request.child_value('option'))
newprofile.replace_int('chara', request.child_value('chara'))
newprofile.replace_int('mode', request.child_value('mode'))

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Any, Dict, List
from typing_extensions import Final
from bemani.backend.popn.base import PopnMusicBase
from bemani.backend.popn.sunnypark import PopnMusicSunnyPark
@ -13,31 +13,31 @@ from bemani.protocol import Node
class PopnMusicLapistoria(PopnMusicBase):
name = "Pop'n Music ラピストリア"
version = VersionConstants.POPN_MUSIC_LAPISTORIA
name: str = "Pop'n Music ラピストリア"
version: int = VersionConstants.POPN_MUSIC_LAPISTORIA
# Chart type, as returned from the game
GAME_CHART_TYPE_EASY = 0
GAME_CHART_TYPE_NORMAL = 1
GAME_CHART_TYPE_HYPER = 2
GAME_CHART_TYPE_EX = 3
GAME_CHART_TYPE_EASY: Final[int] = 0
GAME_CHART_TYPE_NORMAL: Final[int] = 1
GAME_CHART_TYPE_HYPER: Final[int] = 2
GAME_CHART_TYPE_EX: Final[int] = 3
# Medal type, as returned from the game
GAME_PLAY_MEDAL_NO_PLAY = 0
GAME_PLAY_MEDAL_CIRCLE_FAILED = 1
GAME_PLAY_MEDAL_DIAMOND_FAILED = 2
GAME_PLAY_MEDAL_STAR_FAILED = 3
GAME_PLAY_MEDAL_EASY_CLEAR = 4
GAME_PLAY_MEDAL_CIRCLE_CLEARED = 5
GAME_PLAY_MEDAL_DIAMOND_CLEARED = 6
GAME_PLAY_MEDAL_STAR_CLEARED = 7
GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO = 8
GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO = 9
GAME_PLAY_MEDAL_STAR_FULL_COMBO = 10
GAME_PLAY_MEDAL_PERFECT = 11
GAME_PLAY_MEDAL_NO_PLAY: Final[int] = 0
GAME_PLAY_MEDAL_CIRCLE_FAILED: Final[int] = 1
GAME_PLAY_MEDAL_DIAMOND_FAILED: Final[int] = 2
GAME_PLAY_MEDAL_STAR_FAILED: Final[int] = 3
GAME_PLAY_MEDAL_EASY_CLEAR: Final[int] = 4
GAME_PLAY_MEDAL_CIRCLE_CLEARED: Final[int] = 5
GAME_PLAY_MEDAL_DIAMOND_CLEARED: Final[int] = 6
GAME_PLAY_MEDAL_STAR_CLEARED: Final[int] = 7
GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO: Final[int] = 8
GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO: Final[int] = 9
GAME_PLAY_MEDAL_STAR_FULL_COMBO: Final[int] = 10
GAME_PLAY_MEDAL_PERFECT: Final[int] = 11
# Max valud music ID for conversions and stuff
GAME_MAX_MUSIC_ID = 1422
GAME_MAX_MUSIC_ID: Final[int] = 1422
def previous_version(self) -> PopnMusicBase:
return PopnMusicSunnyPark(self.data, self.config, self.model)
@ -766,7 +766,7 @@ class PopnMusicLapistoria(PopnMusicBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
account = request.child('account')
if account is not None:

View File

@ -9,11 +9,11 @@ from bemani.common import VersionConstants
class PopnMusicPeace(PopnMusicModernBase):
name = "Pop'n Music peace"
version = VersionConstants.POPN_MUSIC_PEACE
name: str = "Pop'n Music peace"
version: int = VersionConstants.POPN_MUSIC_PEACE
# Biggest ID in the music DB
GAME_MAX_MUSIC_ID = 1877
GAME_MAX_MUSIC_ID: int = 1877
def previous_version(self) -> PopnMusicBase:
return PopnMusicUsaNeko(self.data, self.config, self.model)

View File

@ -7,14 +7,14 @@ from bemani.common import VersionConstants
class PopnMusic(PopnMusicBase):
name = "Pop'n Music"
version = VersionConstants.POPN_MUSIC
name: str = "Pop'n Music"
version: int = VersionConstants.POPN_MUSIC
class PopnMusic2(PopnMusicBase):
name = "Pop'n Music 2"
version = VersionConstants.POPN_MUSIC_2
name: str = "Pop'n Music 2"
version: int = VersionConstants.POPN_MUSIC_2
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic(self.data, self.config, self.model)
@ -22,8 +22,8 @@ class PopnMusic2(PopnMusicBase):
class PopnMusic3(PopnMusicBase):
name = "Pop'n Music 3"
version = VersionConstants.POPN_MUSIC_3
name: str = "Pop'n Music 3"
version: int = VersionConstants.POPN_MUSIC_3
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic2(self.data, self.config, self.model)
@ -31,8 +31,8 @@ class PopnMusic3(PopnMusicBase):
class PopnMusic4(PopnMusicBase):
name = "Pop'n Music 4"
version = VersionConstants.POPN_MUSIC_4
name: str = "Pop'n Music 4"
version: int = VersionConstants.POPN_MUSIC_4
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic3(self.data, self.config, self.model)
@ -40,8 +40,8 @@ class PopnMusic4(PopnMusicBase):
class PopnMusic5(PopnMusicBase):
name = "Pop'n Music 5"
version = VersionConstants.POPN_MUSIC_5
name: str = "Pop'n Music 5"
version: int = VersionConstants.POPN_MUSIC_5
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic4(self.data, self.config, self.model)
@ -49,8 +49,8 @@ class PopnMusic5(PopnMusicBase):
class PopnMusic6(PopnMusicBase):
name = "Pop'n Music 6"
version = VersionConstants.POPN_MUSIC_6
name: str = "Pop'n Music 6"
version: int = VersionConstants.POPN_MUSIC_6
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic5(self.data, self.config, self.model)
@ -58,8 +58,8 @@ class PopnMusic6(PopnMusicBase):
class PopnMusic7(PopnMusicBase):
name = "Pop'n Music 7"
version = VersionConstants.POPN_MUSIC_7
name: str = "Pop'n Music 7"
version: int = VersionConstants.POPN_MUSIC_7
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic6(self.data, self.config, self.model)
@ -67,8 +67,8 @@ class PopnMusic7(PopnMusicBase):
class PopnMusic8(PopnMusicBase):
name = "Pop'n Music 8"
version = VersionConstants.POPN_MUSIC_8
name: str = "Pop'n Music 8"
version: int = VersionConstants.POPN_MUSIC_8
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic7(self.data, self.config, self.model)
@ -76,8 +76,8 @@ class PopnMusic8(PopnMusicBase):
class PopnMusic9(PopnMusicBase):
name = "Pop'n Music 9"
version = VersionConstants.POPN_MUSIC_9
name: str = "Pop'n Music 9"
version: int = VersionConstants.POPN_MUSIC_9
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic8(self.data, self.config, self.model)
@ -85,8 +85,8 @@ class PopnMusic9(PopnMusicBase):
class PopnMusic10(PopnMusicBase):
name = "Pop'n Music 10"
version = VersionConstants.POPN_MUSIC_10
name: str = "Pop'n Music 10"
version: int = VersionConstants.POPN_MUSIC_10
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic9(self.data, self.config, self.model)
@ -94,8 +94,8 @@ class PopnMusic10(PopnMusicBase):
class PopnMusic11(PopnMusicBase):
name = "Pop'n Music 11"
version = VersionConstants.POPN_MUSIC_11
name: str = "Pop'n Music 11"
version: int = VersionConstants.POPN_MUSIC_11
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic10(self.data, self.config, self.model)
@ -103,8 +103,8 @@ class PopnMusic11(PopnMusicBase):
class PopnMusicIroha(PopnMusicBase):
name = "Pop'n Music いろは"
version = VersionConstants.POPN_MUSIC_IROHA
name: str = "Pop'n Music いろは"
version: int = VersionConstants.POPN_MUSIC_IROHA
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusic11(self.data, self.config, self.model)
@ -112,8 +112,8 @@ class PopnMusicIroha(PopnMusicBase):
class PopnMusicCarnival(PopnMusicBase):
name = "Pop'n Music カーニバル"
version = VersionConstants.POPN_MUSIC_CARNIVAL
name: str = "Pop'n Music カーニバル"
version: int = VersionConstants.POPN_MUSIC_CARNIVAL
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusicIroha(self.data, self.config, self.model)
@ -121,8 +121,8 @@ class PopnMusicCarnival(PopnMusicBase):
class PopnMusicFever(PopnMusicBase):
name = "Pop'n Music FEVER!"
version = VersionConstants.POPN_MUSIC_FEVER
name: str = "Pop'n Music FEVER!"
version: int = VersionConstants.POPN_MUSIC_FEVER
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusicCarnival(self.data, self.config, self.model)
@ -130,8 +130,8 @@ class PopnMusicFever(PopnMusicBase):
class PopnMusicAdventure(PopnMusicBase):
name = "Pop'n Music ADVENTURE"
version = VersionConstants.POPN_MUSIC_ADVENTURE
name: str = "Pop'n Music ADVENTURE"
version: int = VersionConstants.POPN_MUSIC_ADVENTURE
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusicFever(self.data, self.config, self.model)
@ -139,8 +139,8 @@ class PopnMusicAdventure(PopnMusicBase):
class PopnMusicParty(PopnMusicBase):
name = "Pop'n Music Party♪"
version = VersionConstants.POPN_MUSIC_PARTY
name: str = "Pop'n Music Party♪"
version: int = VersionConstants.POPN_MUSIC_PARTY
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusicAdventure(self.data, self.config, self.model)
@ -148,8 +148,8 @@ class PopnMusicParty(PopnMusicBase):
class PopnMusicTheMovie(PopnMusicBase):
name = "Pop'n Music THE MOVIE"
version = VersionConstants.POPN_MUSIC_THE_MOVIE
name: str = "Pop'n Music THE MOVIE"
version: int = VersionConstants.POPN_MUSIC_THE_MOVIE
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusicParty(self.data, self.config, self.model)
@ -157,8 +157,8 @@ class PopnMusicTheMovie(PopnMusicBase):
class PopnMusicSengokuRetsuden(PopnMusicBase):
name = "Pop'n Music せんごく列伝"
version = VersionConstants.POPN_MUSIC_SENGOKU_RETSUDEN
name: str = "Pop'n Music せんごく列伝"
version: int = VersionConstants.POPN_MUSIC_SENGOKU_RETSUDEN
def previous_version(self) -> Optional[PopnMusicBase]:
return PopnMusicTheMovie(self.data, self.config, self.model)

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Any, Dict, List
from typing_extensions import Final
from bemani.backend.popn.base import PopnMusicBase
from bemani.backend.popn.fantasia import PopnMusicFantasia
@ -13,35 +13,35 @@ from bemani.protocol import Node
class PopnMusicSunnyPark(PopnMusicBase):
name = "Pop'n Music Sunny Park"
version = VersionConstants.POPN_MUSIC_SUNNY_PARK
name: str = "Pop'n Music Sunny Park"
version: int = VersionConstants.POPN_MUSIC_SUNNY_PARK
# Chart type, as returned from the game
GAME_CHART_TYPE_EASY = 0
GAME_CHART_TYPE_NORMAL = 1
GAME_CHART_TYPE_HYPER = 2
GAME_CHART_TYPE_EX = 3
GAME_CHART_TYPE_EASY: Final[int] = 0
GAME_CHART_TYPE_NORMAL: Final[int] = 1
GAME_CHART_TYPE_HYPER: Final[int] = 2
GAME_CHART_TYPE_EX: Final[int] = 3
# Chart type, as packed into a hiscore binary
GAME_CHART_TYPE_EASY_POSITION = 0
GAME_CHART_TYPE_NORMAL_POSITION = 1
GAME_CHART_TYPE_HYPER_POSITION = 2
GAME_CHART_TYPE_EX_POSITION = 3
GAME_CHART_TYPE_EASY_POSITION: Final[int] = 0
GAME_CHART_TYPE_NORMAL_POSITION: Final[int] = 1
GAME_CHART_TYPE_HYPER_POSITION: Final[int] = 2
GAME_CHART_TYPE_EX_POSITION: Final[int] = 3
# Medal type, as returned from the game
GAME_PLAY_MEDAL_CIRCLE_FAILED = 1
GAME_PLAY_MEDAL_DIAMOND_FAILED = 2
GAME_PLAY_MEDAL_STAR_FAILED = 3
GAME_PLAY_MEDAL_CIRCLE_CLEARED = 5
GAME_PLAY_MEDAL_DIAMOND_CLEARED = 6
GAME_PLAY_MEDAL_STAR_CLEARED = 7
GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO = 9
GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO = 10
GAME_PLAY_MEDAL_STAR_FULL_COMBO = 11
GAME_PLAY_MEDAL_PERFECT = 15
GAME_PLAY_MEDAL_CIRCLE_FAILED: Final[int] = 1
GAME_PLAY_MEDAL_DIAMOND_FAILED: Final[int] = 2
GAME_PLAY_MEDAL_STAR_FAILED: Final[int] = 3
GAME_PLAY_MEDAL_CIRCLE_CLEARED: Final[int] = 5
GAME_PLAY_MEDAL_DIAMOND_CLEARED: Final[int] = 6
GAME_PLAY_MEDAL_STAR_CLEARED: Final[int] = 7
GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO: Final[int] = 9
GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO: Final[int] = 10
GAME_PLAY_MEDAL_STAR_FULL_COMBO: Final[int] = 11
GAME_PLAY_MEDAL_PERFECT: Final[int] = 15
# Maximum music ID for this game
GAME_MAX_MUSIC_ID = 1350
GAME_MAX_MUSIC_ID: Final[int] = 1350
def previous_version(self) -> PopnMusicBase:
return PopnMusicFantasia(self.data, self.config, self.model)
@ -360,7 +360,7 @@ class PopnMusicSunnyPark(PopnMusicBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
newprofile.replace_int('option', request.child_value('option'))
newprofile.replace_int('chara', request.child_value('chara'))
newprofile.replace_int('mode', request.child_value('mode'))

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Dict, Any
from typing_extensions import Final
from bemani.backend.popn.base import PopnMusicBase
from bemani.backend.popn.stubs import PopnMusicSengokuRetsuden
@ -13,49 +13,49 @@ from bemani.protocol import Node
class PopnMusicTuneStreet(PopnMusicBase):
name = "Pop'n Music TUNE STREET"
version = VersionConstants.POPN_MUSIC_TUNE_STREET
name: str = "Pop'n Music TUNE STREET"
version: int = VersionConstants.POPN_MUSIC_TUNE_STREET
# Play modes, as reported by profile save from the game
GAME_PLAY_MODE_CHALLENGE = 3
GAME_PLAY_MODE_CHO_CHALLENGE = 4
GAME_PLAY_MODE_TOWN_CHO_CHALLENGE = 15
GAME_PLAY_MODE_CHALLENGE: Final[int] = 3
GAME_PLAY_MODE_CHO_CHALLENGE: Final[int] = 4
GAME_PLAY_MODE_TOWN_CHO_CHALLENGE: Final[int] = 15
# Play flags, as saved into/loaded from the DB
GAME_PLAY_FLAG_FAILED = 0
GAME_PLAY_FLAG_CLEARED = 1
GAME_PLAY_FLAG_FULL_COMBO = 2
GAME_PLAY_FLAG_PERFECT_COMBO = 3
GAME_PLAY_FLAG_FAILED: Final[int] = 0
GAME_PLAY_FLAG_CLEARED: Final[int] = 1
GAME_PLAY_FLAG_FULL_COMBO: Final[int] = 2
GAME_PLAY_FLAG_PERFECT_COMBO: Final[int] = 3
# Chart type, as reported by profile save from the game
GAME_CHART_TYPE_NORMAL = 0
GAME_CHART_TYPE_HYPER = 1
GAME_CHART_TYPE_5_BUTTON = 2
GAME_CHART_TYPE_EX = 3
GAME_CHART_TYPE_BATTLE_NORMAL = 4
GAME_CHART_TYPE_BATTLE_HYPER = 5
GAME_CHART_TYPE_ENJOY_5_BUTTON = 6
GAME_CHART_TYPE_ENJOY_9_BUTTON = 7
GAME_CHART_TYPE_NORMAL: Final[int] = 0
GAME_CHART_TYPE_HYPER: Final[int] = 1
GAME_CHART_TYPE_5_BUTTON: Final[int] = 2
GAME_CHART_TYPE_EX: Final[int] = 3
GAME_CHART_TYPE_BATTLE_NORMAL: Final[int] = 4
GAME_CHART_TYPE_BATTLE_HYPER: Final[int] = 5
GAME_CHART_TYPE_ENJOY_5_BUTTON: Final[int] = 6
GAME_CHART_TYPE_ENJOY_9_BUTTON: Final[int] = 7
# Extra chart types supported by Pop'n 19
CHART_TYPE_OLD_NORMAL = 4
CHART_TYPE_OLD_HYPER = 5
CHART_TYPE_OLD_EX = 6
CHART_TYPE_ENJOY_5_BUTTON = 7
CHART_TYPE_ENJOY_9_BUTTON = 8
CHART_TYPE_5_BUTTON = 9
CHART_TYPE_OLD_NORMAL: Final[int] = 4
CHART_TYPE_OLD_HYPER: Final[int] = 5
CHART_TYPE_OLD_EX: Final[int] = 6
CHART_TYPE_ENJOY_5_BUTTON: Final[int] = 7
CHART_TYPE_ENJOY_9_BUTTON: Final[int] = 8
CHART_TYPE_5_BUTTON: Final[int] = 9
# Chart type, as packed into a hiscore binary
GAME_CHART_TYPE_5_BUTTON_POSITION = 0
GAME_CHART_TYPE_NORMAL_POSITION = 1
GAME_CHART_TYPE_HYPER_POSITION = 2
GAME_CHART_TYPE_EX_POSITION = 3
GAME_CHART_TYPE_CHO_NORMAL_POSITION = 4
GAME_CHART_TYPE_CHO_HYPER_POSITION = 5
GAME_CHART_TYPE_CHO_EX_POSITION = 6
GAME_CHART_TYPE_5_BUTTON_POSITION: Final[int] = 0
GAME_CHART_TYPE_NORMAL_POSITION: Final[int] = 1
GAME_CHART_TYPE_HYPER_POSITION: Final[int] = 2
GAME_CHART_TYPE_EX_POSITION: Final[int] = 3
GAME_CHART_TYPE_CHO_NORMAL_POSITION: Final[int] = 4
GAME_CHART_TYPE_CHO_HYPER_POSITION: Final[int] = 5
GAME_CHART_TYPE_CHO_EX_POSITION: Final[int] = 6
# Highest song ID we can represent
GAME_MAX_MUSIC_ID = 1045
GAME_MAX_MUSIC_ID: Final[int] = 1045
def previous_version(self) -> PopnMusicBase:
return PopnMusicSengokuRetsuden(self.data, self.config, self.model)
@ -351,7 +351,7 @@ class PopnMusicTuneStreet(PopnMusicBase):
return root
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Extract the playmode, important for scores later
playmode = int(request.attribute('play_mode'))

View File

@ -9,11 +9,11 @@ from bemani.common import VersionConstants
class PopnMusicUsaNeko(PopnMusicModernBase):
name = "Pop'n Music うさぎと猫と少年の夢"
version = VersionConstants.POPN_MUSIC_USANEKO
name: str = "Pop'n Music うさぎと猫と少年の夢"
version: int = VersionConstants.POPN_MUSIC_USANEKO
# Biggest ID in the music DB
GAME_MAX_MUSIC_ID = 1704
GAME_MAX_MUSIC_ID: int = 1704
def previous_version(self) -> PopnMusicBase:
return PopnMusicEclale(self.data, self.config, self.model)

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Dict, List, Optional
from typing_extensions import Final
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
@ -13,26 +14,26 @@ class ReflecBeatBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
Base game class for all Reflec Beat version that we support.
"""
game = GameConstants.REFLEC_BEAT
game: GameConstants = GameConstants.REFLEC_BEAT
# Chart types, as stored in the DB
CHART_TYPE_BASIC = 0
CHART_TYPE_MEDIUM = 1
CHART_TYPE_HARD = 2
CHART_TYPE_SPECIAL = 3
CHART_TYPE_BASIC: Final[int] = 0
CHART_TYPE_MEDIUM: Final[int] = 1
CHART_TYPE_HARD: Final[int] = 2
CHART_TYPE_SPECIAL: Final[int] = 3
# Clear types, as saved/loaded from the DB
CLEAR_TYPE_NO_PLAY = DBConstants.REFLEC_BEAT_CLEAR_TYPE_NO_PLAY
CLEAR_TYPE_FAILED = DBConstants.REFLEC_BEAT_CLEAR_TYPE_FAILED
CLEAR_TYPE_CLEARED = DBConstants.REFLEC_BEAT_CLEAR_TYPE_CLEARED
CLEAR_TYPE_HARD_CLEARED = DBConstants.REFLEC_BEAT_CLEAR_TYPE_HARD_CLEARED
CLEAR_TYPE_S_HARD_CLEARED = DBConstants.REFLEC_BEAT_CLEAR_TYPE_S_HARD_CLEARED
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_CLEARED: Final[int] = DBConstants.REFLEC_BEAT_CLEAR_TYPE_CLEARED
CLEAR_TYPE_HARD_CLEARED: Final[int] = 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_TYPE_NONE = DBConstants.REFLEC_BEAT_COMBO_TYPE_NONE
COMBO_TYPE_ALMOST_COMBO = DBConstants.REFLEC_BEAT_COMBO_TYPE_ALMOST_COMBO
COMBO_TYPE_FULL_COMBO = DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO
COMBO_TYPE_FULL_COMBO_ALL_JUST = DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO_ALL_JUST
COMBO_TYPE_NONE: Final[int] = DBConstants.REFLEC_BEAT_COMBO_TYPE_NONE
COMBO_TYPE_ALMOST_COMBO: Final[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_ALL_JUST: Final[int] = DBConstants.REFLEC_BEAT_COMBO_TYPE_FULL_COMBO_ALL_JUST
# Return the local2 and lobby2 service so that matching will work on newer
# Reflec Beat games.

View File

@ -1,5 +1,5 @@
import copy
from typing import Optional, Dict, List, Tuple, Any
from typing_extensions import Final
from bemani.backend.reflec.base import ReflecBeatBase
from bemani.backend.reflec.limelight import ReflecBeatLimelight
@ -11,15 +11,15 @@ from bemani.protocol import Node
class ReflecBeatColette(ReflecBeatBase):
name = "REFLEC BEAT colette"
version = VersionConstants.REFLEC_BEAT_COLETTE
name: str = "REFLEC BEAT colette"
version: int = VersionConstants.REFLEC_BEAT_COLETTE
# Clear types according to the game
GAME_CLEAR_TYPE_NO_PLAY = 0
GAME_CLEAR_TYPE_FAILED = 1
GAME_CLEAR_TYPE_CLEARED = 2
GAME_CLEAR_TYPE_ALMOST_COMBO = 3
GAME_CLEAR_TYPE_FULL_COMBO = 4
GAME_CLEAR_TYPE_NO_PLAY: Final[int] = 0
GAME_CLEAR_TYPE_FAILED: Final[int] = 1
GAME_CLEAR_TYPE_CLEARED: Final[int] = 2
GAME_CLEAR_TYPE_ALMOST_COMBO: Final[int] = 3
GAME_CLEAR_TYPE_FULL_COMBO: Final[int] = 4
def previous_version(self) -> Optional[ReflecBeatBase]:
return ReflecBeatLimelight(self.data, self.config, self.model)
@ -941,7 +941,7 @@ class ReflecBeatColette(ReflecBeatBase):
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
game_config = self.get_game_config()
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
newprofile.replace_int('lid', ID.parse_machine_id(request.child_value('pdata/account/lid')))
newprofile.replace_str('name', request.child_value('pdata/base/name'))

View File

@ -1,5 +1,5 @@
import copy
from typing import Optional, Dict, Any, List, Tuple
from typing_extensions import Final
from bemani.backend.reflec.base import ReflecBeatBase
from bemani.backend.reflec.colette import ReflecBeatColette
@ -11,24 +11,24 @@ from bemani.protocol import Node
class ReflecBeatGroovin(ReflecBeatBase):
name = "REFLEC BEAT groovin'!!"
version = VersionConstants.REFLEC_BEAT_GROOVIN
name: str = "REFLEC BEAT groovin'!!"
version: int = VersionConstants.REFLEC_BEAT_GROOVIN
# Clear types according to the game
GAME_CLEAR_TYPE_NO_PLAY = 0
GAME_CLEAR_TYPE_EARLY_FAILED = 1
GAME_CLEAR_TYPE_FAILED = 2
GAME_CLEAR_TYPE_CLEARED = 9
GAME_CLEAR_TYPE_HARD_CLEARED = 10
GAME_CLEAR_TYPE_S_HARD_CLEARED = 11
GAME_CLEAR_TYPE_NO_PLAY: Final[int] = 0
GAME_CLEAR_TYPE_EARLY_FAILED: Final[int] = 1
GAME_CLEAR_TYPE_FAILED: Final[int] = 2
GAME_CLEAR_TYPE_CLEARED: Final[int] = 9
GAME_CLEAR_TYPE_HARD_CLEARED: Final[int] = 10
GAME_CLEAR_TYPE_S_HARD_CLEARED: Final[int] = 11
# Combo types according to the game (actually a bitmask, where bit 0 is
# full combo status, and bit 2 is just reflec status). But we don't support
# saving just reflec without full combo, so we downgrade it.
GAME_COMBO_TYPE_NONE = 0
GAME_COMBO_TYPE_ALL_JUST = 2
GAME_COMBO_TYPE_FULL_COMBO = 1
GAME_COMBO_TYPE_FULL_COMBO_ALL_JUST = 3
GAME_COMBO_TYPE_NONE: Final[int] = 0
GAME_COMBO_TYPE_ALL_JUST: Final[int] = 2
GAME_COMBO_TYPE_FULL_COMBO: Final[int] = 1
GAME_COMBO_TYPE_FULL_COMBO_ALL_JUST: Final[int] = 3
def previous_version(self) -> Optional[ReflecBeatBase]:
return ReflecBeatColette(self.data, self.config, self.model)
@ -1207,7 +1207,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
game_config = self.get_game_config()
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Save base player profile info
newprofile.replace_int('lid', ID.parse_machine_id(request.child_value('pdata/account/lid')))

View File

@ -1,5 +1,5 @@
import copy
from typing import Optional, Dict, Any, Tuple
from typing_extensions import Final
from bemani.backend.reflec.base import ReflecBeatBase
from bemani.backend.reflec.reflecbeat import ReflecBeat
@ -11,14 +11,14 @@ from bemani.protocol import Node
class ReflecBeatLimelight(ReflecBeatBase):
name = "REFLEC BEAT limelight"
version = VersionConstants.REFLEC_BEAT_LIMELIGHT
name: str = "REFLEC BEAT limelight"
version: int = VersionConstants.REFLEC_BEAT_LIMELIGHT
# Clear types according to the game
GAME_CLEAR_TYPE_NO_PLAY = 0
GAME_CLEAR_TYPE_FAILED = 2
GAME_CLEAR_TYPE_CLEARED = 3
GAME_CLEAR_TYPE_FULL_COMBO = 4
GAME_CLEAR_TYPE_NO_PLAY: Final[int] = 0
GAME_CLEAR_TYPE_FAILED: Final[int] = 2
GAME_CLEAR_TYPE_CLEARED: Final[int] = 3
GAME_CLEAR_TYPE_FULL_COMBO: Final[int] = 4
def previous_version(self) -> Optional[ReflecBeatBase]:
return ReflecBeat(self.data, self.config, self.model)
@ -738,7 +738,7 @@ class ReflecBeatLimelight(ReflecBeatBase):
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
game_config = self.get_game_config()
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
newprofile.replace_int('lid', ID.parse_machine_id(request.child_value('lid')))
newprofile.replace_str('name', request.child_value('pdata/base/name'))

View File

@ -1,5 +1,5 @@
import copy
from typing import Any, Dict, Tuple
from typing_extensions import Final
from bemani.backend.reflec.base import ReflecBeatBase
@ -10,13 +10,13 @@ from bemani.protocol import Node
class ReflecBeat(ReflecBeatBase):
name = "REFLEC BEAT"
version = VersionConstants.REFLEC_BEAT
name: str = "REFLEC BEAT"
version: int = VersionConstants.REFLEC_BEAT
# Clear types according to the game
GAME_CLEAR_TYPE_NO_PLAY = 0
GAME_CLEAR_TYPE_PLAYED = 2
GAME_CLEAR_TYPE_FULL_COMBO = 3
GAME_CLEAR_TYPE_NO_PLAY: Final[int] = 0
GAME_CLEAR_TYPE_PLAYED: Final[int] = 2
GAME_CLEAR_TYPE_FULL_COMBO: Final[int] = 3
@classmethod
def get_settings(cls) -> Dict[str, Any]:
@ -399,7 +399,7 @@ class ReflecBeat(ReflecBeatBase):
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
game_config = self.get_game_config()
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
newprofile.replace_int('lid', ID.parse_machine_id(request.child_value('lid')))
newprofile.replace_str('name', request.child_value('pdata/base/name'))

View File

@ -1,4 +1,3 @@
import copy
from typing import Any, Dict, List, Optional
from bemani.backend.reflec.base import ReflecBeatBase
@ -12,8 +11,8 @@ from bemani.protocol import Node
class ReflecBeatVolzza(ReflecBeatVolzzaBase):
name = "REFLEC BEAT VOLZZA"
version = VersionConstants.REFLEC_BEAT_VOLZZA
name: str = "REFLEC BEAT VOLZZA"
version: int = VersionConstants.REFLEC_BEAT_VOLZZA
def previous_version(self) -> Optional[ReflecBeatBase]:
return ReflecBeatGroovin(self.data, self.config, self.model)
@ -544,7 +543,7 @@ class ReflecBeatVolzza(ReflecBeatVolzzaBase):
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
game_config = self.get_game_config()
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Save base player profile info
newprofile.replace_int('lid', ID.parse_machine_id(request.child_value('pdata/account/lid')))

View File

@ -1,4 +1,3 @@
import copy
from typing import Any, Dict, List, Optional
from bemani.backend.reflec.base import ReflecBeatBase
@ -12,8 +11,8 @@ from bemani.protocol import Node
class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
name = "REFLEC BEAT VOLZZA 2"
version = VersionConstants.REFLEC_BEAT_VOLZZA_2
name: str = "REFLEC BEAT VOLZZA 2"
version: int = VersionConstants.REFLEC_BEAT_VOLZZA_2
def previous_version(self) -> Optional[ReflecBeatBase]:
return ReflecBeatVolzza(self.data, self.config, self.model)
@ -655,7 +654,7 @@ class ReflecBeatVolzza2(ReflecBeatVolzzaBase):
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
game_config = self.get_game_config()
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Save base player profile info
newprofile.replace_int('lid', ID.parse_machine_id(request.child_value('pdata/account/lid')))

View File

@ -1,4 +1,5 @@
from typing import Dict, List, Tuple
from typing_extensions import Final
from bemani.backend.reflec.base import ReflecBeatBase
@ -10,20 +11,20 @@ from bemani.protocol import Node
class ReflecBeatVolzzaBase(ReflecBeatBase):
# Clear types according to the game
GAME_CLEAR_TYPE_NO_PLAY = 0
GAME_CLEAR_TYPE_EARLY_FAILED = 1
GAME_CLEAR_TYPE_FAILED = 2
GAME_CLEAR_TYPE_CLEARED = 9
GAME_CLEAR_TYPE_HARD_CLEARED = 10
GAME_CLEAR_TYPE_S_HARD_CLEARED = 11
GAME_CLEAR_TYPE_NO_PLAY: Final[int] = 0
GAME_CLEAR_TYPE_EARLY_FAILED: Final[int] = 1
GAME_CLEAR_TYPE_FAILED: Final[int] = 2
GAME_CLEAR_TYPE_CLEARED: Final[int] = 9
GAME_CLEAR_TYPE_HARD_CLEARED: Final[int] = 10
GAME_CLEAR_TYPE_S_HARD_CLEARED: Final[int] = 11
# Combo types according to the game (actually a bitmask, where bit 0 is
# full combo status, and bit 2 is just reflec status). But we don't support
# saving just reflec without full combo, so we downgrade it.
GAME_COMBO_TYPE_NONE = 0
GAME_COMBO_TYPE_ALL_JUST = 2
GAME_COMBO_TYPE_FULL_COMBO = 1
GAME_COMBO_TYPE_FULL_COMBO_ALL_JUST = 3
GAME_COMBO_TYPE_NONE: Final[int] = 0
GAME_COMBO_TYPE_ALL_JUST: Final[int] = 2
GAME_COMBO_TYPE_FULL_COMBO: Final[int] = 1
GAME_COMBO_TYPE_FULL_COMBO_ALL_JUST: Final[int] = 3
def _db_to_game_clear_type(self, db_status: int) -> int:
return {

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Dict, Optional
from typing_extensions import Final
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
@ -13,32 +14,32 @@ class SoundVoltexBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
Base game class for all Sound Voltex version that we support.
"""
game = GameConstants.SDVX
game: GameConstants = GameConstants.SDVX
CLEAR_TYPE_NO_PLAY = DBConstants.SDVX_CLEAR_TYPE_NO_PLAY
CLEAR_TYPE_FAILED = DBConstants.SDVX_CLEAR_TYPE_FAILED
CLEAR_TYPE_CLEAR = DBConstants.SDVX_CLEAR_TYPE_CLEAR
CLEAR_TYPE_HARD_CLEAR = DBConstants.SDVX_CLEAR_TYPE_HARD_CLEAR
CLEAR_TYPE_ULTIMATE_CHAIN = DBConstants.SDVX_CLEAR_TYPE_ULTIMATE_CHAIN
CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN = DBConstants.SDVX_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN
CLEAR_TYPE_NO_PLAY: Final[int] = DBConstants.SDVX_CLEAR_TYPE_NO_PLAY
CLEAR_TYPE_FAILED: Final[int] = DBConstants.SDVX_CLEAR_TYPE_FAILED
CLEAR_TYPE_CLEAR: Final[int] = DBConstants.SDVX_CLEAR_TYPE_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_PERFECT_ULTIMATE_CHAIN: Final[int] = DBConstants.SDVX_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN
GRADE_NO_PLAY = DBConstants.SDVX_GRADE_NO_PLAY
GRADE_D = DBConstants.SDVX_GRADE_D
GRADE_C = DBConstants.SDVX_GRADE_C
GRADE_B = DBConstants.SDVX_GRADE_B
GRADE_A = DBConstants.SDVX_GRADE_A
GRADE_A_PLUS = DBConstants.SDVX_GRADE_A_PLUS
GRADE_AA = DBConstants.SDVX_GRADE_AA
GRADE_AA_PLUS = DBConstants.SDVX_GRADE_AA_PLUS
GRADE_AAA = DBConstants.SDVX_GRADE_AAA
GRADE_AAA_PLUS = DBConstants.SDVX_GRADE_AAA_PLUS
GRADE_S = DBConstants.SDVX_GRADE_S
GRADE_NO_PLAY: Final[int] = DBConstants.SDVX_GRADE_NO_PLAY
GRADE_D: Final[int] = DBConstants.SDVX_GRADE_D
GRADE_C: Final[int] = DBConstants.SDVX_GRADE_C
GRADE_B: Final[int] = DBConstants.SDVX_GRADE_B
GRADE_A: Final[int] = DBConstants.SDVX_GRADE_A
GRADE_A_PLUS: Final[int] = DBConstants.SDVX_GRADE_A_PLUS
GRADE_AA: Final[int] = DBConstants.SDVX_GRADE_AA
GRADE_AA_PLUS: Final[int] = DBConstants.SDVX_GRADE_AA_PLUS
GRADE_AAA: Final[int] = DBConstants.SDVX_GRADE_AAA
GRADE_AAA_PLUS: Final[int] = DBConstants.SDVX_GRADE_AAA_PLUS
GRADE_S: Final[int] = DBConstants.SDVX_GRADE_S
CHART_TYPE_NOVICE = 0
CHART_TYPE_ADVANCED = 1
CHART_TYPE_EXHAUST = 2
CHART_TYPE_INFINITE = 3
CHART_TYPE_MAXIMUM = 4
CHART_TYPE_NOVICE: Final[int] = 0
CHART_TYPE_ADVANCED: Final[int] = 1
CHART_TYPE_EXHAUST: Final[int] = 2
CHART_TYPE_INFINITE: Final[int] = 3
CHART_TYPE_MAXIMUM: Final[int] = 4
def previous_version(self) -> Optional['SoundVoltexBase']:
"""

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Any, Dict, Optional, Tuple
from typing_extensions import Final
from bemani.backend.ess import EventLogHandler
from bemani.backend.sdvx.base import SoundVoltexBase
@ -14,27 +14,27 @@ class SoundVoltexBooth(
SoundVoltexBase,
):
name = 'SOUND VOLTEX BOOTH'
version = VersionConstants.SDVX_BOOTH
name: str = 'SOUND VOLTEX BOOTH'
version: int = VersionConstants.SDVX_BOOTH
GAME_LIMITED_LOCKED = 1
GAME_LIMITED_UNLOCKED = 2
GAME_LIMITED_LOCKED: Final[int] = 1
GAME_LIMITED_UNLOCKED: Final[int] = 2
GAME_CURRENCY_PACKETS = 0
GAME_CURRENCY_BLOCKS = 1
GAME_CURRENCY_PACKETS: Final[int] = 0
GAME_CURRENCY_BLOCKS: Final[int] = 1
GAME_CLEAR_TYPE_NO_CLEAR = 1
GAME_CLEAR_TYPE_CLEAR = 2
GAME_CLEAR_TYPE_ULTIMATE_CHAIN = 3
GAME_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN = 4
GAME_CLEAR_TYPE_NO_CLEAR: Final[int] = 1
GAME_CLEAR_TYPE_CLEAR: Final[int] = 2
GAME_CLEAR_TYPE_ULTIMATE_CHAIN: Final[int] = 3
GAME_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN: Final[int] = 4
GAME_GRADE_NO_PLAY = 0
GAME_GRADE_D = 1
GAME_GRADE_C = 2
GAME_GRADE_B = 3
GAME_GRADE_A = 4
GAME_GRADE_AA = 5
GAME_GRADE_AAA = 6
GAME_GRADE_NO_PLAY: Final[int] = 0
GAME_GRADE_D: Final[int] = 1
GAME_GRADE_C: Final[int] = 2
GAME_GRADE_B: Final[int] = 3
GAME_GRADE_A: Final[int] = 4
GAME_GRADE_AA: Final[int] = 5
GAME_GRADE_AAA: Final[int] = 6
@classmethod
def get_settings(cls) -> Dict[str, Any]:
@ -470,7 +470,7 @@ class SoundVoltexBooth(
return game
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Update experience and in-game currencies
earned_gamecoin_packet = request.child_value('earned_gamecoin_packet')

View File

@ -1,4 +1,4 @@
from typing import Optional
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.sdvx.booth import SoundVoltexBooth
@ -13,7 +13,7 @@ from bemani.data import Config, Data
class SoundVoltexFactory(Factory):
MANAGED_CLASSES = [
MANAGED_CLASSES: List[Type[Base]] = [
SoundVoltexBooth,
SoundVoltexInfiniteInfection,
SoundVoltexGravityWars,

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
from typing import Any, Dict, List, Optional
from typing_extensions import Final
from bemani.backend.ess import EventLogHandler
from bemani.backend.sdvx.base import SoundVoltexBase
@ -13,35 +14,35 @@ class SoundVoltexGravityWars(
SoundVoltexBase,
):
name = 'SOUND VOLTEX III GRAVITY WARS'
version = VersionConstants.SDVX_GRAVITY_WARS
name: str = 'SOUND VOLTEX III GRAVITY WARS'
version: int = VersionConstants.SDVX_GRAVITY_WARS
GAME_LIMITED_LOCKED = 1
GAME_LIMITED_UNLOCKABLE = 2
GAME_LIMITED_UNLOCKED = 3
GAME_LIMITED_LOCKED: Final[int] = 1
GAME_LIMITED_UNLOCKABLE: Final[int] = 2
GAME_LIMITED_UNLOCKED: Final[int] = 3
GAME_CURRENCY_PACKETS = 0
GAME_CURRENCY_BLOCKS = 1
GAME_CURRENCY_PACKETS: Final[int] = 0
GAME_CURRENCY_BLOCKS: Final[int] = 1
GAME_CLEAR_TYPE_NO_CLEAR = 1
GAME_CLEAR_TYPE_CLEAR = 2
GAME_CLEAR_TYPE_HARD_CLEAR = 3
GAME_CLEAR_TYPE_ULTIMATE_CHAIN = 4
GAME_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN = 5
GAME_CLEAR_TYPE_NO_CLEAR: Final[int] = 1
GAME_CLEAR_TYPE_CLEAR: Final[int] = 2
GAME_CLEAR_TYPE_HARD_CLEAR: Final[int] = 3
GAME_CLEAR_TYPE_ULTIMATE_CHAIN: Final[int] = 4
GAME_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN: Final[int] = 5
GAME_GRADE_NO_PLAY = 0
GAME_GRADE_D = 1
GAME_GRADE_C = 2
GAME_GRADE_B = 3
GAME_GRADE_A = 4
GAME_GRADE_AA = 5
GAME_GRADE_AAA = 6
GAME_GRADE_NO_PLAY: Final[int] = 0
GAME_GRADE_D: Final[int] = 1
GAME_GRADE_C: Final[int] = 2
GAME_GRADE_B: Final[int] = 3
GAME_GRADE_A: Final[int] = 4
GAME_GRADE_AA: Final[int] = 5
GAME_GRADE_AAA: Final[int] = 6
GAME_CATALOG_TYPE_SONG = 0
GAME_CATALOG_TYPE_APPEAL_CARD = 1
GAME_CATALOG_TYPE_CREW = 4
GAME_CATALOG_TYPE_SONG: Final[int] = 0
GAME_CATALOG_TYPE_APPEAL_CARD: Final[int] = 1
GAME_CATALOG_TYPE_CREW: Final[int] = 4
GAME_GAUGE_TYPE_SKILL = 1
GAME_GAUGE_TYPE_SKILL: Final[int] = 1
@classmethod
def get_settings(cls) -> Dict[str, Any]:

View File

@ -1,5 +1,4 @@
# vim: set fileencoding=utf-8
import copy
from typing import Any, Dict, List
from bemani.backend.sdvx.gravitywars import SoundVoltexGravityWars
@ -3263,7 +3262,7 @@ class SoundVoltexGravityWarsSeason1(
return game
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value('earned_gamecoin_packet')

View File

@ -1,5 +1,4 @@
# vim: set fileencoding=utf-8
import copy
from typing import Any, Dict, List, Tuple
from bemani.backend.sdvx.gravitywars import SoundVoltexGravityWars
@ -4125,7 +4124,7 @@ class SoundVoltexGravityWarsSeason2(
return game
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value('earned_gamecoin_packet')

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Any, Dict, List, Optional, Tuple
from typing_extensions import Final
from bemani.backend.ess import EventLogHandler
from bemani.backend.sdvx.base import SoundVoltexBase
@ -15,62 +15,62 @@ class SoundVoltexHeavenlyHaven(
SoundVoltexBase,
):
name = 'SOUND VOLTEX IV HEAVENLY HAVEN'
version = VersionConstants.SDVX_HEAVENLY_HAVEN
name: str = 'SOUND VOLTEX IV HEAVENLY HAVEN'
version: int = VersionConstants.SDVX_HEAVENLY_HAVEN
GAME_LIMITED_LOCKED = 1
GAME_LIMITED_UNLOCKABLE = 2
GAME_LIMITED_UNLOCKED = 3
GAME_LIMITED_LOCKED: Final[int] = 1
GAME_LIMITED_UNLOCKABLE: Final[int] = 2
GAME_LIMITED_UNLOCKED: Final[int] = 3
GAME_CURRENCY_PACKETS = 0
GAME_CURRENCY_BLOCKS = 1
GAME_CURRENCY_PACKETS: Final[int] = 0
GAME_CURRENCY_BLOCKS: Final[int] = 1
GAME_CATALOG_TYPE_SONG = 0
GAME_CATALOG_TYPE_APPEAL_CARD = 1
GAME_CATALOG_TYPE_CREW = 4
GAME_CATALOG_TYPE_SONG: Final[int] = 0
GAME_CATALOG_TYPE_APPEAL_CARD: Final[int] = 1
GAME_CATALOG_TYPE_CREW: Final[int] = 4
GAME_CLEAR_TYPE_NO_PLAY = 0
GAME_CLEAR_TYPE_FAILED = 1
GAME_CLEAR_TYPE_CLEAR = 2
GAME_CLEAR_TYPE_HARD_CLEAR = 3
GAME_CLEAR_TYPE_ULTIMATE_CHAIN = 4
GAME_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN = 5
GAME_CLEAR_TYPE_NO_PLAY: Final[int] = 0
GAME_CLEAR_TYPE_FAILED: Final[int] = 1
GAME_CLEAR_TYPE_CLEAR: Final[int] = 2
GAME_CLEAR_TYPE_HARD_CLEAR: Final[int] = 3
GAME_CLEAR_TYPE_ULTIMATE_CHAIN: Final[int] = 4
GAME_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN: Final[int] = 5
GAME_GRADE_NO_PLAY = 0
GAME_GRADE_D = 1
GAME_GRADE_C = 2
GAME_GRADE_B = 3
GAME_GRADE_A = 4
GAME_GRADE_A_PLUS = 5
GAME_GRADE_AA = 6
GAME_GRADE_AA_PLUS = 7
GAME_GRADE_AAA = 8
GAME_GRADE_AAA_PLUS = 9
GAME_GRADE_S = 10
GAME_GRADE_NO_PLAY: Final[int] = 0
GAME_GRADE_D: Final[int] = 1
GAME_GRADE_C: Final[int] = 2
GAME_GRADE_B: Final[int] = 3
GAME_GRADE_A: Final[int] = 4
GAME_GRADE_A_PLUS: Final[int] = 5
GAME_GRADE_AA: Final[int] = 6
GAME_GRADE_AA_PLUS: Final[int] = 7
GAME_GRADE_AAA: Final[int] = 8
GAME_GRADE_AAA_PLUS: Final[int] = 9
GAME_GRADE_S: Final[int] = 10
GAME_SKILL_NAME_ID_LV_01 = 1
GAME_SKILL_NAME_ID_LV_02 = 2
GAME_SKILL_NAME_ID_LV_03 = 3
GAME_SKILL_NAME_ID_LV_04 = 4
GAME_SKILL_NAME_ID_LV_05 = 5
GAME_SKILL_NAME_ID_LV_06 = 6
GAME_SKILL_NAME_ID_LV_07 = 7
GAME_SKILL_NAME_ID_LV_08 = 8
GAME_SKILL_NAME_ID_LV_09 = 9
GAME_SKILL_NAME_ID_LV_10 = 10
GAME_SKILL_NAME_ID_LV_11 = 11
GAME_SKILL_NAME_ID_LV_INF = 12
GAME_SKILL_NAME_ID_KAC_6TH_BODY = 13
GAME_SKILL_NAME_ID_KAC_6TH_TECHNOLOGY = 14
GAME_SKILL_NAME_ID_KAC_6TH_HEART = 15
GAME_SKILL_NAME_ID_TENKAICHI = 16
GAME_SKILL_NAME_ID_MUSIC_FESTIVAL = 17
GAME_SKILL_NAME_ID_YELLOWTAIL = 18 # For the April Fool's day courses.
GAME_SKILL_NAME_ID_BMK2017 = 19
GAME_SKILL_NAME_ID_KAC_7TH_TIGER = 20
GAME_SKILL_NAME_ID_KAC_7TH_WOLF = 21
GAME_SKILL_NAME_ID_RIKKA = 22 # For the course that ran from 1/18/2018-2/18/2018
GAME_SKILL_NAME_ID_KAC_8TH = 23
GAME_SKILL_NAME_ID_LV_01: Final[int] = 1
GAME_SKILL_NAME_ID_LV_02: Final[int] = 2
GAME_SKILL_NAME_ID_LV_03: Final[int] = 3
GAME_SKILL_NAME_ID_LV_04: Final[int] = 4
GAME_SKILL_NAME_ID_LV_05: Final[int] = 5
GAME_SKILL_NAME_ID_LV_06: Final[int] = 6
GAME_SKILL_NAME_ID_LV_07: Final[int] = 7
GAME_SKILL_NAME_ID_LV_08: Final[int] = 8
GAME_SKILL_NAME_ID_LV_09: Final[int] = 9
GAME_SKILL_NAME_ID_LV_10: Final[int] = 10
GAME_SKILL_NAME_ID_LV_11: Final[int] = 11
GAME_SKILL_NAME_ID_LV_INF: Final[int] = 12
GAME_SKILL_NAME_ID_KAC_6TH_BODY: Final[int] = 13
GAME_SKILL_NAME_ID_KAC_6TH_TECHNOLOGY: Final[int] = 14
GAME_SKILL_NAME_ID_KAC_6TH_HEART: Final[int] = 15
GAME_SKILL_NAME_ID_TENKAICHI: Final[int] = 16
GAME_SKILL_NAME_ID_MUSIC_FESTIVAL: Final[int] = 17
GAME_SKILL_NAME_ID_YELLOWTAIL: Final[int] = 18 # For the April Fool's day courses.
GAME_SKILL_NAME_ID_BMK2017: Final[int] = 19
GAME_SKILL_NAME_ID_KAC_7TH_TIGER: Final[int] = 20
GAME_SKILL_NAME_ID_KAC_7TH_WOLF: Final[int] = 21
GAME_SKILL_NAME_ID_RIKKA: Final[int] = 22 # For the course that ran from 1/18/2018-2/18/2018
GAME_SKILL_NAME_ID_KAC_8TH: Final[int] = 23
# Return the local2 service so that SDVX 4 and above will send certain packets.
extra_services: List[str] = [
@ -4023,7 +4023,7 @@ class SoundVoltexHeavenlyHaven(
return game
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value('earned_gamecoin_packet')

View File

@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8
import copy
from typing import Any, Dict, List, Optional
from typing_extensions import Final
from bemani.backend.ess import EventLogHandler
from bemani.backend.sdvx.base import SoundVoltexBase
@ -15,35 +15,35 @@ class SoundVoltexInfiniteInfection(
SoundVoltexBase,
):
name = 'SOUND VOLTEX II -infinite infection-'
version = VersionConstants.SDVX_INFINITE_INFECTION
name: str = 'SOUND VOLTEX II -infinite infection-'
version: int = VersionConstants.SDVX_INFINITE_INFECTION
GAME_LIMITED_LOCKED = 1
GAME_LIMITED_UNLOCKABLE = 2
GAME_LIMITED_UNLOCKED = 3
GAME_LIMITED_LOCKED: Final[int] = 1
GAME_LIMITED_UNLOCKABLE: Final[int] = 2
GAME_LIMITED_UNLOCKED: Final[int] = 3
GAME_CURRENCY_PACKETS = 0
GAME_CURRENCY_BLOCKS = 1
GAME_CURRENCY_PACKETS: Final[int] = 0
GAME_CURRENCY_BLOCKS: Final[int] = 1
GAME_CLEAR_TYPE_NO_CLEAR = 1
GAME_CLEAR_TYPE_CLEAR = 2
GAME_CLEAR_TYPE_HARD_CLEAR = 5
GAME_CLEAR_TYPE_ULTIMATE_CHAIN = 3
GAME_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN = 4
GAME_CLEAR_TYPE_NO_CLEAR: Final[int] = 1
GAME_CLEAR_TYPE_CLEAR: Final[int] = 2
GAME_CLEAR_TYPE_HARD_CLEAR: Final[int] = 5
GAME_CLEAR_TYPE_ULTIMATE_CHAIN: Final[int] = 3
GAME_CLEAR_TYPE_PERFECT_ULTIMATE_CHAIN: Final[int] = 4
GAME_GRADE_NO_PLAY = 0
GAME_GRADE_D = 1
GAME_GRADE_C = 2
GAME_GRADE_B = 3
GAME_GRADE_A = 4
GAME_GRADE_AA = 5
GAME_GRADE_AAA = 6
GAME_GRADE_NO_PLAY: Final[int] = 0
GAME_GRADE_D: Final[int] = 1
GAME_GRADE_C: Final[int] = 2
GAME_GRADE_B: Final[int] = 3
GAME_GRADE_A: Final[int] = 4
GAME_GRADE_AA: Final[int] = 5
GAME_GRADE_AAA: Final[int] = 6
GAME_CATALOG_TYPE_SONG = 0
GAME_CATALOG_TYPE_APPEAL_CARD = 1
GAME_CATALOG_TYPE_SPECIAL_SONG = 2
GAME_CATALOG_TYPE_SONG: Final[int] = 0
GAME_CATALOG_TYPE_APPEAL_CARD: Final[int] = 1
GAME_CATALOG_TYPE_SPECIAL_SONG: Final[int] = 2
GAME_GAUGE_TYPE_SKILL = 1
GAME_GAUGE_TYPE_SKILL: Final[int] = 1
@classmethod
def get_settings(cls) -> Dict[str, Any]:
@ -2415,7 +2415,7 @@ class SoundVoltexInfiniteInfection(
return game
def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile:
newprofile = copy.deepcopy(oldprofile)
newprofile = oldprofile.clone()
# Update blaster energy and in-game currencies
earned_gamecoin_packet = request.child_value('earned_gamecoin_packet')

View File

@ -1,3 +1,4 @@
import copy
from typing import Optional, List, Dict, Any
from bemani.common.constants import GameConstants
@ -26,6 +27,9 @@ class ValidatedDict(dict):
type. If it does not, the value is not updated.
"""
def clone(self) -> "ValidatedDict":
return ValidatedDict(copy.deepcopy(self))
def get_int(self, name: str, default: int=0) -> int:
"""
Given the name of a value, return an integer stored under that name.
@ -455,6 +459,9 @@ class Profile(ValidatedDict):
self.refid = refid
self.extid = extid
def clone(self) -> "Profile":
return Profile(self.game, self.version, self. refid, self.extid, copy.deepcopy(self))
class PlayStatistics(ValidatedDict):
"""
@ -488,3 +495,15 @@ class PlayStatistics(ValidatedDict):
self.first_play_timestamp = first_play_timestamp
# The timestamp of the very last play session, in seconds.
self.last_play_timestamp = last_play_timestamp
def clone(self) -> "PlayStatistics":
return PlayStatistics(
self.game,
self.total_plays,
self.today_plays,
self.total_days,
self.consecutive_days,
self.first_play_timestamp,
self.last_play_timestamp,
copy.deepcopy(self),
)