1
0
mirror of synced 2025-01-18 14:14:03 +01:00

Make Config a real class instead of a Dict, for safer access and defaults.

This commit is contained in:
Jennifer Taylor 2021-08-20 04:43:59 +00:00
parent 628828ed12
commit 40dbf1d6b9
58 changed files with 544 additions and 351 deletions

View File

@ -9,12 +9,12 @@ from bemani.api.exceptions import APIException
from bemani.api.objects import RecordsObject, ProfileObject, StatisticsObject, CatalogObject
from bemani.api.types import g
from bemani.common import GameConstants, APIConstants, VersionConstants
from bemani.data import Data
from bemani.data import Config, Data
app = Flask(
__name__
)
config: Dict[str, Any] = {}
config = Config()
SUPPORTED_VERSIONS = ['v1']
@ -172,8 +172,8 @@ def info() -> Dict[str, Any]:
return {
'versions': SUPPORTED_VERSIONS,
'name': g.config.get('name', 'e-AMUSEMENT Network'),
'email': g.config.get('email', 'nobody@nowhere.com'),
'name': g.config.name,
'email': g.config.email,
}
@ -209,7 +209,7 @@ def lookup(protoversion: str, requestgame: str, requestversion: str) -> Dict[str
('reflecbeat', GameConstants.REFLEC_BEAT),
('soundvoltex', GameConstants.SDVX),
]:
if constant in g.config['support']:
if constant in g.config.support:
gamemapping[gameid] = constant
game = gamemapping.get(requestgame)
if game is None:

View File

@ -1,13 +1,13 @@
from typing import Any, Dict, TYPE_CHECKING
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from flask.ctx import _AppCtxGlobals
from bemani.data import Data
from bemani.data import Config, Data
class RequestGlobals(_AppCtxGlobals):
config: Dict[str, Any]
config: Config
data: Data
authorized: bool

View File

@ -3,7 +3,7 @@ import traceback
from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Type
from bemani.common import Model, ValidatedDict, Profile, GameConstants, Time
from bemani.data import Data, UserID, RemoteUser
from bemani.data import Config, Data, UserID, RemoteUser
class ProfileCreationException(Exception):
@ -41,7 +41,7 @@ class Factory:
raise Exception('Override this in subclass!')
@classmethod
def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> None:
def run_scheduled_work(cls, data: Data, config: Config) -> None:
"""
Subclasses of this class should use this function to run any scheduled
work on classes which it is a factory for. This is usually used for
@ -84,7 +84,7 @@ class Factory:
yield (game.game, game.version, game.get_settings())
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional['Base']:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional['Base']:
"""
Given a modelstring and an optional parent model, return an instantiated game class that can handle a packet.
@ -129,13 +129,13 @@ class Base(ABC):
"""
name: str
def __init__(self, data: Data, config: Dict[str, Any], model: Model) -> None:
def __init__(self, data: Data, config: Config, model: Model) -> None:
self.data = data
self.config = config
self.model = model
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional['Base']:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional['Base']:
"""
Given a modelstring and an optional parent model, return an instantiated game class that can handle a packet.
@ -179,7 +179,7 @@ class Base(ABC):
cls.__registered_handlers.add(handler)
@classmethod
def run_scheduled_work(cls, data: Data, config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
def run_scheduled_work(cls, data: Data, config: Config) -> List[Tuple[str, Dict[str, Any]]]:
"""
Run any out-of-band scheduled work that is applicable to this game.
"""
@ -387,23 +387,23 @@ class Base(ABC):
self.data.local.game.put_settings(self.game, userid, settings)
def get_machine_id(self) -> int:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
return machine.id
def update_machine_name(self, newname: Optional[str]) -> None:
if newname is None:
return
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
machine.name = newname
self.data.local.machine.put_machine(machine)
def update_machine_data(self, newdata: Dict[str, Any]) -> None:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
machine.data.update(newdata)
self.data.local.machine.put_machine(machine)
def get_game_config(self) -> ValidatedDict:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
settings = self.data.local.machine.get_settings(machine.arcade, self.game, self.version, 'game_config')
else:

View File

@ -1,9 +1,9 @@
from typing import Dict, Optional, Any
from typing import Optional
from bemani.backend.base import Base, Factory
from bemani.backend.bishi.bishi import TheStarBishiBashi
from bemani.common import Model
from bemani.data import Data
from bemani.data import Config, Data
class BishiBashiFactory(Factory):
@ -18,7 +18,7 @@ class BishiBashiFactory(Factory):
Base.register(gamecode, BishiBashiFactory)
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
if model.gamecode == 'IBB':
return TheStarBishiBashi(data, config, model)

View File

@ -49,7 +49,7 @@ class CardManagerHandler(Base):
expired = True
refid = self.data.local.user.get_refid(self.game, self.version, userid)
paseli_enabled = self.supports_paseli() and self.config['paseli']['enabled']
paseli_enabled = self.supports_paseli() and self.config.paseli.enabled
root = Node.void('cardmng')
root.set_attribute('refid', refid)

View File

@ -22,7 +22,7 @@ class CoreHandler(Base):
node.set_attribute('url', url)
return node
url = f'{"https" if self.config["server"]["https"] else "http"}://{self.config["server"]["address"]}:{self.config["server"]["port"]}/'
url = f'{"https" if self.config.server.https else "http"}://{self.config.server.address}:{self.config.server.port}/'
root = Node.void('services')
root.set_attribute('expire', '600')
# This can be set to 'operation', 'debug', 'test', and 'factory'.
@ -45,13 +45,9 @@ class CoreHandler(Base):
root.add_child(item(srv, url))
root.add_child(item('ntp', 'ntp://pool.ntp.org/'))
# Look up keepalive override if exists, otherwise use the server address
if 'keepalive' in self.config['server']:
keepalive = self.config['server']['keepalive']
else:
keepalive = self.config['server']['address']
# Translate to a raw IP because we can't give out a host here
keepalive = socket.gethostbyname(keepalive)
# Translate keepalive to a raw IP because we can't give out a host here
keepalive = socket.gethostbyname(self.config.server.keepalive)
root.add_child(item(
'keepalive',
f'http://{keepalive}/core/keepalive?pa={keepalive}&ia={keepalive}&ga={keepalive}&ma={keepalive}&t1=2&t2=10',
@ -65,7 +61,7 @@ class CoreHandler(Base):
"""
# Reports that a machine is booting. Overloaded to enable/disable paseli
root = Node.void('pcbtracker')
root.set_attribute('ecenable', '1' if (self.supports_paseli() and self.config['paseli']['enabled']) else '0')
root.set_attribute('ecenable', '1' if (self.supports_paseli() and self.config.paseli.enabled) else '0')
root.set_attribute('expire', '600')
return root
@ -84,8 +80,8 @@ class CoreHandler(Base):
'name': name,
'value': value,
'model': str(self.model),
'pcbid': self.config['machine']['pcbid'],
'ip': self.config['client']['address'],
'pcbid': self.config.machine.pcbid,
'ip': self.config.client.address,
},
timestamp=timestamp,
)
@ -124,7 +120,7 @@ class CoreHandler(Base):
which expects to return a bunch of information about the arcade this
cabinet is in, as well as some settings for URLs and the name of the cab.
"""
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root = Node.void('facility')
root.set_attribute('expire', '600')
@ -140,7 +136,7 @@ class CoreHandler(Base):
line.add_child(Node.u8('class', 0))
portfw = Node.void('portfw')
portfw.add_child(Node.ipv4('globalip', self.config['client']['address']))
portfw.add_child(Node.ipv4('globalip', self.config.client.address))
portfw.add_child(Node.u16('globalport', machine.port))
portfw.add_child(Node.u16('privateport', machine.port))
@ -160,11 +156,11 @@ class CoreHandler(Base):
eapass.add_child(Node.u16('valid', 365))
url = Node.void('url')
url.add_child(Node.string('eapass', self.config['server']['uri'] or 'www.ea-pass.konami.net'))
url.add_child(Node.string('arcadefan', self.config['server']['uri'] or 'www.konami.jp/am'))
url.add_child(Node.string('konaminetdx', self.config['server']['uri'] or 'http://am.573.jp'))
url.add_child(Node.string('konamiid', self.config['server']['uri'] or 'https://id.konami.net'))
url.add_child(Node.string('eagate', self.config['server']['uri'] or 'http://eagate.573.jp'))
url.add_child(Node.string('eapass', self.config.server.uri or 'www.ea-pass.konami.net'))
url.add_child(Node.string('arcadefan', self.config.server.uri or 'www.konami.jp/am'))
url.add_child(Node.string('konaminetdx', self.config.server.uri or 'http://am.573.jp'))
url.add_child(Node.string('konamiid', self.config.server.uri or 'https://id.konami.net'))
url.add_child(Node.string('eagate', self.config.server.uri or 'http://eagate.573.jp'))
share.add_child(eacoin)
share.add_child(url)

View File

@ -27,7 +27,7 @@ class PASELIHandler(Base):
"""
method = request.attribute('method')
if not self.config['paseli']['enabled']:
if not self.config.paseli.enabled:
# Refuse to respond, we don't have PASELI enabled
print("PASELI not enabled, ignoring eacoin request")
root = Node.void('eacoin')
@ -61,15 +61,15 @@ class PASELIHandler(Base):
session = self.data.local.user.create_session(userid)
if self.config['paseli']['infinite']:
if self.config.paseli.infinite:
balance = PASELIHandler.INFINITE_PASELI_AMOUNT
else:
if self.config['machine']['arcade'] is None:
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'])
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))
@ -89,13 +89,13 @@ class PASELIHandler(Base):
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if self.config['machine']['arcade'] is None:
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'])
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")
@ -136,10 +136,10 @@ class PASELIHandler(Base):
print("Invalid session for eacoin consume request")
return make_resp(2, 0)
if self.config['paseli']['infinite']:
if self.config.paseli.infinite:
balance = PASELIHandler.INFINITE_PASELI_AMOUNT - payment
else:
if self.config['machine']['arcade'] is None:
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.
@ -147,11 +147,11 @@ class PASELIHandler(Base):
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)
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']))
return make_resp(1, self.data.local.user.get_balance(userid, self.config.machine.arcade))
else:
self.data.local.network.put_event(
'paseli_transaction',
@ -160,10 +160,10 @@ class PASELIHandler(Base):
'balance': balance,
'service': -service,
'reason': details,
'pcbid': self.config['machine']['pcbid'],
'pcbid': self.config.machine.pcbid,
},
userid=userid,
arcadeid=self.config['machine']['arcade'],
arcadeid=self.config.machine.arcade,
)
return make_resp(0, balance)
@ -191,7 +191,7 @@ class PASELIHandler(Base):
# 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'])
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
@ -394,13 +394,13 @@ class PASELIHandler(Base):
root.set_attribute('status', str(Status.NO_PROFILE))
return root
if self.config['machine']['arcade'] is None:
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'])
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")

View File

@ -1,10 +1,10 @@
# vim: set fileencoding=utf-8
from typing import Optional, Dict, List, Any
from typing import Optional, List
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
from bemani.common import Model, Profile, ValidatedDict, GameConstants, DBConstants, Time
from bemani.data import Data, Score, UserID, ScoreSaveException
from bemani.data import Config, Data, Score, UserID, ScoreSaveException
from bemani.protocol import Node
@ -51,7 +51,7 @@ class DDRBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
CHART_DOUBLE_EXPERT = 8
CHART_DOUBLE_CHALLENGE = 9
def __init__(self, data: Data, config: Dict[str, Any], model: Model) -> None:
def __init__(self, data: Data, config: Config, model: Model) -> None:
super().__init__(data, config, model)
if model.rev == 'X':
self.omnimix = True

View File

@ -466,7 +466,7 @@ class DDRAce(
response.add_child(data)
data.add_child(Node.s32('recordtype', requestdata.child_value('loadflag')))
thismachine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
thismachine = self.data.local.machine.get_machine(self.config.machine.pcbid)
machines_by_id: Dict[int, Optional[Machine]] = {thismachine.id: thismachine}
loadkind = requestdata.child_value('loadflag')
@ -559,7 +559,7 @@ class DDRAce(
if userid is None:
raise Exception('Expecting valid UserID to create new profile!')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
profile = Profile(
self.game,
self.version,

View File

@ -1,4 +1,4 @@
from typing import Dict, Optional, Any
from typing import Optional
from bemani.backend.base import Base, Factory
from bemani.backend.ddr.stubs import (
@ -21,7 +21,7 @@ from bemani.backend.ddr.ddr2014 import DDR2014
from bemani.backend.ddr.ddrace import DDRAce
from bemani.backend.ddr.ddra20 import DDRA20
from bemani.common import Model, VersionConstants
from bemani.data import Data
from bemani.data import Config, Data
class DDRFactory(Factory):
@ -52,7 +52,7 @@ class DDRFactory(Factory):
Base.register(gamecode, DDRFactory)
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def version_from_date(date: int) -> Optional[int]:
if date < 2014051200:

View File

@ -1,9 +1,8 @@
import copy
from typing import Optional, Dict, Any
from typing import Optional, Any
from bemani.backend.base import Model, Base, Status
from bemani.protocol import Node
from bemani.data import Data
from bemani.data import Config, Data
class UnrecognizedPCBIDException(Exception):
@ -20,7 +19,7 @@ class Dispatch:
class and then returning a response.
"""
def __init__(self, config: Dict[str, Any], data: Data, verbose: bool) -> None:
def __init__(self, config: Config, data: Data, verbose: bool) -> None:
"""
Initialize the Dispatch object.
@ -77,9 +76,9 @@ class Dispatch:
# If we are enforcing, bail out if we don't recognize thie ID
pcb = self.__data.local.machine.get_machine(pcbid)
if self.__config['server']['enforce_pcbid'] and pcb is None:
if self.__config.server.enforce_pcbid and pcb is None:
self.log("Unrecognized PCBID {}", pcbid)
raise UnrecognizedPCBIDException(pcbid, modelstring, self.__config['client']['address'])
raise UnrecognizedPCBIDException(pcbid, modelstring, self.__config.client.address)
# If we don't have a Machine, but we aren't enforcing, we must create it
if pcb is None:
@ -87,7 +86,7 @@ class Dispatch:
request = tree.children[0]
config = copy.copy(self.__config)
config = self.__config.clone()
config['machine'] = {
'pcbid': pcbid,
'arcade': pcb.arcade,
@ -103,9 +102,6 @@ class Dispatch:
if arcade.data.get_bool('mask_services_url'):
# Mask the address, no matter what the server settings are
config['server']['uri'] = None
# If we don't have a server URI, we should add the default
if 'uri' not in config['server']:
config['server']['uri'] = None
game = Base.create(self.__data, config, model)
method = request.attribute('method')
@ -113,10 +109,10 @@ class Dispatch:
# If we are enforcing, make sure the PCBID isn't specified to be
# game-specific
if self.__config['server']['enforce_pcbid'] and pcb.game is not None:
if config.server.enforce_pcbid and pcb.game is not None:
if pcb.game != game.game:
self.log("PCBID {} assigned to game {}, but connected from game {}", pcbid, pcb.game, game.game)
raise UnrecognizedPCBIDException(pcbid, modelstring, self.__config['client']['address'])
raise UnrecognizedPCBIDException(pcbid, modelstring, config.client.address)
if pcb.version is not None:
if pcb.version > 0 and pcb.version != game.version:
self.log(
@ -127,7 +123,7 @@ class Dispatch:
game.game,
game.version,
)
raise UnrecognizedPCBIDException(pcbid, modelstring, self.__config['client']['address'])
raise UnrecognizedPCBIDException(pcbid, modelstring, config.client.address)
if pcb.version < 0 and (-pcb.version) < game.version:
self.log(
"PCBID {} assigned to game {} maximum version {}, but connected from game {} version {}",
@ -137,7 +133,7 @@ class Dispatch:
game.game,
game.version,
)
raise UnrecognizedPCBIDException(pcbid, modelstring, self.__config['client']['address'])
raise UnrecognizedPCBIDException(pcbid, modelstring, config.client.address)
# First, try to handle with specific service/method function
try:

View File

@ -5,7 +5,7 @@ from typing import Optional, Dict, Any, List, Tuple
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
from bemani.common import Profile, ValidatedDict, Model, GameConstants, DBConstants, Parallel
from bemani.data import Data, Score, Machine, UserID
from bemani.data import Config, Data, Score, Machine, UserID
from bemani.protocol import Node
@ -75,7 +75,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
GHOST_TYPE_RIVAL_TOP = 800
GHOST_TYPE_RIVAL_AVERAGE = 900
def __init__(self, data: Data, config: Dict[str, Any], model: Model) -> None:
def __init__(self, data: Data, config: Config, model: Model) -> None:
super().__init__(data, config, model)
if model.rev == 'X':
self.omnimix = True
@ -189,7 +189,7 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
return None
def machine_joined_arcade(self) -> bool:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
return machine.arcade is not None
def get_clear_rates(

View File

@ -288,7 +288,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
raise Exception('Invalid cltype!')
def handle_IIDX25shop_getname_request(self, request: Node) -> Node:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine is not None:
machine_name = machine.name
close = machine.data.get_bool('close')
@ -333,7 +333,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
def handle_IIDX25shop_getconvention_request(self, request: Node) -> Node:
root = Node.void('IIDX25shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -350,7 +350,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
return root
def handle_IIDX25shop_setconvention_request(self, request: Node) -> Node:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = ValidatedDict()
course.replace_int('music_0', request.child_value('music_0'))
@ -376,7 +376,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
# Chart type 6 is presumably beginner mode, but it crashes the game
return root
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -677,7 +677,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
if self.machine_joined_arcade():
game_config = self.get_game_config()
global_scores = game_config.get_bool('global_shop_ranking')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
else:
# If we aren't in an arcade, we can only show global scores
global_scores = True
@ -1425,7 +1425,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
# Look up judge window adjustments
judge_dict = profile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
# Profile data
pcdata = Node.void('pcdata')
@ -1921,10 +1921,10 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase):
newprofile.replace_int('rtype', int(request.attribute('rtype')))
# Update judge window adjustments per-machine
judge_dict = newprofile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
machine_judge.replace_int('single', int(request.attribute('s_judgeAdj')))
machine_judge.replace_int('double', int(request.attribute('d_judgeAdj')))
judge_dict.replace_dict(self.config['machine']['pcbid'], machine_judge)
judge_dict.replace_dict(self.config.machine.pcbid, machine_judge)
newprofile.replace_dict('machine_judge_adjust', judge_dict)
# Secret flags saving

View File

@ -293,7 +293,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
if method == 'getname':
root = Node.void('IIDX23shop')
root.set_attribute('cls_opt', '0')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root.set_attribute('opname', machine.name)
root.set_attribute('pid', '51')
return root
@ -309,7 +309,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
if method == 'getconvention':
root = Node.void('IIDX23shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -327,7 +327,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
if method == 'setconvention':
root = Node.void('IIDX23shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = ValidatedDict()
course.replace_int('music_0', request.child_value('music_0'))
@ -364,7 +364,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
# Chart type 6 is presumably beginner mode, but it crashes the game
return root
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -571,7 +571,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
if self.machine_joined_arcade():
game_config = self.get_game_config()
global_scores = game_config.get_bool('global_shop_ranking')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
else:
# If we aren't in an arcade, we can only show global scores
global_scores = True
@ -1477,7 +1477,7 @@ class IIDXCopula(IIDXCourse, IIDXBase):
# Look up judge window adjustments
judge_dict = profile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
# Profile data
pcdata = Node.void('pcdata')
@ -1925,10 +1925,10 @@ class IIDXCopula(IIDXCourse, IIDXBase):
# Update judge window adjustments per-machine
judge_dict = newprofile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
machine_judge.replace_int('single', int(request.attribute('s_judgeAdj')))
machine_judge.replace_int('double', int(request.attribute('d_judgeAdj')))
judge_dict.replace_dict(self.config['machine']['pcbid'], machine_judge)
judge_dict.replace_dict(self.config.machine.pcbid, machine_judge)
newprofile.replace_dict('machine_judge_adjust', judge_dict)
# Secret flags saving

View File

@ -1,4 +1,4 @@
from typing import Dict, Optional, Any
from typing import Optional
from bemani.backend.base import Base, Factory
from bemani.backend.iidx.stubs import (
@ -32,7 +32,7 @@ from bemani.backend.iidx.rootage import IIDXRootage
from bemani.backend.iidx.heroicverse import IIDXHeroicVerse
from bemani.backend.iidx.bistrover import IIDXBistrover
from bemani.common import Model, VersionConstants
from bemani.data import Data
from bemani.data import Config, Data
class IIDXFactory(Factory):
@ -74,7 +74,7 @@ class IIDXFactory(Factory):
Base.register(gamecode, IIDXFactory)
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def version_from_date(date: int) -> Optional[int]:
if date < 2013100200:

View File

@ -161,7 +161,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
if method == 'getname':
root = Node.void('IIDX22shop')
root.set_attribute('cls_opt', '0')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root.set_attribute('opname', machine.name)
root.set_attribute('pid', '51')
return root
@ -177,7 +177,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
if method == 'getconvention':
root = Node.void('IIDX22shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -195,7 +195,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
if method == 'setconvention':
root = Node.void('IIDX22shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = ValidatedDict()
course.replace_int('music_0', request.child_value('music_0'))
@ -227,7 +227,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
# Chart type 6 is presumably beginner mode, but it crashes the game
return root
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -555,7 +555,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
if self.machine_joined_arcade():
game_config = self.get_game_config()
global_scores = game_config.get_bool('global_shop_ranking')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
else:
# If we aren't in an arcade, we can only show global scores
global_scores = True
@ -1390,7 +1390,7 @@ class IIDXPendual(IIDXCourse, IIDXBase):
# Look up judge window adjustments
judge_dict = profile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
# Profile data
pcdata = Node.void('pcdata')
@ -1771,10 +1771,10 @@ class IIDXPendual(IIDXCourse, IIDXBase):
# Update judge window adjustments per-machine
judge_dict = newprofile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
machine_judge.replace_int('single', int(request.attribute('s_judgeAdj')))
machine_judge.replace_int('double', int(request.attribute('d_judgeAdj')))
judge_dict.replace_dict(self.config['machine']['pcbid'], machine_judge)
judge_dict.replace_dict(self.config.machine.pcbid, machine_judge)
newprofile.replace_dict('machine_judge_adjust', judge_dict)
# Secret flags saving

View File

@ -289,7 +289,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
raise Exception('Invalid cltype!')
def handle_IIDX26shop_getname_request(self, request: Node) -> Node:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine is not None:
machine_name = machine.name
close = machine.data.get_bool('close')
@ -334,7 +334,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
def handle_IIDX26shop_getconvention_request(self, request: Node) -> Node:
root = Node.void('IIDX26shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -351,7 +351,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
return root
def handle_IIDX26shop_setconvention_request(self, request: Node) -> Node:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = ValidatedDict()
course.replace_int('music_0', request.child_value('music_0'))
@ -530,7 +530,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
if self.machine_joined_arcade():
game_config = self.get_game_config()
global_scores = game_config.get_bool('global_shop_ranking')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
else:
# If we aren't in an arcade, we can only show global scores
global_scores = True
@ -1100,7 +1100,7 @@ class IIDXRootage(IIDXCourse, IIDXBase):
# Look up judge window adjustments
judge_dict = profile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
# Profile data
pcdata = Node.void('pcdata')
@ -1638,10 +1638,10 @@ class IIDXRootage(IIDXCourse, IIDXBase):
# Update judge window adjustments per-machine
judge_dict = newprofile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
machine_judge.replace_int('single', int(request.attribute('s_judgeAdj')))
machine_judge.replace_int('double', int(request.attribute('d_judgeAdj')))
judge_dict.replace_dict(self.config['machine']['pcbid'], machine_judge)
judge_dict.replace_dict(self.config.machine.pcbid, machine_judge)
newprofile.replace_dict('machine_judge_adjust', judge_dict)
# Secret flags saving

View File

@ -288,7 +288,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
raise Exception('Invalid cltype!')
def handle_IIDX24shop_getname_request(self, request: Node) -> Node:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine is not None:
machine_name = machine.name
close = machine.data.get_bool('close')
@ -333,7 +333,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
def handle_IIDX24shop_getconvention_request(self, request: Node) -> Node:
root = Node.void('IIDX24shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -350,7 +350,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
return root
def handle_IIDX24shop_setconvention_request(self, request: Node) -> Node:
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = ValidatedDict()
course.replace_int('music_0', request.child_value('music_0'))
@ -376,7 +376,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
# Chart type 6 is presumably beginner mode, but it crashes the game
return root
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -675,7 +675,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
if self.machine_joined_arcade():
game_config = self.get_game_config()
global_scores = game_config.get_bool('global_shop_ranking')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
else:
# If we aren't in an arcade, we can only show global scores
global_scores = True
@ -1449,7 +1449,7 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
# Look up judge window adjustments
judge_dict = profile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
# Profile data
pcdata = Node.void('pcdata')
@ -1936,10 +1936,10 @@ class IIDXSinobuz(IIDXCourse, IIDXBase):
# Update judge window adjustments per-machine
judge_dict = newprofile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
machine_judge.replace_int('single', int(request.attribute('s_judgeAdj')))
machine_judge.replace_int('double', int(request.attribute('d_judgeAdj')))
judge_dict.replace_dict(self.config['machine']['pcbid'], machine_judge)
judge_dict.replace_dict(self.config.machine.pcbid, machine_judge)
newprofile.replace_dict('machine_judge_adjust', judge_dict)
# Secret flags saving

View File

@ -266,7 +266,7 @@ class IIDXSpada(IIDXBase):
if method == 'getname':
root = Node.void('IIDX21shop')
root.set_attribute('cls_opt', '0')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root.set_attribute('opname', machine.name)
root.set_attribute('pid', '51')
return root
@ -282,7 +282,7 @@ class IIDXSpada(IIDXBase):
if method == 'getconvention':
root = Node.void('IIDX21shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -300,7 +300,7 @@ class IIDXSpada(IIDXBase):
if method == 'setconvention':
root = Node.void('IIDX21shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = ValidatedDict()
course.replace_int('music_0', request.child_value('music_0'))
@ -332,7 +332,7 @@ class IIDXSpada(IIDXBase):
# Chart type 6 is presumably beginner mode, but it crashes the game
return root
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -503,7 +503,7 @@ class IIDXSpada(IIDXBase):
if self.machine_joined_arcade():
game_config = self.get_game_config()
global_scores = game_config.get_bool('global_shop_ranking')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
else:
# If we aren't in an arcade, we can only show global scores
global_scores = True
@ -1089,7 +1089,7 @@ class IIDXSpada(IIDXBase):
# Look up judge window adjustments
judge_dict = profile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
# Profile data
pcdata = Node.void('pcdata')
@ -1516,10 +1516,10 @@ class IIDXSpada(IIDXBase):
# Update judge window adjustments per-machine
judge_dict = newprofile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
machine_judge.replace_int('single', int(request.attribute('s_judgeAdj')))
machine_judge.replace_int('double', int(request.attribute('d_judgeAdj')))
judge_dict.replace_dict(self.config['machine']['pcbid'], machine_judge)
judge_dict.replace_dict(self.config.machine.pcbid, machine_judge)
newprofile.replace_dict('machine_judge_adjust', judge_dict)
# Secret flags saving

View File

@ -265,7 +265,7 @@ class IIDXTricoro(IIDXBase):
if method == 'getname':
root = Node.void('shop')
root.set_attribute('cls_opt', '0')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
root.set_attribute('opname', machine.name)
root.set_attribute('pid', '51')
return root
@ -281,7 +281,7 @@ class IIDXTricoro(IIDXBase):
if method == 'getconvention':
root = Node.void('shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -299,7 +299,7 @@ class IIDXTricoro(IIDXBase):
if method == 'setconvention':
root = Node.void('shop')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = ValidatedDict()
course.replace_int('music_0', request.child_value('music_0'))
@ -331,7 +331,7 @@ class IIDXTricoro(IIDXBase):
# Chart type 6 is presumably beginner mode, but it crashes the game
return root
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
course = self.data.local.machine.get_settings(machine.arcade, self.game, self.music_version, 'shop_course')
else:
@ -503,7 +503,7 @@ class IIDXTricoro(IIDXBase):
if self.machine_joined_arcade():
game_config = self.get_game_config()
global_scores = game_config.get_bool('global_shop_ranking')
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
else:
# If we aren't in an arcade, we can only show global scores
global_scores = True
@ -985,7 +985,7 @@ class IIDXTricoro(IIDXBase):
# Look up judge window adjustments
judge_dict = profile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
# Profile data
pcdata = Node.void('pcdata')
@ -1292,9 +1292,9 @@ class IIDXTricoro(IIDXBase):
# Update judge window adjustments per-machine
judge_dict = newprofile.get_dict('machine_judge_adjust')
machine_judge = judge_dict.get_dict(self.config['machine']['pcbid'])
machine_judge = judge_dict.get_dict(self.config.machine.pcbid)
machine_judge.replace_int('adj', int(request.attribute('judgeAdj')))
judge_dict.replace_dict(self.config['machine']['pcbid'], machine_judge)
judge_dict.replace_dict(self.config.machine.pcbid, machine_judge)
newprofile.replace_dict('machine_judge_adjust', judge_dict)
# Secret flags saving

View File

@ -1,4 +1,4 @@
from typing import Dict, Optional, Any
from typing import Optional
from bemani.backend.base import Base, Factory
from bemani.backend.jubeat.stubs import (
@ -17,7 +17,7 @@ from bemani.backend.jubeat.qubell import JubeatQubell
from bemani.backend.jubeat.clan import JubeatClan
from bemani.backend.jubeat.festo import JubeatFesto
from bemani.common import Model
from bemani.data import Data
from bemani.data import Config, Data
class JubeatFactory(Factory):
@ -44,7 +44,7 @@ class JubeatFactory(Factory):
Base.register(gamecode, JubeatFactory)
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
if model.gamecode == 'H44':
return Jubeat(data, config, model)
if model.gamecode == 'I44':

View File

@ -1,10 +1,10 @@
# vim: set fileencoding=utf-8
from typing import Dict, Optional, Any
from typing import Dict, Optional
from bemani.backend.base import Base
from bemani.backend.core import CoreHandler, CardManagerHandler, PASELIHandler
from bemani.common import Profile, ValidatedDict, GameConstants, DBConstants, Parallel, Model
from bemani.data import UserID, Data
from bemani.data import UserID, Config, Data
from bemani.protocol import Node
@ -33,7 +33,7 @@ class MusecaBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
CLEAR_TYPE_CLEARED = DBConstants.MUSECA_CLEAR_TYPE_CLEARED
CLEAR_TYPE_FULL_COMBO = DBConstants.MUSECA_CLEAR_TYPE_FULL_COMBO
def __init__(self, data: Data, config: Dict[str, Any], model: Model) -> None:
def __init__(self, data: Data, config: Config, model: Model) -> None:
super().__init__(data, config, model)
if model.rev == 'X':
self.omnimix = True

View File

@ -1,10 +1,10 @@
from typing import Any, Dict, List, Optional, Type
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.museca.museca1 import Museca1
from bemani.backend.museca.museca1plus import Museca1Plus
from bemani.common import Model, VersionConstants
from bemani.data import Data
from bemani.data import Config, Data
class MusecaFactory(Factory):
@ -20,7 +20,7 @@ class MusecaFactory(Factory):
Base.register(gamecode, MusecaFactory)
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def version_from_date(date: int) -> Optional[int]:
if date <= 2016072600:

View File

@ -1,4 +1,4 @@
from typing import Dict, Optional, Any
from typing import Optional
from bemani.backend.base import Base, Factory
from bemani.backend.popn.stubs import (
@ -29,7 +29,7 @@ from bemani.backend.popn.eclale import PopnMusicEclale
from bemani.backend.popn.usaneko import PopnMusicUsaNeko
from bemani.backend.popn.peace import PopnMusicPeace
from bemani.common import Model, VersionConstants
from bemani.data import Data
from bemani.data import Config, Data
class PopnMusicFactory(Factory):
@ -68,7 +68,7 @@ class PopnMusicFactory(Factory):
Base.register(gamecode, PopnMusicFactory)
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def version_from_date(date: int) -> Optional[int]:
if date <= 2014061900:

View File

@ -1,4 +1,4 @@
from typing import Any, Dict, List, Optional, Type
from typing import List, Optional, Type
from bemani.backend.base import Base, Factory
from bemani.backend.reflec.reflecbeat import ReflecBeat
@ -8,7 +8,7 @@ from bemani.backend.reflec.groovin import ReflecBeatGroovin
from bemani.backend.reflec.volzza import ReflecBeatVolzza
from bemani.backend.reflec.volzza2 import ReflecBeatVolzza2
from bemani.common import Model, VersionConstants
from bemani.data import Data
from bemani.data import Config, Data
class ReflecBeatFactory(Factory):
@ -28,7 +28,7 @@ class ReflecBeatFactory(Factory):
Base.register(gamecode, ReflecBeatFactory)
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def version_from_date(date: int) -> Optional[int]:
if date < 2014060400:

View File

@ -295,7 +295,7 @@ class ReflecBeatGroovin(ReflecBeatBase):
all_profiles = self.data.local.user.get_all_profiles(self.game, self.version)
all_attempts = self.data.local.music.get_all_attempts(self.game, self.version, timelimit=(Time.beginning_of_today() - Time.SECONDS_IN_DAY))
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
lids = [
machine.id for machine in self.data.local.machine.get_all_machines(machine.arcade)

View File

@ -81,7 +81,7 @@ class ReflecBeatVolzzaBase(ReflecBeatBase):
all_profiles = self.data.local.user.get_all_profiles(self.game, self.version)
all_attempts = self.data.local.music.get_all_attempts(self.game, self.version, timelimit=(Time.beginning_of_today() - Time.SECONDS_IN_DAY))
machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
machine = self.data.local.machine.get_machine(self.config.machine.pcbid)
if machine.arcade is not None:
lids = [
machine.id for machine in self.data.local.machine.get_all_machines(machine.arcade)

View File

@ -1,4 +1,4 @@
from typing import Any, Dict, Optional
from typing import Optional
from bemani.backend.base import Base, Factory
from bemani.backend.sdvx.booth import SoundVoltexBooth
@ -8,7 +8,7 @@ from bemani.backend.sdvx.gravitywars_s1 import SoundVoltexGravityWarsSeason1
from bemani.backend.sdvx.gravitywars_s2 import SoundVoltexGravityWarsSeason2
from bemani.backend.sdvx.heavenlyhaven import SoundVoltexHeavenlyHaven
from bemani.common import Model, VersionConstants
from bemani.data import Data
from bemani.data import Config, Data
class SoundVoltexFactory(Factory):
@ -26,7 +26,7 @@ class SoundVoltexFactory(Factory):
Base.register(gamecode, SoundVoltexFactory)
@classmethod
def create(cls, data: Data, config: Dict[str, Any], model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def create(cls, data: Data, config: Config, model: Model, parentmodel: Optional[Model]=None) -> Optional[Base]:
def version_from_date(date: int) -> Optional[int]:
if date < 2013060500:

View File

@ -1,3 +1,4 @@
from bemani.data.config import Config
from bemani.data.data import Data, DBCreateException
from bemani.data.exceptions import ScoreSaveException
from bemani.data.types import User, Achievement, Machine, Arcade, Score, Attempt, News, Link, Song, Event, Server, Client, UserID, ArcadeID
@ -6,6 +7,7 @@ from bemani.data.triggers import Triggers
__all__ = [
"Config",
"Data",
"DBCreateException",
"ScoreSaveException",

195
bemani/data/config.py Normal file
View File

@ -0,0 +1,195 @@
import copy
import os
from sqlalchemy.engine import Engine # type: ignore
from typing import Any, Dict, Optional, Set
from bemani.common.constants import GameConstants
from bemani.data.types import ArcadeID
class Database:
def __init__(self, parent_config: "Config") -> None:
self.__config = parent_config
@property
def address(self) -> str:
return str(self.__config.get('database', {}).get('address', 'localhost'))
@property
def database(self) -> str:
return str(self.__config.get('database', {}).get('database', 'bemani'))
@property
def user(self) -> str:
return str(self.__config.get('database', {}).get('user', 'bemani'))
@property
def password(self) -> str:
return str(self.__config.get('database', {}).get('password', 'bemani'))
@property
def engine(self) -> Engine:
engine = self.__config.get('database', {}).get('engine')
if engine is None:
raise Exception("Config object is not instantiated properly, no SQLAlchemy engine present!")
if not isinstance(engine, Engine):
raise Exception("Config object is not instantiated properly, engine property is not a SQLAlchemy Engine!")
return engine
@property
def read_only(self) -> bool:
return bool(self.__config.get('database', {}).get('read_only', False))
class Server:
def __init__(self, parent_config: "Config") -> None:
self.__config = parent_config
@property
def address(self) -> str:
return str(self.__config.get('server', {}).get('address', '127.0.0.1'))
@property
def keepalive(self) -> str:
return str(self.__config.get('server', {}).get('keepalive', self.address))
@property
def port(self) -> int:
return int(self.__config.get('server', {}).get('port', 80))
@property
def https(self) -> bool:
return bool(self.__config.get('server', {}).get('https', False))
@property
def uri(self) -> Optional[str]:
uri = self.__config.get('server', {}).get('uri')
return str(uri) if uri else None
@property
def redirect(self) -> Optional[str]:
redirect = self.__config.get('server', {}).get('redirect')
return str(redirect) if redirect else None
@property
def enforce_pcbid(self) -> bool:
return bool(self.__config.get('server', {}).get('enforce_pcbid', False))
class Client:
def __init__(self, parent_config: "Config") -> None:
self.__config = parent_config
@property
def address(self) -> str:
address = self.__config.get('client', {}).get('address')
if address is None:
raise Exception("Config object is not instantiated properly, no client address present!")
return str(address)
class Machine:
def __init__(self, parent_config: "Config") -> None:
self.__config = parent_config
@property
def pcbid(self) -> str:
pcbid = self.__config.get('machine', {}).get('pcbid')
if pcbid is None:
raise Exception("Config object is not instantiated properly, no machine pcbid present!")
return str(pcbid)
@property
def arcade(self) -> Optional[ArcadeID]:
return self.__config.get('machine', {}).get('arcade')
class PASELI:
def __init__(self, parent_config: "Config") -> None:
self.__config = parent_config
@property
def enabled(self) -> bool:
return bool(self.__config.get('paseli', {}).get('enabled', False))
@property
def infinite(self) -> bool:
return bool(self.__config.get('paseli', {}).get('infinite', False))
class WebHooks:
def __init__(self, parent_config: "Config") -> None:
self.discord = DiscordWebHooks(parent_config)
class DiscordWebHooks:
def __init__(self, parent_config: "Config") -> None:
self.__config = parent_config
def __getitem__(self, key: GameConstants) -> Optional[str]:
uri = self.__config.get('webhooks', {}).get('discord', {}).get(key.value)
return str(uri) if uri else None
class Config(dict):
def __init__(self, existing_contents: Dict[str, Any] = {}) -> None:
super().__init__(existing_contents or {})
self.database = Database(self)
self.server = Server(self)
self.client = Client(self)
self.paseli = PASELI(self)
self.webhooks = WebHooks(self)
self.machine = Machine(self)
def clone(self) -> "Config":
# Somehow its not possible to clone this object if an instantiated Engine is present,
# so we do a little shenanigans here.
engine = self.get('database', {}).get('engine')
if engine is not None:
self['database']['engine'] = None
clone = Config(copy.deepcopy(self))
if engine is not None:
self['database']['engine'] = engine
clone['database']['engine'] = engine
return clone
@property
def filename(self) -> str:
filename = self.get('filename')
if filename is None:
raise Exception("Config object is not instantiated properly, no filename present!")
return os.path.abspath(str(filename))
@property
def support(self) -> Set[GameConstants]:
support = self.get('support')
if support is None:
raise Exception("Config object is not instantiated properly, no support list present!")
if not isinstance(support, set):
raise Exception("Config object is not instantiated properly, support property is not a Set!")
return support
@property
def secret_key(self) -> str:
return str(self.get('secret_key', 'youdidntchangethisatalldidyou?'))
@property
def name(self) -> str:
return str(self.get('name', 'e-AMUSEMENT Network'))
@property
def email(self) -> str:
return str(self.get('email', 'nobody@nowhere.com'))
@property
def cache_dir(self) -> str:
return os.path.abspath(str(self.get('cache_dir', '/tmp')))
@property
def event_log_duration(self) -> Optional[int]:
duration = self.get('event_log_duration')
return int(duration) if duration else None

View File

@ -1,5 +1,4 @@
import os
from typing import Dict, Any
import alembic.config # type: ignore
from alembic.migration import MigrationContext # type: ignore
@ -14,6 +13,7 @@ from sqlalchemy.exc import ProgrammingError # type: ignore
from bemani.data.api.user import GlobalUserData
from bemani.data.api.game import GlobalGameData
from bemani.data.api.music import GlobalMusicData
from bemani.data.config import Config
from bemani.data.mysql.base import metadata
from bemani.data.mysql.user import UserData
from bemani.data.mysql.music import MusicData
@ -86,7 +86,7 @@ class Data:
and storing data.
"""
def __init__(self, config: Dict[str, Any]) -> None:
def __init__(self, config: Config) -> None:
"""
Initializes the data object.
@ -95,7 +95,7 @@ class Data:
to initialize an internal DB connection.
"""
session_factory = sessionmaker(
bind=config['database']['engine'],
bind=config.database.engine,
autoflush=True,
autocommit=True,
)
@ -122,11 +122,11 @@ class Data:
self.triggers = Triggers(config)
@classmethod
def sqlalchemy_url(cls, config: Dict[str, Any]) -> str:
return f"mysql://{config['database']['user']}:{config['database']['password']}@{config['database']['address']}/{config['database']['database']}?charset=utf8mb4"
def sqlalchemy_url(cls, config: Config) -> str:
return f"mysql://{config.database.user}:{config.database.password}@{config.database.address}/{config.database.database}?charset=utf8mb4"
@classmethod
def create_engine(cls, config: Dict[str, Any]) -> Engine:
def create_engine(cls, config: Config) -> Engine:
return create_engine(
Data.sqlalchemy_url(config),
pool_recycle=3600,
@ -164,7 +164,7 @@ class Data:
raise DBCreateException('Tables already created, use upgrade to upgrade schema!')
metadata.create_all(
self.__config['database']['engine'].connect(),
self.__config.database.engine.connect(),
checkfirst=True,
)
@ -182,7 +182,7 @@ class Data:
raise DBCreateException('Tables have not been created yet, use create to create them!')
# Verify that there are actual changes, and refuse to create empty migration scripts
context = MigrationContext.configure(self.__config['database']['engine'].connect(), opts={'compare_type': True})
context = MigrationContext.configure(self.__config.database.engine.connect(), opts={'compare_type': True})
diff = compare_metadata(context, metadata)
if (not allow_empty) and (len(diff) == 0):
raise DBCreateException('There is nothing different between code and the DB, refusing to create migration!')

View File

@ -3,6 +3,7 @@ import random
from typing import Dict, Any, Optional
from bemani.common import Time
from bemani.data.config import Config
from sqlalchemy.engine.base import Connection # type: ignore
from sqlalchemy.engine import CursorResult # type: ignore
@ -39,7 +40,7 @@ class BaseData:
SESSION_LENGTH = 32
def __init__(self, config: Dict[str, Any], conn: Connection) -> None:
def __init__(self, config: Config, conn: Connection) -> None:
"""
Initialize any DB singleton.
@ -65,7 +66,7 @@ class BaseData:
Returns:
A SQLAlchemy CursorResult object.
"""
if self.__config['database'].get('read_only', False):
if self.__config.database.read_only:
# See if this is an insert/update/delete
for write_statement in [
"insert into ",

View File

@ -1,8 +1,9 @@
from datetime import datetime
from discord_webhook import DiscordWebhook, DiscordEmbed # type: ignore
from typing import Any, Dict
from typing import Dict
from bemani.common.constants import GameConstants, BroadcastConstants
from bemani.data.config import Config
from bemani.data.types import Song
@ -10,7 +11,7 @@ class Triggers:
"""
Class for broadcasting data to some outside service
"""
def __init__(self, config: Dict[str, Any]):
def __init__(self, config: Config) -> None:
self.config = config
def __gameconst_to_series(self, game: GameConstants) -> str:
@ -28,20 +29,20 @@ class Triggers:
def broadcast_score(self, data: Dict[BroadcastConstants, str], game: GameConstants, song: Song) -> None:
# For now we only support discord
if self.config.get('webhooks', {}).get('discord', {}).get(game, None) is not None:
if self.config.webhooks.discord[game] is not None:
self.broadcast_score_discord(data, game, song)
def broadcast_score_discord(self, data: Dict[BroadcastConstants, str], game: GameConstants, song: Song) -> None:
if game == GameConstants.IIDX:
now = datetime.now()
webhook = DiscordWebhook(url=self.config['webhooks']['discord'][game])
webhook = DiscordWebhook(url=self.config.webhooks.discord[game])
scoreembed = DiscordEmbed(title=f'New {self.__gameconst_to_series(game)} Score!', color='fbba08')
scoreembed.set_footer(text=(now.strftime('Score was recorded on %m/%d/%y at %H:%M:%S')))
# lets give it an author
song_url = f"{self.config['server']['uri']}/{game}/topscores/{song.id}" if self.config['server']['uri'] is not None else None
scoreembed.set_author(name=self.config['name'], url=song_url)
song_url = f"{self.config.server.uri}/{game.value}/topscores/{song.id}" if self.config.server.uri is not None else None
scoreembed.set_author(name=self.config.name, url=song_url)
for item, value in data.items():
inline = True
if item in {BroadcastConstants.DJ_NAME, BroadcastConstants.SONG_NAME, BroadcastConstants.ARTIST_NAME, BroadcastConstants.PLAY_STATS_HEADER}:

View File

@ -28,7 +28,7 @@ def login() -> Response:
return Response(render_template('account/login.html', **{'title': 'Log In', 'show_navigation': False, 'username': username}))
if g.data.local.user.validate_password(userid, password):
aes = AESCipher(g.config['secret_key'])
aes = AESCipher(g.config.secret_key)
sessionID = g.data.local.user.create_session(userid, expiration=90 * 86400)
response = make_response(redirect(url_for('home_pages.viewhome')))
response.set_cookie(
@ -127,7 +127,7 @@ def register() -> Response:
g.data.local.user.update_password(userid, password1)
# Now, log them into that created account!
aes = AESCipher(g.config['secret_key'])
aes = AESCipher(g.config.secret_key)
sessionID = g.data.local.user.create_session(userid)
success('Successfully registered account!')
response = make_response(redirect(url_for('home_pages.viewhome')))

View File

@ -156,9 +156,9 @@ def viewevents() -> Response:
'refresh': url_for('admin_pages.listevents', since=-1),
'backfill': url_for('admin_pages.backfillevents', until=-1),
'viewuser': url_for('admin_pages.viewuser', userid=-1),
'jubeatsong': url_for('jubeat_pages.viewtopscores', musicid=-1) if GameConstants.JUBEAT in g.config['support'] else None,
'iidxsong': url_for('iidx_pages.viewtopscores', musicid=-1) if GameConstants.IIDX in g.config['support'] else None,
'pnmsong': url_for('popn_pages.viewtopscores', musicid=-1) if GameConstants.POPN_MUSIC in g.config['support'] else None,
'jubeatsong': url_for('jubeat_pages.viewtopscores', musicid=-1) if GameConstants.JUBEAT in g.config.support else None,
'iidxsong': url_for('iidx_pages.viewtopscores', musicid=-1) if GameConstants.IIDX in g.config.support else None,
'pnmsong': url_for('popn_pages.viewtopscores', musicid=-1) if GameConstants.POPN_MUSIC in g.config.support else None,
},
)
@ -214,8 +214,8 @@ def viewarcades() -> Response:
{
'arcades': [format_arcade(arcade) for arcade in g.data.local.machine.get_all_arcades()],
'usernames': g.data.local.user.get_all_usernames(),
'paseli_enabled': g.config['paseli']['enabled'],
'paseli_infinite': g.config['paseli']['infinite'],
'paseli_enabled': g.config.paseli.enabled,
'paseli_infinite': g.config.paseli.infinite,
'mask_services_url': False,
},
{
@ -252,7 +252,7 @@ def viewmachines() -> Response:
GameConstants.SDVX.value: 'SDVX',
},
'games': games,
'enforcing': g.config['server']['enforce_pcbid'],
'enforcing': g.config.server.enforce_pcbid,
},
{
'generatepcbid': url_for('admin_pages.generatepcbid'),

View File

@ -8,7 +8,7 @@ from flask_caching import Cache # type: ignore
from functools import wraps
from bemani.common import AESCipher, GameConstants
from bemani.data import Data
from bemani.data import Config, Data
from bemani.frontend.types import g
from bemani.frontend.templates import templates_location
from bemani.frontend.static import static_location
@ -18,7 +18,7 @@ app = Flask(
template_folder=templates_location,
static_folder=static_location,
)
config: Dict[str, Any] = {}
config = Config()
@app.before_request
@ -26,7 +26,7 @@ def before_request() -> None:
global config
g.cache = Cache(app, config={
'CACHE_TYPE': 'filesystem',
'CACHE_DIR': config['cache_dir'],
'CACHE_DIR': config.cache_dir,
})
if request.endpoint in ['jsx', 'static']:
# This is just serving cached compiled frontends, skip loading from DB
@ -37,7 +37,7 @@ def before_request() -> None:
g.sessionID = None
g.userID = None
try:
aes = AESCipher(config['secret_key'])
aes = AESCipher(config.secret_key)
sessionID = aes.decrypt(request.cookies.get('SessionID'))
except Exception:
sessionID = None
@ -254,14 +254,24 @@ def navigation() -> Dict[str, Any]:
return False
# Look up the logged in user ID.
if g.userID is not None:
user = g.data.local.user.get_user(g.userID)
profiles = g.data.local.user.get_games_played(g.userID)
else:
try:
if g.userID is not None:
user = g.data.local.user.get_user(g.userID)
profiles = g.data.local.user.get_games_played(g.userID)
else:
return {
'components': components,
'any': jinja2_any,
}
except AttributeError:
# If we are trying to render a 500 error and we couldn't even run the
# before request, we won't have a userID object on g. So, just give
# up and refuse to render any navigation.
return {
'components': components,
'any': jinja2_any,
}
pages: List[Dict[str, Any]] = []
# Landing page
@ -272,7 +282,7 @@ def navigation() -> Dict[str, Any]:
},
)
if GameConstants.BISHI_BASHI in g.config['support']:
if GameConstants.BISHI_BASHI in g.config.support:
# BishiBashi pages
bishi_entries = []
if len([p for p in profiles if p[0] == GameConstants.BISHI_BASHI]) > 0:
@ -301,7 +311,7 @@ def navigation() -> Dict[str, Any]:
},
)
if GameConstants.DDR in g.config['support']:
if GameConstants.DDR in g.config.support:
# DDR pages
ddr_entries = []
if len([p for p in profiles if p[0] == GameConstants.DDR]) > 0:
@ -350,7 +360,7 @@ def navigation() -> Dict[str, Any]:
},
)
if GameConstants.IIDX in g.config['support']:
if GameConstants.IIDX in g.config.support:
# IIDX pages
iidx_entries = []
if len([p for p in profiles if p[0] == GameConstants.IIDX]) > 0:
@ -399,7 +409,7 @@ def navigation() -> Dict[str, Any]:
},
)
if GameConstants.JUBEAT in g.config['support']:
if GameConstants.JUBEAT in g.config.support:
# Jubeat pages
jubeat_entries = []
if len([p for p in profiles if p[0] == GameConstants.JUBEAT]) > 0:
@ -448,7 +458,7 @@ def navigation() -> Dict[str, Any]:
},
)
if GameConstants.MUSECA in g.config['support']:
if GameConstants.MUSECA in g.config.support:
# Museca pages
museca_entries = []
if len([p for p in profiles if p[0] == GameConstants.MUSECA]) > 0:
@ -493,7 +503,7 @@ def navigation() -> Dict[str, Any]:
},
)
if GameConstants.POPN_MUSIC in g.config['support']:
if GameConstants.POPN_MUSIC in g.config.support:
# Pop'n Music pages
popn_entries = []
if len([p for p in profiles if p[0] == GameConstants.POPN_MUSIC]) > 0:
@ -542,7 +552,7 @@ def navigation() -> Dict[str, Any]:
},
)
if GameConstants.REFLEC_BEAT in g.config['support']:
if GameConstants.REFLEC_BEAT in g.config.support:
# ReflecBeat pages
reflec_entries = []
if len([p for p in profiles if p[0] == GameConstants.REFLEC_BEAT]) > 0:
@ -591,7 +601,7 @@ def navigation() -> Dict[str, Any]:
},
)
if GameConstants.SDVX in g.config['support']:
if GameConstants.SDVX in g.config.support:
# SDVX pages
sdvx_entries = []
if len([p for p in profiles if p[0] == GameConstants.SDVX]) > 0:

View File

@ -153,7 +153,7 @@ def viewarcade(arcadeid: int) -> Response:
'balances': {balance[0]: balance[1] for balance in g.data.local.machine.get_balances(arcadeid)},
'users': {user.id: user.username for user in g.data.local.user.get_all_users()},
'events': [format_event(event) for event in g.data.local.network.get_events(arcadeid=arcadeid, event='paseli_transaction')],
'enforcing': g.config['server']['enforce_pcbid'],
'enforcing': g.config.server.enforce_pcbid,
},
{
'refresh': url_for('arcade_pages.listarcade', arcadeid=arcadeid),

View File

@ -1,10 +1,8 @@
from typing import Dict, Any
from bemani.data import Data
from bemani.data import Config, Data
class BishiBashiCache:
@classmethod
def preload(cls, data: Data, config: Dict[str, Any]) -> None:
def preload(cls, data: Data, config: Config) -> None:
pass

View File

@ -1,8 +1,6 @@
from typing import Dict, Any
from flask_caching import Cache # type: ignore
from bemani.data import Data
from bemani.data import Config, Data
from bemani.frontend.app import app
from bemani.frontend.ddr.ddr import DDRFrontend
@ -10,10 +8,10 @@ from bemani.frontend.ddr.ddr import DDRFrontend
class DDRCache:
@classmethod
def preload(cls, data: Data, config: Dict[str, Any]) -> None:
def preload(cls, data: Data, config: Config) -> None:
cache = Cache(app, config={
'CACHE_TYPE': 'filesystem',
'CACHE_DIR': config['cache_dir'],
'CACHE_DIR': config.cache_dir,
})
frontend = DDRFrontend(data, config, cache)
frontend.get_all_songs(force_db_load=True)

View File

@ -1,8 +1,6 @@
from typing import Dict, Any
from flask_caching import Cache # type: ignore
from bemani.data import Data
from bemani.data import Config, Data
from bemani.frontend.app import app
from bemani.frontend.iidx.iidx import IIDXFrontend
@ -10,10 +8,10 @@ from bemani.frontend.iidx.iidx import IIDXFrontend
class IIDXCache:
@classmethod
def preload(cls, data: Data, config: Dict[str, Any]) -> None:
def preload(cls, data: Data, config: Config) -> None:
cache = Cache(app, config={
'CACHE_TYPE': 'filesystem',
'CACHE_DIR': config['cache_dir'],
'CACHE_DIR': config.cache_dir,
})
frontend = IIDXFrontend(data, config, cache)
frontend.get_all_songs(force_db_load=True)

View File

@ -1,8 +1,6 @@
from typing import Dict, Any
from flask_caching import Cache # type: ignore
from bemani.data import Data
from bemani.data import Config, Data
from bemani.frontend.app import app
from bemani.frontend.jubeat.jubeat import JubeatFrontend
@ -10,10 +8,10 @@ from bemani.frontend.jubeat.jubeat import JubeatFrontend
class JubeatCache:
@classmethod
def preload(cls, data: Data, config: Dict[str, Any]) -> None:
def preload(cls, data: Data, config: Config) -> None:
cache = Cache(app, config={
'CACHE_TYPE': 'filesystem',
'CACHE_DIR': config['cache_dir'],
'CACHE_DIR': config.cache_dir,
})
frontend = JubeatFrontend(data, config, cache)
frontend.get_all_songs(force_db_load=True)

View File

@ -1,8 +1,6 @@
from typing import Dict, Any
from flask_caching import Cache # type: ignore
from bemani.data import Data
from bemani.data import Config, Data
from bemani.frontend.app import app
from bemani.frontend.museca.museca import MusecaFrontend
@ -10,10 +8,10 @@ from bemani.frontend.museca.museca import MusecaFrontend
class MusecaCache:
@classmethod
def preload(cls, data: Data, config: Dict[str, Any]) -> None:
def preload(cls, data: Data, config: Config) -> None:
cache = Cache(app, config={
'CACHE_TYPE': 'filesystem',
'CACHE_DIR': config['cache_dir'],
'CACHE_DIR': config.cache_dir,
})
frontend = MusecaFrontend(data, config, cache)
frontend.get_all_songs(force_db_load=True)

View File

@ -1,8 +1,6 @@
from typing import Dict, Any
from flask_caching import Cache # type: ignore
from bemani.data import Data
from bemani.data import Config, Data
from bemani.frontend.app import app
from bemani.frontend.popn.popn import PopnMusicFrontend
@ -10,10 +8,10 @@ from bemani.frontend.popn.popn import PopnMusicFrontend
class PopnMusicCache:
@classmethod
def preload(cls, data: Data, config: Dict[str, Any]) -> None:
def preload(cls, data: Data, config: Config) -> None:
cache = Cache(app, config={
'CACHE_TYPE': 'filesystem',
'CACHE_DIR': config['cache_dir'],
'CACHE_DIR': config.cache_dir,
})
frontend = PopnMusicFrontend(data, config, cache)
frontend.get_all_songs(force_db_load=True)

View File

@ -1,8 +1,6 @@
from typing import Dict, Any
from flask_caching import Cache # type: ignore
from bemani.data import Data
from bemani.data import Config, Data
from bemani.frontend.app import app
from bemani.frontend.reflec.reflec import ReflecBeatFrontend
@ -10,10 +8,10 @@ from bemani.frontend.reflec.reflec import ReflecBeatFrontend
class ReflecBeatCache:
@classmethod
def preload(cls, data: Data, config: Dict[str, Any]) -> None:
def preload(cls, data: Data, config: Config) -> None:
cache = Cache(app, config={
'CACHE_TYPE': 'filesystem',
'CACHE_DIR': config['cache_dir'],
'CACHE_DIR': config.cache_dir,
})
frontend = ReflecBeatFrontend(data, config, cache)
frontend.get_all_songs(force_db_load=True)

View File

@ -1,8 +1,6 @@
from typing import Dict, Any
from flask_caching import Cache # type: ignore
from bemani.data import Data
from bemani.data import Config, Data
from bemani.frontend.app import app
from bemani.frontend.sdvx.sdvx import SoundVoltexFrontend
@ -10,10 +8,10 @@ from bemani.frontend.sdvx.sdvx import SoundVoltexFrontend
class SoundVoltexCache:
@classmethod
def preload(cls, data: Data, config: Dict[str, Any]) -> None:
def preload(cls, data: Data, config: Config) -> None:
cache = Cache(app, config={
'CACHE_TYPE': 'filesystem',
'CACHE_DIR': config['cache_dir'],
'CACHE_DIR': config.cache_dir,
})
frontend = SoundVoltexFrontend(data, config, cache)
frontend.get_all_songs(force_db_load=True)

View File

@ -1,17 +1,17 @@
{% extends "base.html" %}
{% block content %}
<div class="section">
To change any of these settings, edit <span class="file">server.yaml</span>.
To change any of these settings, edit <span class="file">{{ config.filename }}</span>.
</div>
<div class="section">
<h3>Database Settings</h3>
<dl>
<dt>Host</dt>
<dd>{{ config['database']['address'] }}</dd>
<dd>{{ config.database.address }}</dd>
<dt>Database</dt>
<dd>{{ config['database']['database'] }}</dd>
<dd>{{ config.database.database }}</dd>
<dt>User</dt>
<dd>{{ config['database']['user'] }}</dd>
<dd>{{ config.database.user }}</dd>
<dt>Password</dt>
<dd>&bull;&bull;&bull;&bull;&bull;&bull;</dd>
</dl>
@ -20,44 +20,51 @@
<h3>Backend Settings</h3>
<dl>
<dt>Host</dt>
<dd>{{ config['server']['address'] }}</dd>
<dd>{{ config.server.address }}</dd>
<dt>Port</dt>
<dd>{{ config['server']['port'] }}</dd>
<dd>{{ config.server.port }}</dd>
<dt>HTTPS</dt>
<dd>{{ 'active' if config['server']['https'] else 'inactive' }}</dd>
<dd>{{ 'active' if config.server.https else 'inactive' }}</dd>
<dt>Keepalive Address</dt>
<dd>{{ config['server']['keepalive'] }}</dd>
<dd>{{ config.server.keepalive }}</dd>
<dt>HTTP Get Redirect Address</dt>
<dd>{{ config['server']['redirect'] if config['server']['redirect'] else 'disabled' }}</dd>
<dd>{{ config.server.redirect or 'disabled' }}</dd>
</dl>
</div>
<div class="section">
<h3>Cache Settings</h3>
<dl>
<dt>Cache Directory</dt>
<dd>{{ config.cache_dir }}</dd>
</dl>
</div>
<div class="section">
<h3>Frontend Settings</h3>
<dl>
<dt>Web Address</dt>
<dd>{{ config['server']['uri'] if config['server']['uri'] else 'http://eagate.573.jp' }}</dd>
<dd>{{ config.server.uri or 'http://eagate.573.jp' }}</dd>
<dt>Network Name</dt>
<dd>{{ config.get('name','e-AMUSEMENT Network') }}</dd>
<dd>{{ config.name }}</dd>
</dl>
</div>
<div class="section">
<h3>Data Exchange API Settings</h3>
<dl>
<dt>Administrative Email</dt>
<dd>{{ config.get('email','nobody@nowhere.com') }}</dd>
<dd>{{ config.email }}</dd>
</dl>
</div>
<div class="section">
<h3>Server Settings</h3>
<dl>
<dt>PCBID Enforcement</dt>
<dd>{{ 'active' if config['server']['enforce_pcbid'] else 'inactive' }}</dd>
<dd>{{ 'active' if config.server.enforce_pcbid else 'inactive' }}</dd>
<dt>PASELI Enabled</dt>
<dd>{{ 'yes' if config['paseli']['enabled'] else 'no' }} (can be overridden by arcade settings)</dd>
<dd>{{ 'yes' if config.paseli.enabled else 'no' }} (can be overridden by arcade settings)</dd>
<dt>Infinite PASELI Enabled</dt>
<dd>{{ 'yes' if config['paseli']['infinite'] else 'no' }} (can be overridden by arcade settings)</dd>
<dd>{{ 'yes' if config.paseli.infinite else 'no' }} (can be overridden by arcade settings)</dd>
<dt>Event Log Preservation Duration</dt>
<dd>{{ (config['event_log_duration']|string + ' seconds') if config['event_log_duration'] else 'infinite' }}</dd>
<dd>{{ (config.event_log_duration|string + ' seconds') if config.event_log_duration else 'infinite' }}</dd>
</dl>
</div>
{% endblock %}

View File

@ -1,14 +1,14 @@
from typing import Any, Dict, Optional, TYPE_CHECKING
from typing import Optional, TYPE_CHECKING
if TYPE_CHECKING:
from flask.ctx import _AppCtxGlobals
from flask_caching import Cache # type: ignore
from bemani.data import Data, UserID
from bemani.data import Config, Data, UserID
class RequestGlobals(_AppCtxGlobals):
config: Dict[str, Any]
config: Config
cache: Cache
data: Data
sessionID: Optional[str]

View File

@ -1,5 +1,6 @@
# vim: set fileencoding=utf-8
import unittest
from unittest.mock import Mock
from bemani.data.mysql.base import BaseData
@ -7,7 +8,7 @@ from bemani.data.mysql.base import BaseData
class TestBaseData(unittest.TestCase):
def test_basic_serialize(self) -> None:
data = BaseData({}, None)
data = BaseData(Mock(), None)
testdict = {
'test1': 1,
@ -23,7 +24,7 @@ class TestBaseData(unittest.TestCase):
self.assertEqual(data.deserialize(data.serialize(testdict)), testdict)
def test_basic_byte_serialize(self) -> None:
data = BaseData({}, None)
data = BaseData(Mock(), None)
testdict = {
'bytes': b'\x01\x02\x03\x04\x05',
@ -34,7 +35,7 @@ class TestBaseData(unittest.TestCase):
self.assertEqual(data.deserialize(serialized), testdict)
def test_deep_byte_serialize(self) -> None:
data = BaseData({}, None)
data = BaseData(Mock(), None)
testdict = {
'sentinal': True,

View File

@ -10,7 +10,7 @@ from bemani.tests.helpers import FakeCursor
class TestGameData(unittest.TestCase):
def test_put_time_sensitive_settings(self) -> None:
game = GameData({}, None)
game = GameData(Mock(), None)
# Verify that we catch incorrect input order
with self.assertRaises(Exception) as context:

View File

@ -27,14 +27,14 @@ class TestIIDXPendual(unittest.TestCase):
)
def test_average_no_scores(self) -> None:
base = IIDXPendual(Mock(), {}, Mock())
base = IIDXPendual(Mock(), Mock(), Mock())
self.assertEqual(
base.delta_score([], 3),
(None, None),
)
def test_average_identity(self) -> None:
base = IIDXPendual(Mock(), {}, Mock())
base = IIDXPendual(Mock(), Mock(), Mock())
self.assertEqual(
base.delta_score([
self.__make_score([10, 20, 30]),
@ -43,7 +43,7 @@ class TestIIDXPendual(unittest.TestCase):
)
def test_average_basic(self) -> None:
base = IIDXPendual(Mock(), {}, Mock())
base = IIDXPendual(Mock(), Mock(), Mock())
self.assertEqual(
base.delta_score([
self.__make_score([10, 20, 30]),
@ -53,7 +53,7 @@ class TestIIDXPendual(unittest.TestCase):
)
def test_average_complex(self) -> None:
base = IIDXPendual(Mock(), {}, Mock())
base = IIDXPendual(Mock(), Mock(), Mock())
self.assertEqual(
base.delta_score([
self.__make_score([10, 20, 30]),
@ -64,7 +64,7 @@ class TestIIDXPendual(unittest.TestCase):
)
def test_average_always_zero(self) -> None:
base = IIDXPendual(Mock(), {}, Mock())
base = IIDXPendual(Mock(), Mock(), Mock())
ex_score, ghost = base.delta_score([
self.__make_score([random.randint(0, 10) for _ in range(64)]),
self.__make_score([random.randint(0, 10) for _ in range(64)]),

View File

@ -11,7 +11,7 @@ from bemani.tests.helpers import FakeCursor
class TestNetworkData(unittest.TestCase):
def test_get_schedule_type(self) -> None:
network = NetworkData({}, None)
network = NetworkData(Mock(), None)
with freeze_time('2016-01-01 12:00'):
# Check daily schedule
@ -29,7 +29,7 @@ class TestNetworkData(unittest.TestCase):
)
def test_should_schedule(self) -> None:
network = NetworkData({}, None)
network = NetworkData(Mock(), None)
with freeze_time('2016-01-01'):
# Check for should schedule if nothing in DB

View File

@ -1,5 +1,5 @@
import yaml
from typing import Any, Dict, Set
from typing import Set
from bemani.backend.iidx import IIDXFactory
from bemani.backend.popn import PopnMusicFactory
@ -10,12 +10,13 @@ from bemani.backend.sdvx import SoundVoltexFactory
from bemani.backend.reflec import ReflecBeatFactory
from bemani.backend.museca import MusecaFactory
from bemani.common import GameConstants
from bemani.data import Data
from bemani.data import Config, Data
def load_config(filename: str, config: Dict[str, Any]) -> None:
def load_config(filename: str, config: Config) -> None:
config.update(yaml.safe_load(open(filename)))
config['database']['engine'] = Data.create_engine(config)
config['filename'] = filename
supported_series: Set[GameConstants] = set()
for series in GameConstants:
@ -24,20 +25,20 @@ def load_config(filename: str, config: Dict[str, Any]) -> None:
config['support'] = supported_series
def register_games(config: Dict[str, Any]) -> None:
if GameConstants.POPN_MUSIC in config['support']:
def register_games(config: Config) -> None:
if GameConstants.POPN_MUSIC in config.support:
PopnMusicFactory.register_all()
if GameConstants.JUBEAT in config['support']:
if GameConstants.JUBEAT in config.support:
JubeatFactory.register_all()
if GameConstants.IIDX in config['support']:
if GameConstants.IIDX in config.support:
IIDXFactory.register_all()
if GameConstants.BISHI_BASHI in config['support']:
if GameConstants.BISHI_BASHI in config.support:
BishiBashiFactory.register_all()
if GameConstants.DDR in config['support']:
if GameConstants.DDR in config.support:
DDRFactory.register_all()
if GameConstants.SDVX in config['support']:
if GameConstants.SDVX in config.support:
SoundVoltexFactory.register_all()
if GameConstants.REFLEC_BEAT in config['support']:
if GameConstants.REFLEC_BEAT in config.support:
ReflecBeatFactory.register_all()
if GameConstants.MUSECA in config['support']:
if GameConstants.MUSECA in config.support:
MusecaFactory.register_all()

View File

@ -1,19 +1,19 @@
import argparse
import getpass
import sys
from typing import Any, Dict, Optional
from typing import Optional
from bemani.data import Data, DBCreateException
from bemani.data import Config, Data, DBCreateException
from bemani.utils.config import load_config
def create(config: Dict[str, Any]) -> None:
def create(config: Config) -> None:
data = Data(config)
data.create()
data.close()
def generate(config: Dict[str, Any], message: Optional[str], allow_empty: bool) -> None:
def generate(config: Config, message: Optional[str], allow_empty: bool) -> None:
if message is None:
raise Exception('Please provide a message!')
data = Data(config)
@ -21,13 +21,13 @@ def generate(config: Dict[str, Any], message: Optional[str], allow_empty: bool)
data.close()
def upgrade(config: Dict[str, Any]) -> None:
def upgrade(config: Config) -> None:
data = Data(config)
data.upgrade()
data.close()
def change_password(config: Dict[str, Any], username: Optional[str]) -> None:
def change_password(config: Config, username: Optional[str]) -> None:
if username is None:
raise Exception('Please provide a username!')
password1 = getpass.getpass('Password: ')
@ -42,7 +42,7 @@ def change_password(config: Dict[str, Any], username: Optional[str]) -> None:
print(f'User {username} changed password.')
def add_admin(config: Dict[str, Any], username: Optional[str]) -> None:
def add_admin(config: Config, username: Optional[str]) -> None:
if username is None:
raise Exception('Please provide a username!')
data = Data(config)
@ -55,7 +55,7 @@ def add_admin(config: Dict[str, Any], username: Optional[str]) -> None:
print(f'User {username} gained admin rights.')
def remove_admin(config: Dict[str, Any], username: Optional[str]) -> None:
def remove_admin(config: Config, username: Optional[str]) -> None:
if username is None:
raise Exception('Please provide a username!')
data = Data(config)
@ -96,7 +96,7 @@ def main() -> None:
parser.add_argument("-c", "--config", help="Core configuration. Defaults to server.yaml", type=str, default="server.yaml")
args = parser.parse_args()
config: Dict[str, Any] = {}
config = Config()
load_config(args.config, config)
try:

View File

@ -25,21 +25,21 @@ def register_blueprints() -> None:
app.register_blueprint(arcade_pages)
app.register_blueprint(home_pages)
if GameConstants.IIDX in config['support']:
if GameConstants.IIDX in config.support:
app.register_blueprint(iidx_pages)
if GameConstants.POPN_MUSIC in config['support']:
if GameConstants.POPN_MUSIC in config.support:
app.register_blueprint(popn_pages)
if GameConstants.JUBEAT in config['support']:
if GameConstants.JUBEAT in config.support:
app.register_blueprint(jubeat_pages)
if GameConstants.BISHI_BASHI in config['support']:
if GameConstants.BISHI_BASHI in config.support:
app.register_blueprint(bishi_pages)
if GameConstants.DDR in config['support']:
if GameConstants.DDR in config.support:
app.register_blueprint(ddr_pages)
if GameConstants.SDVX in config['support']:
if GameConstants.SDVX in config.support:
app.register_blueprint(sdvx_pages)
if GameConstants.REFLEC_BEAT in config['support']:
if GameConstants.REFLEC_BEAT in config.support:
app.register_blueprint(reflec_pages)
if GameConstants.MUSECA in config['support']:
if GameConstants.MUSECA in config.support:
app.register_blueprint(museca_pages)
@ -51,7 +51,7 @@ def register_games() -> None:
def load_config(filename: str) -> None:
global config
base_load_config(filename, config)
app.secret_key = config['secret_key']
app.secret_key = config.secret_key
def main() -> None:

View File

@ -17,7 +17,7 @@ from typing import Any, Dict, List, Optional, Tuple
from bemani.common import GameConstants, VersionConstants, DBConstants, PEFile, Time
from bemani.format import ARC, IFS, IIDXChart, IIDXMusicDB
from bemani.data import Server, Song
from bemani.data import Config, Server, Song
from bemani.data.interfaces import APIProviderInterface
from bemani.data.api.music import GlobalMusicData
from bemani.data.api.game import GlobalGameData
@ -48,7 +48,7 @@ class ImportBase:
def __init__(
self,
config: Dict[str, Any],
config: Config,
game: GameConstants,
version: Optional[int],
no_combine: bool,
@ -59,7 +59,7 @@ class ImportBase:
self.update = update
self.no_combine = no_combine
self.__config = config
self.__engine = self.__config['database']['engine']
self.__engine = self.__config.database.engine
self.__sessionmanager = sessionmaker(self.__engine)
self.__conn = self.__engine.connect()
self.__session = self.__sessionmanager(bind=self.__conn)
@ -76,7 +76,7 @@ class ImportBase:
if not self.__batch:
raise Exception('Logic error, cannot execute outside of a batch!')
if self.__config['database'].get('read_only', False):
if self.__config.database.read_only:
# See if this is an insert/update/delete
for write_statement in [
"insert into ",
@ -359,7 +359,7 @@ class ImportPopn(ImportBase):
def __init__(
self,
config: Dict[str, Any],
config: Config,
version: str,
no_combine: bool,
update: bool,
@ -1198,7 +1198,7 @@ class ImportJubeat(ImportBase):
def __init__(
self,
config: Dict[str, Any],
config: Config,
version: str,
no_combine: bool,
update: bool,
@ -1453,7 +1453,7 @@ class ImportIIDX(ImportBase):
def __init__(
self,
config: Dict[str, Any],
config: Config,
version: str,
no_combine: bool,
update: bool,
@ -2037,7 +2037,7 @@ class ImportDDR(ImportBase):
def __init__(
self,
config: Dict[str, Any],
config: Config,
version: str,
no_combine: bool,
update: bool,
@ -2711,7 +2711,7 @@ class ImportSDVX(ImportBase):
def __init__(
self,
config: Dict[str, Any],
config: Config,
version: str,
no_combine: bool,
update: bool,
@ -3050,7 +3050,7 @@ class ImportMuseca(ImportBase):
def __init__(
self,
config: Dict[str, Any],
config: Config,
version: str,
no_combine: bool,
update: bool,
@ -3179,7 +3179,7 @@ class ImportReflecBeat(ImportBase):
def __init__(
self,
config: Dict[str, Any],
config: Config,
version: str,
no_combine: bool,
update: bool,
@ -3448,7 +3448,7 @@ class ImportDanceEvolution(ImportBase):
def __init__(
self,
config: Dict[str, Any],
config: Config,
version: str,
no_combine: bool,
update: bool,
@ -3652,7 +3652,7 @@ if __name__ == "__main__":
raise Exception("Cannot specify both a remote server and a local file to read from!")
# Load the config so we can talk to the server
config: Dict[str, Any] = {}
config = Config()
load_config(args.config, config)
series = None

View File

@ -1,5 +1,5 @@
import argparse
from typing import Any, Dict, List
from typing import Any, List
from bemani.backend.popn import PopnMusicFactory
from bemani.backend.jubeat import JubeatFactory
@ -18,38 +18,38 @@ from bemani.frontend.sdvx import SoundVoltexCache
from bemani.frontend.reflec import ReflecBeatCache
from bemani.frontend.museca import MusecaCache
from bemani.common import GameConstants, Time
from bemani.data import Data
from bemani.data import Config, Data
from bemani.utils.config import load_config
def run_scheduled_work(config: Dict[str, Any]) -> None:
def run_scheduled_work(config: Config) -> None:
data = Data(config)
# Only run scheduled work for enabled components
enabled_factories: List[Any] = []
enabled_caches: List[Any] = []
if GameConstants.IIDX in config['support']:
if GameConstants.IIDX in config.support:
enabled_factories.append(IIDXFactory)
enabled_caches.append(IIDXCache)
if GameConstants.POPN_MUSIC in config['support']:
if GameConstants.POPN_MUSIC in config.support:
enabled_factories.append(PopnMusicFactory)
enabled_caches.append(PopnMusicCache)
if GameConstants.JUBEAT in config['support']:
if GameConstants.JUBEAT in config.support:
enabled_factories.append(JubeatFactory)
enabled_caches.append(JubeatCache)
if GameConstants.BISHI_BASHI in config['support']:
if GameConstants.BISHI_BASHI in config.support:
enabled_factories.append(BishiBashiFactory)
enabled_caches.append(BishiBashiCache)
if GameConstants.DDR in config['support']:
if GameConstants.DDR in config.support:
enabled_factories.append(DDRFactory)
enabled_caches.append(DDRCache)
if GameConstants.SDVX in config['support']:
if GameConstants.SDVX in config.support:
enabled_factories.append(SoundVoltexFactory)
enabled_caches.append(SoundVoltexCache)
if GameConstants.REFLEC_BEAT in config['support']:
if GameConstants.REFLEC_BEAT in config.support:
enabled_factories.append(ReflecBeatFactory)
enabled_caches.append(ReflecBeatCache)
if GameConstants.MUSECA in config['support']:
if GameConstants.MUSECA in config.support:
enabled_factories.append(MusecaFactory)
enabled_caches.append(MusecaCache)
@ -75,7 +75,7 @@ if __name__ == '__main__':
args = parser.parse_args()
# Set up global configuration
config: Dict[str, Any] = {}
config = Config()
load_config(args.config, config)
# Run out of band work

View File

@ -1,24 +1,22 @@
import argparse
import copy
import traceback
from typing import Any, Dict
from flask import Flask, request, redirect, Response, make_response
from bemani.protocol import EAmuseProtocol
from bemani.backend import Dispatch, UnrecognizedPCBIDException
from bemani.data import Data
from bemani.data import Config, Data
from bemani.utils.config import load_config as base_load_config, register_games as base_register_games
app = Flask(__name__)
config: Dict[str, Any] = {}
config = Config()
@app.route('/', defaults={'path': ''}, methods=['GET'])
@app.route('/<path:path>', methods=['GET'])
def receive_healthcheck(path: str) -> Response:
global config
redirect_uri = config['server'].get('redirect')
redirect_uri = config.server.redirect
if redirect_uri is None:
# Return a standard status OKAY message.
return Response("Services OK.")
@ -50,7 +48,7 @@ def receive_request(path: str) -> Response:
# Create and format config
global config
requestconfig = copy.copy(config)
requestconfig = config.clone()
requestconfig['client'] = {
'address': remote_address or request.remote_addr,
}

View File

@ -1,26 +1,27 @@
database:
# IP or DNS entry for MySQL instance
# IP or DNS entry for MySQL instance.
address: "localhost"
# Database that will be used
# Database that will be used.
database: "bemani"
# User who has full credentials to the above DB
# User who has full credentials to the above DB.
user: "bemani"
# Password of said user
# Password of said user.
password: "bemani"
server:
# Advertised server IP or DNS entry games will connect to
# Advertised server IP or DNS entry games will connect to.
address: "192.168.0.1"
# Advertised keepalive address, must be globally pingable
# Advertised keepalive address, must be globally pingable. Delete
# this to use the address above instead of a unique keepalive address.
keepalive: "127.0.0.1"
# What port games will connect to
# What port on the above address games will connect to.
port: 80
# Whether games should connect over HTTPS
# Whether games should connect over HTTPS.
https: False
# Advertised frontend URI. Delete this to mask the frontend address.
uri: "https://eagate.573.jp"
# URI that users hitting the GET interface will be redirected to.
# Delete this to return an HTTP error instead.
# Delete this to return an HTTP error instead of redirecting.
redirect: "https://eagate.573.jp"
# Whether PCBIDs must be added to the network before games will work.
enforce_pcbid: False
@ -39,31 +40,31 @@ paseli:
infinite: True
support:
# Bishi Bashi frontend/backend enabled
# Bishi Bashi frontend/backend enabled.
bishi: True
# DDR frontend/backend enabled
# DDR frontend/backend enabled.
ddr: True
# IIDX frontend/backend enabled
# IIDX frontend/backend enabled.
iidx: True
# Jubeat frontend/backend enabled
# Jubeat frontend/backend enabled.
jubeat: True
# Museca frontend/backend enabled
# Museca frontend/backend enabled.
museca: True
# Pop'n Music frontend/backend enabled
# Pop'n Music frontend/backend enabled.
pnm: True
# Reflec Beat frontend/backend enabled
# Reflec Beat frontend/backend enabled.
reflec: True
# SDVX frontend/backend enabled
# SDVX frontend/backend enabled.
sdvx: True
# Key used to encrypt cookies, should be unique per instance
# Key used to encrypt cookies, should be unique per network instance.
secret_key: 'this_is_a_secret_please_change_me'
# Name of this network
# Name of this network.
name: 'e-AMUSEMENT Network'
# Administrative contact for this network
# Administrative contact for this network.
email: 'nobody@nowhere.com'
# Cache DIR, should point somewhere other than /tmp for production instances
# Cache DIR, should point somewhere other than /tmp for production instances.
cache_dir: '/tmp'
# Number of seconds to preserve event logs before deleting them.
# Set to zero to disable deleting logs.
# Set to zero or delete to disable deleting logs.
event_log_duration: 2592000