Add config, database and user interface to change network region as well as per-arcade region. Also unified IIDX prefecture setting.
This commit is contained in:
parent
beb818f42b
commit
d05c3f907d
@ -1,7 +1,7 @@
|
|||||||
from bemani.common.model import Model
|
from bemani.common.model import Model
|
||||||
from bemani.common.validateddict import ValidatedDict, Profile, PlayStatistics, intish
|
from bemani.common.validateddict import ValidatedDict, Profile, PlayStatistics, intish
|
||||||
from bemani.common.http import HTTP
|
from bemani.common.http import HTTP
|
||||||
from bemani.common.constants import APIConstants, GameConstants, VersionConstants, DBConstants, BroadcastConstants
|
from bemani.common.constants import APIConstants, GameConstants, VersionConstants, DBConstants, BroadcastConstants, RegionConstants
|
||||||
from bemani.common.card import CardCipher, CardCipherException
|
from bemani.common.card import CardCipher, CardCipherException
|
||||||
from bemani.common.id import ID
|
from bemani.common.id import ID
|
||||||
from bemani.common.aes import AESCipher
|
from bemani.common.aes import AESCipher
|
||||||
@ -21,6 +21,7 @@ __all__ = [
|
|||||||
"VersionConstants",
|
"VersionConstants",
|
||||||
"DBConstants",
|
"DBConstants",
|
||||||
"BroadcastConstants",
|
"BroadcastConstants",
|
||||||
|
"RegionConstants",
|
||||||
"CardCipher",
|
"CardCipher",
|
||||||
"CardCipherException",
|
"CardCipherException",
|
||||||
"ID",
|
"ID",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from typing import Dict
|
||||||
from typing_extensions import Final
|
from typing_extensions import Final
|
||||||
|
|
||||||
|
|
||||||
@ -322,3 +323,206 @@ class BroadcastConstants(Enum):
|
|||||||
COOLS: Final[str] = 'Cools'
|
COOLS: Final[str] = 'Cools'
|
||||||
COMBO: Final[str] = 'Combo'
|
COMBO: Final[str] = 'Combo'
|
||||||
MEDAL: Final[str] = 'Medal'
|
MEDAL: Final[str] = 'Medal'
|
||||||
|
|
||||||
|
|
||||||
|
class _RegionConstants:
|
||||||
|
"""
|
||||||
|
Class representing the various region IDs found in all games.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# The following are the original enumerations, that still are correct
|
||||||
|
# for new games today.
|
||||||
|
HOKKAIDO: Final[int] = 1
|
||||||
|
AOMORI: Final[int] = 2
|
||||||
|
IWATE: Final[int] = 3
|
||||||
|
MIYAGI: Final[int] = 4
|
||||||
|
AKITA: Final[int] = 5
|
||||||
|
YAMAGATA: Final[int] = 6
|
||||||
|
FUKUSHIMA: Final[int] = 7
|
||||||
|
IBARAKI: Final[int] = 8
|
||||||
|
TOCHIGI: Final[int] = 9
|
||||||
|
GUNMA: Final[int] = 10
|
||||||
|
SAITAMA: Final[int] = 11
|
||||||
|
CHIBA: Final[int] = 12
|
||||||
|
TOKYO: Final[int] = 13
|
||||||
|
KANAGAWA: Final[int] = 14
|
||||||
|
NIIGATA: Final[int] = 15
|
||||||
|
TOYAMA: Final[int] = 16
|
||||||
|
ISHIKAWA: Final[int] = 17
|
||||||
|
FUKUI: Final[int] = 18
|
||||||
|
YAMANASHI: Final[int] = 19
|
||||||
|
NAGANO: Final[int] = 20
|
||||||
|
GIFU: Final[int] = 21
|
||||||
|
SHIZUOKA: Final[int] = 22
|
||||||
|
AICHI: Final[int] = 23
|
||||||
|
MIE: Final[int] = 24
|
||||||
|
SHIGA: Final[int] = 25
|
||||||
|
KYOTO: Final[int] = 26
|
||||||
|
OSAKA: Final[int] = 27
|
||||||
|
HYOGO: Final[int] = 28
|
||||||
|
NARA: Final[int] = 29
|
||||||
|
WAKAYAMA: Final[int] = 30
|
||||||
|
TOTTORI: Final[int] = 31
|
||||||
|
SHIMANE: Final[int] = 32
|
||||||
|
OKAYAMA: Final[int] = 33
|
||||||
|
HIROSHIMA: Final[int] = 34
|
||||||
|
YAMAGUCHI: Final[int] = 35
|
||||||
|
TOKUSHIMA: Final[int] = 36
|
||||||
|
KAGAWA: Final[int] = 37
|
||||||
|
EHIME: Final[int] = 38
|
||||||
|
KOUCHI: Final[int] = 39
|
||||||
|
FUKUOKA: Final[int] = 40
|
||||||
|
SAGA: Final[int] = 41
|
||||||
|
NAGASAKI: Final[int] = 42
|
||||||
|
KUMAMOTO: Final[int] = 43
|
||||||
|
OITA: Final[int] = 44
|
||||||
|
MIYAZAKI: Final[int] = 45
|
||||||
|
KAGOSHIMA: Final[int] = 46
|
||||||
|
OKINAWA: Final[int] = 47
|
||||||
|
HONG_KONG: Final[int] = 48
|
||||||
|
KOREA: Final[int] = 49
|
||||||
|
TAIWAN: Final[int] = 50
|
||||||
|
|
||||||
|
# The following are new additions, replacing the "OLD" values below.
|
||||||
|
THAILAND: Final[int] = 51
|
||||||
|
INDONESIA: Final[int] = 52
|
||||||
|
SINGAPORE: Final[int] = 53
|
||||||
|
PHILLIPINES: Final[int] = 54
|
||||||
|
MACAO: Final[int] = 55
|
||||||
|
USA: Final[int] = 56
|
||||||
|
OTHER: Final[int] = 57
|
||||||
|
|
||||||
|
# Bogus value for europe.
|
||||||
|
EUROPE: Final[int] = 1000
|
||||||
|
NO_MAPPING: Final[int] = 2000
|
||||||
|
|
||||||
|
# Old constant values.
|
||||||
|
OLD_USA: Final[int] = 51
|
||||||
|
OLD_EUROPE: Final[int] = 52
|
||||||
|
OLD_OTHER: Final[int] = 53
|
||||||
|
|
||||||
|
# Min/max valid values for server.
|
||||||
|
MIN: Final[int] = 1
|
||||||
|
MAX: Final[int] = 56
|
||||||
|
|
||||||
|
# This is a really nasty LUT to attempt to make the frontend display
|
||||||
|
# the same regardless of the game in question. This is mostly because
|
||||||
|
# the prefecture/region stored in the profile is editable by IIDX and
|
||||||
|
# I didn't anticipate this ever changing.
|
||||||
|
def db_to_game_region(self, use_new_table: bool, region: int) -> int:
|
||||||
|
if use_new_table:
|
||||||
|
# The new lookup table does not have Europe as an option.
|
||||||
|
if region in {RegionConstants.EUROPE, RegionConstants.NO_MAPPING}:
|
||||||
|
return RegionConstants.OTHER
|
||||||
|
|
||||||
|
# The rest matches what we have already.
|
||||||
|
return region
|
||||||
|
else:
|
||||||
|
# The old lookup table supports most of the values.
|
||||||
|
if region <= RegionConstants.TAIWAN:
|
||||||
|
return region
|
||||||
|
|
||||||
|
# Map the two values that still exist back to their old values.
|
||||||
|
if region == RegionConstants.USA:
|
||||||
|
return RegionConstants.OLD_USA
|
||||||
|
if region == RegionConstants.EUROPE:
|
||||||
|
return RegionConstants.OLD_EUROPE
|
||||||
|
|
||||||
|
# The rest get mapped to other.
|
||||||
|
return RegionConstants.OLD_OTHER
|
||||||
|
|
||||||
|
# This performs the equivalent inverse of the above function. Note that
|
||||||
|
# depending on the game and selection, this is lossy (as in, Europe could
|
||||||
|
# get converted to Other, etc).
|
||||||
|
def game_to_db_region(self, use_new_table: bool, region: int) -> int:
|
||||||
|
if use_new_table:
|
||||||
|
if region == RegionConstants.OTHER:
|
||||||
|
return RegionConstants.NO_MAPPING
|
||||||
|
|
||||||
|
# The new lookup table is correct aside from the above correction.
|
||||||
|
return region
|
||||||
|
else:
|
||||||
|
# The old lookup table supports most of the values.
|
||||||
|
if region <= RegionConstants.TAIWAN:
|
||||||
|
return region
|
||||||
|
|
||||||
|
# Map the three values that might be seen to new DB values.
|
||||||
|
if region == RegionConstants.OLD_USA:
|
||||||
|
return RegionConstants.USA
|
||||||
|
if region == RegionConstants.OLD_EUROPE:
|
||||||
|
return RegionConstants.EUROPE
|
||||||
|
if region == RegionConstants.OLD_OTHER:
|
||||||
|
return RegionConstants.NO_MAPPING
|
||||||
|
|
||||||
|
raise Exception(f"Unexpected value {region} for game region!")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def LUT(cls) -> Dict[int, str]:
|
||||||
|
return {
|
||||||
|
cls.HOKKAIDO: '北海道 (Hokkaido)',
|
||||||
|
cls.AOMORI: '青森県 (Aomori)',
|
||||||
|
cls.IWATE: '岩手県 (Iwate)',
|
||||||
|
cls.MIYAGI: '宮城県 (Miyagi)',
|
||||||
|
cls.AKITA: '秋田県 (Akita)',
|
||||||
|
cls.YAMAGATA: '山形県 (Yamagata)',
|
||||||
|
cls.FUKUSHIMA: '福島県 (Fukushima)',
|
||||||
|
cls.IBARAKI: '茨城県 (Ibaraki)',
|
||||||
|
cls.TOCHIGI: '栃木県 (Tochigi)',
|
||||||
|
cls.GUNMA: '群馬県 (Gunma)',
|
||||||
|
cls.SAITAMA: '埼玉県 (Saitama)',
|
||||||
|
cls.CHIBA: '千葉県 (Chiba)',
|
||||||
|
cls.TOKYO: '東京都 (Tokyo)',
|
||||||
|
cls.KANAGAWA: '神奈川県 (Kanagawa)',
|
||||||
|
cls.NIIGATA: '新潟県 (Niigata)',
|
||||||
|
cls.TOYAMA: '富山県 (Toyama)',
|
||||||
|
cls.ISHIKAWA: '石川県 (Ishikawa)',
|
||||||
|
cls.FUKUI: '福井県 (Fukui)',
|
||||||
|
cls.YAMANASHI: '山梨県 (Yamanashi)',
|
||||||
|
cls.NAGANO: '長野県 (Nagano)',
|
||||||
|
cls.GIFU: '岐阜県 (Gifu)',
|
||||||
|
cls.SHIZUOKA: '静岡県 (Shizuoka)',
|
||||||
|
cls.AICHI: '愛知県 (Aichi)',
|
||||||
|
cls.MIE: '三重県 (Mie)',
|
||||||
|
cls.SHIGA: '滋賀県 (Shiga)',
|
||||||
|
cls.KYOTO: '京都府 (Kyoto)',
|
||||||
|
cls.OSAKA: '大阪府 (Osaka)',
|
||||||
|
cls.HYOGO: '兵庫県 (Hyogo)',
|
||||||
|
cls.NARA: '奈良県 (Nara)',
|
||||||
|
cls.WAKAYAMA: '和歌山県 (Wakayama)',
|
||||||
|
cls.TOTTORI: '鳥取県 (Tottori)',
|
||||||
|
cls.SHIMANE: '島根県 (Shimane)',
|
||||||
|
cls.OKAYAMA: '岡山県 (Okayama)',
|
||||||
|
cls.HIROSHIMA: '広島県 (Hiroshima)',
|
||||||
|
cls.YAMAGUCHI: '山口県 (Yamaguchi)',
|
||||||
|
cls.TOKUSHIMA: '徳島県 (Tokushima)',
|
||||||
|
cls.KAGAWA: '香川県 (Kagawa)',
|
||||||
|
cls.EHIME: '愛媛県 (Ehime)',
|
||||||
|
cls.KOUCHI: '高知県 (Kochi)',
|
||||||
|
cls.FUKUOKA: '福岡県 (Fukuoka)',
|
||||||
|
cls.SAGA: '佐賀県 (Saga)',
|
||||||
|
cls.NAGASAKI: '長崎県 (Nagasaki)',
|
||||||
|
cls.KUMAMOTO: '熊本県 (Kumamoto)',
|
||||||
|
cls.OITA: '大分県 (Oita)',
|
||||||
|
cls.MIYAZAKI: '宮崎県 (Miyazaki)',
|
||||||
|
cls.KAGOSHIMA: '鹿児島県 (Kagoshima)',
|
||||||
|
cls.OKINAWA: '沖縄県 (Okinawa)',
|
||||||
|
cls.HONG_KONG: '香港 (Hong Kong)',
|
||||||
|
cls.KOREA: '韓国 (Korea)',
|
||||||
|
cls.TAIWAN: '台湾 (Taiwan)',
|
||||||
|
|
||||||
|
# The following are different depending on the version of the game,
|
||||||
|
# so we choose the new value.
|
||||||
|
cls.THAILAND: "タイ (Thailand)",
|
||||||
|
cls.INDONESIA: "インドネシア (Indonesia)",
|
||||||
|
cls.SINGAPORE: "シンガポール (Singapore)",
|
||||||
|
cls.PHILLIPINES: "フィリピン (Phillipines)",
|
||||||
|
cls.MACAO: "マカオ (Macao)",
|
||||||
|
cls.USA: "アメリカ (USA)",
|
||||||
|
cls.EUROPE: '欧州 (Europe)',
|
||||||
|
cls.NO_MAPPING: "海外 (Other)",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# This is just so I can use the defined constants inside a LUT
|
||||||
|
# without having the LUT itself outside the class.
|
||||||
|
RegionConstants = _RegionConstants()
|
||||||
|
@ -3,7 +3,7 @@ import os
|
|||||||
from sqlalchemy.engine import Engine # type: ignore
|
from sqlalchemy.engine import Engine # type: ignore
|
||||||
from typing import Any, Dict, Optional, Set
|
from typing import Any, Dict, Optional, Set
|
||||||
|
|
||||||
from bemani.common.constants import GameConstants
|
from bemani.common import GameConstants, RegionConstants
|
||||||
from bemani.data.types import ArcadeID
|
from bemani.data.types import ArcadeID
|
||||||
|
|
||||||
|
|
||||||
@ -79,6 +79,18 @@ class Server:
|
|||||||
def pcbid_self_grant_limit(self) -> int:
|
def pcbid_self_grant_limit(self) -> int:
|
||||||
return int(self.__config.get('server', {}).get('pcbid_self_grant_limit', 0))
|
return int(self.__config.get('server', {}).get('pcbid_self_grant_limit', 0))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def region(self) -> int:
|
||||||
|
region = int(self.__config.get('server', {}).get('region', RegionConstants.USA))
|
||||||
|
if region in {RegionConstants.EUROPE, RegionConstants.NO_MAPPING}:
|
||||||
|
# Bogus values we support.
|
||||||
|
return region
|
||||||
|
if region < RegionConstants.MIN or region > RegionConstants.MAX:
|
||||||
|
# Pick the original default for the network (USA).
|
||||||
|
return RegionConstants.USA
|
||||||
|
# Region was fine.
|
||||||
|
return region
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self, parent_config: "Config") -> None:
|
def __init__(self, parent_config: "Config") -> None:
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
"""Add region column to arcade settings.
|
||||||
|
|
||||||
|
Revision ID: a1f4a09a1f90
|
||||||
|
Revises: 36dff3ac15a3
|
||||||
|
Create Date: 2021-09-06 22:01:29.905538
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.sql import text
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a1f4a09a1f90'
|
||||||
|
down_revision = '36dff3ac15a3'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('arcade', sa.Column('pref', sa.Integer(), nullable=False))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
conn = op.get_bind()
|
||||||
|
|
||||||
|
# Set a sane default for all current arcades.
|
||||||
|
sql = "UPDATE arcade SET pref = 56"
|
||||||
|
conn.execute(text(sql), {})
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('arcade', 'pref')
|
||||||
|
# ### end Alembic commands ###
|
@ -39,6 +39,7 @@ arcade = Table(
|
|||||||
Column('name', String(255), nullable=False),
|
Column('name', String(255), nullable=False),
|
||||||
Column('description', String(255), nullable=False),
|
Column('description', String(255), nullable=False),
|
||||||
Column('pin', String(8), nullable=False),
|
Column('pin', String(8), nullable=False),
|
||||||
|
Column('pref', Integer, nullable=False),
|
||||||
Column('data', JSON),
|
Column('data', JSON),
|
||||||
mysql_charset='utf8mb4',
|
mysql_charset='utf8mb4',
|
||||||
)
|
)
|
||||||
@ -288,7 +289,7 @@ class MachineData(BaseData):
|
|||||||
sql = "DELETE FROM `machine` WHERE pcbid = :pcbid LIMIT 1"
|
sql = "DELETE FROM `machine` WHERE pcbid = :pcbid LIMIT 1"
|
||||||
self.execute(sql, {'pcbid': pcbid})
|
self.execute(sql, {'pcbid': pcbid})
|
||||||
|
|
||||||
def create_arcade(self, name: str, description: str, data: Dict[str, Any], owners: List[UserID]) -> Arcade:
|
def create_arcade(self, name: str, description: str, region: int, data: Dict[str, Any], owners: List[UserID]) -> Arcade:
|
||||||
"""
|
"""
|
||||||
Given a set of values, create a new arcade and return the ID of that arcade.
|
Given a set of values, create a new arcade and return the ID of that arcade.
|
||||||
|
|
||||||
@ -296,14 +297,15 @@ class MachineData(BaseData):
|
|||||||
An Arcade object representing this arcade
|
An Arcade object representing this arcade
|
||||||
"""
|
"""
|
||||||
sql = (
|
sql = (
|
||||||
"INSERT INTO arcade (name, description, data, pin) " +
|
"INSERT INTO arcade (name, description, pref, data, pin) " +
|
||||||
"VALUES (:name, :desc, :data, '00000000')"
|
"VALUES (:name, :desc, :pref, :data, '00000000')"
|
||||||
)
|
)
|
||||||
cursor = self.execute(
|
cursor = self.execute(
|
||||||
sql,
|
sql,
|
||||||
{
|
{
|
||||||
'name': name,
|
'name': name,
|
||||||
'desc': description,
|
'desc': description,
|
||||||
|
'pref': region,
|
||||||
'data': self.serialize(data),
|
'data': self.serialize(data),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -329,7 +331,7 @@ class MachineData(BaseData):
|
|||||||
An Arcade object if this arcade was found, or None otherwise.
|
An Arcade object if this arcade was found, or None otherwise.
|
||||||
"""
|
"""
|
||||||
sql = (
|
sql = (
|
||||||
"SELECT name, description, pin, data FROM arcade WHERE id = :id"
|
"SELECT name, description, pin, pref, data FROM arcade WHERE id = :id"
|
||||||
)
|
)
|
||||||
cursor = self.execute(sql, {'id': arcadeid})
|
cursor = self.execute(sql, {'id': arcadeid})
|
||||||
if cursor.rowcount != 1:
|
if cursor.rowcount != 1:
|
||||||
@ -346,6 +348,7 @@ class MachineData(BaseData):
|
|||||||
result['name'],
|
result['name'],
|
||||||
result['description'],
|
result['description'],
|
||||||
result['pin'],
|
result['pin'],
|
||||||
|
result['pref'],
|
||||||
self.deserialize(result['data']),
|
self.deserialize(result['data']),
|
||||||
[owner['userid'] for owner in cursor.fetchall()],
|
[owner['userid'] for owner in cursor.fetchall()],
|
||||||
)
|
)
|
||||||
@ -360,7 +363,7 @@ class MachineData(BaseData):
|
|||||||
# Update machine name based on game
|
# Update machine name based on game
|
||||||
sql = (
|
sql = (
|
||||||
"UPDATE `arcade` " +
|
"UPDATE `arcade` " +
|
||||||
"SET name = :name, description = :desc, pin = :pin, data = :data " +
|
"SET name = :name, description = :desc, pin = :pin, pref = :pref, data = :data " +
|
||||||
"WHERE id = :arcadeid"
|
"WHERE id = :arcadeid"
|
||||||
)
|
)
|
||||||
self.execute(
|
self.execute(
|
||||||
@ -369,6 +372,7 @@ class MachineData(BaseData):
|
|||||||
'name': arcade.name,
|
'name': arcade.name,
|
||||||
'desc': arcade.description,
|
'desc': arcade.description,
|
||||||
'pin': arcade.pin,
|
'pin': arcade.pin,
|
||||||
|
'pref': arcade.region,
|
||||||
'data': self.serialize(arcade.data),
|
'data': self.serialize(arcade.data),
|
||||||
'arcadeid': arcade.id,
|
'arcadeid': arcade.id,
|
||||||
},
|
},
|
||||||
@ -411,7 +415,7 @@ class MachineData(BaseData):
|
|||||||
arcade_to_owners[arcade] = []
|
arcade_to_owners[arcade] = []
|
||||||
arcade_to_owners[arcade].append(owner)
|
arcade_to_owners[arcade].append(owner)
|
||||||
|
|
||||||
sql = "SELECT id, name, description, pin, data FROM arcade"
|
sql = "SELECT id, name, description, pin, pref, data FROM arcade"
|
||||||
cursor = self.execute(sql)
|
cursor = self.execute(sql)
|
||||||
return [
|
return [
|
||||||
Arcade(
|
Arcade(
|
||||||
@ -419,6 +423,7 @@ class MachineData(BaseData):
|
|||||||
result['name'],
|
result['name'],
|
||||||
result['description'],
|
result['description'],
|
||||||
result['pin'],
|
result['pin'],
|
||||||
|
result['pref'],
|
||||||
self.deserialize(result['data']),
|
self.deserialize(result['data']),
|
||||||
arcade_to_owners.get(result['id'], []),
|
arcade_to_owners.get(result['id'], []),
|
||||||
) for result in cursor.fetchall()
|
) for result in cursor.fetchall()
|
||||||
|
@ -144,7 +144,7 @@ class Arcade:
|
|||||||
crediting accounts. Machines belong to either no arcade or a single arcase.
|
crediting accounts. Machines belong to either no arcade or a single arcase.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, arcadeid: ArcadeID, name: str, description: str, pin: str, data: Dict[str, Any], owners: List[UserID]) -> None:
|
def __init__(self, arcadeid: ArcadeID, name: str, description: str, pin: str, region: int, data: Dict[str, Any], owners: List[UserID]) -> None:
|
||||||
"""
|
"""
|
||||||
Initialize the arcade instance.
|
Initialize the arcade instance.
|
||||||
|
|
||||||
@ -153,6 +153,7 @@ class Arcade:
|
|||||||
name - The name of the arcade.
|
name - The name of the arcade.
|
||||||
description - The description of the arcade.
|
description - The description of the arcade.
|
||||||
pin - An eight digit string representing the PIN used to pull up PASELI info.
|
pin - An eight digit string representing the PIN used to pull up PASELI info.
|
||||||
|
region - An integer representing the region this arcade is in.
|
||||||
data - A dictionary of settings for this arcade.
|
data - A dictionary of settings for this arcade.
|
||||||
owners - An list of integers specifying the user IDs of owners for this arcade.
|
owners - An list of integers specifying the user IDs of owners for this arcade.
|
||||||
"""
|
"""
|
||||||
@ -160,11 +161,12 @@ class Arcade:
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.description = description
|
self.description = description
|
||||||
self.pin = pin
|
self.pin = pin
|
||||||
|
self.region = region
|
||||||
self.data = ValidatedDict(data)
|
self.data = ValidatedDict(data)
|
||||||
self.owners = owners
|
self.owners = owners
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"Arcade(arcadeid={self.id}, name={self.name}, description={self.description}, pin={self.pin}, data={self.data}, owners={self.owners})"
|
return f"Arcade(arcadeid={self.id}, name={self.name}, description={self.description}, pin={self.pin}, region={self.region}, data={self.data}, owners={self.owners})"
|
||||||
|
|
||||||
|
|
||||||
class Song:
|
class Song:
|
||||||
|
@ -3,7 +3,7 @@ from typing import Dict, Tuple, Any, Optional
|
|||||||
from flask import Blueprint, request, Response, render_template, url_for
|
from flask import Blueprint, request, Response, render_template, url_for
|
||||||
|
|
||||||
from bemani.backend.base import Base
|
from bemani.backend.base import Base
|
||||||
from bemani.common import CardCipher, CardCipherException, GameConstants
|
from bemani.common import CardCipher, CardCipherException, GameConstants, RegionConstants
|
||||||
from bemani.data import Arcade, Machine, User, UserID, News, Event, Server, Client
|
from bemani.data import Arcade, Machine, User, UserID, News, Event, Server, Client
|
||||||
from bemani.data.api.client import APIClient, NotAuthorizedAPIException, APIException
|
from bemani.data.api.client import APIClient, NotAuthorizedAPIException, APIException
|
||||||
from bemani.frontend.app import adminrequired, jsonify, valid_email, valid_username, valid_pin, render_react
|
from bemani.frontend.app import adminrequired, jsonify, valid_email, valid_username, valid_pin, render_react
|
||||||
@ -33,6 +33,7 @@ def format_arcade(arcade: Arcade) -> Dict[str, Any]:
|
|||||||
'id': arcade.id,
|
'id': arcade.id,
|
||||||
'name': arcade.name,
|
'name': arcade.name,
|
||||||
'description': arcade.description,
|
'description': arcade.description,
|
||||||
|
'region': arcade.region,
|
||||||
'paseli_enabled': arcade.data.get_bool('paseli_enabled'),
|
'paseli_enabled': arcade.data.get_bool('paseli_enabled'),
|
||||||
'paseli_infinite': arcade.data.get_bool('paseli_infinite'),
|
'paseli_infinite': arcade.data.get_bool('paseli_infinite'),
|
||||||
'mask_services_url': arcade.data.get_bool('mask_services_url'),
|
'mask_services_url': arcade.data.get_bool('mask_services_url'),
|
||||||
@ -128,6 +129,7 @@ def viewsettings() -> Response:
|
|||||||
**{
|
**{
|
||||||
'title': 'Network Settings',
|
'title': 'Network Settings',
|
||||||
'config': g.config,
|
'config': g.config,
|
||||||
|
'region': RegionConstants.LUT,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -213,9 +215,11 @@ def viewarcades() -> Response:
|
|||||||
'admin/arcades.react.js',
|
'admin/arcades.react.js',
|
||||||
{
|
{
|
||||||
'arcades': [format_arcade(arcade) for arcade in g.data.local.machine.get_all_arcades()],
|
'arcades': [format_arcade(arcade) for arcade in g.data.local.machine.get_all_arcades()],
|
||||||
|
'regions': RegionConstants.LUT,
|
||||||
'usernames': g.data.local.user.get_all_usernames(),
|
'usernames': g.data.local.user.get_all_usernames(),
|
||||||
'paseli_enabled': g.config.paseli.enabled,
|
'paseli_enabled': g.config.paseli.enabled,
|
||||||
'paseli_infinite': g.config.paseli.infinite,
|
'paseli_infinite': g.config.paseli.infinite,
|
||||||
|
'default_region': g.config.server.region,
|
||||||
'mask_services_url': False,
|
'mask_services_url': False,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -402,6 +406,7 @@ def updatearcade() -> Dict[str, Any]:
|
|||||||
|
|
||||||
arcade.name = new_values['name']
|
arcade.name = new_values['name']
|
||||||
arcade.description = new_values['description']
|
arcade.description = new_values['description']
|
||||||
|
arcade.region = new_values['region']
|
||||||
arcade.data.replace_bool('paseli_enabled', new_values['paseli_enabled'])
|
arcade.data.replace_bool('paseli_enabled', new_values['paseli_enabled'])
|
||||||
arcade.data.replace_bool('paseli_infinite', new_values['paseli_infinite'])
|
arcade.data.replace_bool('paseli_infinite', new_values['paseli_infinite'])
|
||||||
arcade.data.replace_bool('mask_services_url', new_values['mask_services_url'])
|
arcade.data.replace_bool('mask_services_url', new_values['mask_services_url'])
|
||||||
@ -441,6 +446,7 @@ def addarcade() -> Dict[str, Any]:
|
|||||||
g.data.local.machine.create_arcade(
|
g.data.local.machine.create_arcade(
|
||||||
new_values['name'],
|
new_values['name'],
|
||||||
new_values['description'],
|
new_values['description'],
|
||||||
|
new_values['region'],
|
||||||
{
|
{
|
||||||
'paseli_enabled': new_values['paseli_enabled'],
|
'paseli_enabled': new_values['paseli_enabled'],
|
||||||
'paseli_infinite': new_values['paseli_infinite'],
|
'paseli_infinite': new_values['paseli_infinite'],
|
||||||
|
@ -3,7 +3,7 @@ from typing import Any, Dict, List, Optional
|
|||||||
from flask import Blueprint, request, Response, abort, url_for
|
from flask import Blueprint, request, Response, abort, url_for
|
||||||
|
|
||||||
from bemani.backend.base import Base
|
from bemani.backend.base import Base
|
||||||
from bemani.common import CardCipher, CardCipherException, ValidatedDict, GameConstants
|
from bemani.common import CardCipher, CardCipherException, ValidatedDict, GameConstants, RegionConstants
|
||||||
from bemani.data import Arcade, ArcadeID, Event, Machine
|
from bemani.data import Arcade, ArcadeID, Event, Machine
|
||||||
from bemani.frontend.app import loginrequired, jsonify, render_react, valid_pin
|
from bemani.frontend.app import loginrequired, jsonify, render_react, valid_pin
|
||||||
from bemani.frontend.templates import templates_location
|
from bemani.frontend.templates import templates_location
|
||||||
@ -66,6 +66,7 @@ def format_arcade(arcade: Arcade) -> Dict[str, Any]:
|
|||||||
'name': arcade.name,
|
'name': arcade.name,
|
||||||
'description': arcade.description,
|
'description': arcade.description,
|
||||||
'pin': arcade.pin,
|
'pin': arcade.pin,
|
||||||
|
'region': arcade.region,
|
||||||
'paseli_enabled': arcade.data.get_bool('paseli_enabled'),
|
'paseli_enabled': arcade.data.get_bool('paseli_enabled'),
|
||||||
'paseli_infinite': arcade.data.get_bool('paseli_infinite'),
|
'paseli_infinite': arcade.data.get_bool('paseli_infinite'),
|
||||||
'mask_services_url': arcade.data.get_bool('mask_services_url'),
|
'mask_services_url': arcade.data.get_bool('mask_services_url'),
|
||||||
@ -155,6 +156,7 @@ def viewarcade(arcadeid: int) -> Response:
|
|||||||
'arcade/arcade.react.js',
|
'arcade/arcade.react.js',
|
||||||
{
|
{
|
||||||
'arcade': format_arcade(arcade),
|
'arcade': format_arcade(arcade),
|
||||||
|
'regions': RegionConstants.LUT,
|
||||||
'machines': machines,
|
'machines': machines,
|
||||||
'game_settings': get_game_settings(arcade),
|
'game_settings': get_game_settings(arcade),
|
||||||
'balances': {balance[0]: balance[1] for balance in g.data.local.machine.get_balances(arcadeid)},
|
'balances': {balance[0]: balance[1] for balance in g.data.local.machine.get_balances(arcadeid)},
|
||||||
@ -172,6 +174,7 @@ def viewarcade(arcadeid: int) -> Response:
|
|||||||
'add_balance': url_for('arcade_pages.addbalance', arcadeid=arcadeid),
|
'add_balance': url_for('arcade_pages.addbalance', arcadeid=arcadeid),
|
||||||
'update_balance': url_for('arcade_pages.updatebalance', arcadeid=arcadeid),
|
'update_balance': url_for('arcade_pages.updatebalance', arcadeid=arcadeid),
|
||||||
'update_pin': url_for('arcade_pages.updatepin', arcadeid=arcadeid),
|
'update_pin': url_for('arcade_pages.updatepin', arcadeid=arcadeid),
|
||||||
|
'update_region': url_for('arcade_pages.updateregion', arcadeid=arcadeid),
|
||||||
'generatepcbid': url_for('arcade_pages.generatepcbid', arcadeid=arcadeid),
|
'generatepcbid': url_for('arcade_pages.generatepcbid', arcadeid=arcadeid),
|
||||||
'updatepcbid': url_for('arcade_pages.updatepcbid', arcadeid=arcadeid),
|
'updatepcbid': url_for('arcade_pages.updatepcbid', arcadeid=arcadeid),
|
||||||
'removepcbid': url_for('arcade_pages.removepcbid', arcadeid=arcadeid),
|
'removepcbid': url_for('arcade_pages.removepcbid', arcadeid=arcadeid),
|
||||||
@ -306,6 +309,34 @@ def updatepin(arcadeid: int) -> Dict[str, Any]:
|
|||||||
return {'pin': pin}
|
return {'pin': pin}
|
||||||
|
|
||||||
|
|
||||||
|
@arcade_pages.route('/<int:arcadeid>/region/update', methods=['POST'])
|
||||||
|
@jsonify
|
||||||
|
@loginrequired
|
||||||
|
def updateregion(arcadeid: int) -> Dict[str, Any]:
|
||||||
|
# Cast the ID for type safety.
|
||||||
|
arcadeid = ArcadeID(arcadeid)
|
||||||
|
|
||||||
|
try:
|
||||||
|
region = int(request.get_json()['region'])
|
||||||
|
except Exception:
|
||||||
|
region = 0
|
||||||
|
|
||||||
|
# Make sure the arcade is valid
|
||||||
|
arcade = g.data.local.machine.get_arcade(arcadeid)
|
||||||
|
if arcade is None or g.userID not in arcade.owners:
|
||||||
|
raise Exception('You don\'t own this arcade, refusing to update!')
|
||||||
|
|
||||||
|
if region not in {RegionConstants.EUROPE, RegionConstants.NO_MAPPING} and (region < RegionConstants.MIN or region > RegionConstants.MAX):
|
||||||
|
raise Exception('Invalid region!')
|
||||||
|
|
||||||
|
# Update and save
|
||||||
|
arcade.region = region
|
||||||
|
g.data.local.machine.put_arcade(arcade)
|
||||||
|
|
||||||
|
# Return nothing
|
||||||
|
return {'region': region}
|
||||||
|
|
||||||
|
|
||||||
@arcade_pages.route('/<int:arcadeid>/pcbids/generate', methods=['POST'])
|
@arcade_pages.route('/<int:arcadeid>/pcbids/generate', methods=['POST'])
|
||||||
@jsonify
|
@jsonify
|
||||||
@loginrequired
|
@loginrequired
|
||||||
|
@ -6,7 +6,7 @@ from typing import Any, Dict, Iterator, List, Optional, Set, Tuple
|
|||||||
from flask_caching import Cache # type: ignore
|
from flask_caching import Cache # type: ignore
|
||||||
|
|
||||||
from bemani.common import GameConstants, Profile, ValidatedDict, ID
|
from bemani.common import GameConstants, Profile, ValidatedDict, ID
|
||||||
from bemani.data import Data, Score, Attempt, Link, Song, UserID, RemoteUser
|
from bemani.data import Data, Config, Score, Attempt, Link, Song, UserID, RemoteUser
|
||||||
|
|
||||||
|
|
||||||
class FrontendBase(ABC):
|
class FrontendBase(ABC):
|
||||||
@ -34,7 +34,7 @@ class FrontendBase(ABC):
|
|||||||
"""
|
"""
|
||||||
valid_rival_types: List[str] = []
|
valid_rival_types: List[str] = []
|
||||||
|
|
||||||
def __init__(self, data: Data, config: Dict[str, Any], cache: Cache) -> None:
|
def __init__(self, data: Data, config: Config, cache: Cache) -> None:
|
||||||
self.data = data
|
self.data = data
|
||||||
self.config = config
|
self.config = config
|
||||||
self.cache = cache
|
self.cache = cache
|
||||||
|
@ -6,7 +6,7 @@ from flask_caching import Cache # type: ignore
|
|||||||
|
|
||||||
from bemani.backend.bishi import BishiBashiFactory
|
from bemani.backend.bishi import BishiBashiFactory
|
||||||
from bemani.common import Profile, ValidatedDict, ID, GameConstants
|
from bemani.common import Profile, ValidatedDict, ID, GameConstants
|
||||||
from bemani.data import Data
|
from bemani.data import Data, Config
|
||||||
from bemani.frontend.base import FrontendBase
|
from bemani.frontend.base import FrontendBase
|
||||||
|
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ class BishiBashiFrontend(FrontendBase):
|
|||||||
|
|
||||||
game = GameConstants.BISHI_BASHI
|
game = GameConstants.BISHI_BASHI
|
||||||
|
|
||||||
def __init__(self, data: Data, config: Dict[str, Any], cache: Cache) -> None:
|
def __init__(self, data: Data, config: Config, cache: Cache) -> None:
|
||||||
super().__init__(data, config, cache)
|
super().__init__(data, config, cache)
|
||||||
self.machines: Dict[int, str] = {}
|
self.machines: Dict[int, str] = {}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import re
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
from flask import Blueprint, request, Response, url_for, abort
|
from flask import Blueprint, request, Response, url_for, abort
|
||||||
|
|
||||||
from bemani.common import ID, GameConstants
|
from bemani.common import ID, GameConstants, RegionConstants
|
||||||
from bemani.data import UserID
|
from bemani.data import UserID
|
||||||
from bemani.frontend.app import loginrequired, jsonify, render_react
|
from bemani.frontend.app import loginrequired, jsonify, render_react
|
||||||
from bemani.frontend.iidx.iidx import IIDXFrontend
|
from bemani.frontend.iidx.iidx import IIDXFrontend
|
||||||
@ -326,6 +326,7 @@ def viewsettings() -> Response:
|
|||||||
'iidx/settings.react.js',
|
'iidx/settings.react.js',
|
||||||
{
|
{
|
||||||
'player': djinfo,
|
'player': djinfo,
|
||||||
|
'regions': RegionConstants.LUT,
|
||||||
'versions': {version: name for (game, version, name) in frontend.all_games()},
|
'versions': {version: name for (game, version, name) in frontend.all_games()},
|
||||||
'qpros': frontend.get_all_items(versions),
|
'qpros': frontend.get_all_items(versions),
|
||||||
},
|
},
|
||||||
@ -515,7 +516,7 @@ def updateprefecture() -> Dict[str, Any]:
|
|||||||
profile = g.data.local.user.get_profile(GameConstants.IIDX, version, user.id)
|
profile = g.data.local.user.get_profile(GameConstants.IIDX, version, user.id)
|
||||||
if profile is None:
|
if profile is None:
|
||||||
raise Exception('Unable to find profile to update!')
|
raise Exception('Unable to find profile to update!')
|
||||||
profile.replace_int('pid', prefecture)
|
profile.replace_int('pid', RegionConstants.db_to_game_region(version >= 25, prefecture))
|
||||||
g.data.local.user.put_profile(GameConstants.IIDX, version, user.id, profile)
|
g.data.local.user.put_profile(GameConstants.IIDX, version, user.id, profile)
|
||||||
|
|
||||||
# Return that we updated
|
# Return that we updated
|
||||||
|
@ -4,8 +4,8 @@ from typing import Any, Dict, Iterator, Optional, Tuple, List
|
|||||||
from flask_caching import Cache # type: ignore
|
from flask_caching import Cache # type: ignore
|
||||||
|
|
||||||
from bemani.backend.iidx import IIDXFactory, IIDXBase
|
from bemani.backend.iidx import IIDXFactory, IIDXBase
|
||||||
from bemani.common import Profile, ValidatedDict, GameConstants
|
from bemani.common import Profile, ValidatedDict, GameConstants, RegionConstants
|
||||||
from bemani.data import Attempt, Data, Score, Song, UserID
|
from bemani.data import Attempt, Data, Config, Score, Song, UserID
|
||||||
from bemani.frontend.base import FrontendBase
|
from bemani.frontend.base import FrontendBase
|
||||||
|
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ class IIDXFrontend(FrontendBase):
|
|||||||
'dp_rival',
|
'dp_rival',
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, data: Data, config: Dict[str, Any], cache: Cache) -> None:
|
def __init__(self, data: Data, config: Config, cache: Cache) -> None:
|
||||||
super().__init__(data, config, cache)
|
super().__init__(data, config, cache)
|
||||||
self.machines: Dict[int, str] = {}
|
self.machines: Dict[int, str] = {}
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ class IIDXFrontend(FrontendBase):
|
|||||||
formatted_profile = super().format_profile(profile, playstats)
|
formatted_profile = super().format_profile(profile, playstats)
|
||||||
formatted_profile.update({
|
formatted_profile.update({
|
||||||
'arcade': "",
|
'arcade': "",
|
||||||
'prefecture': profile.get_int('pid', 51),
|
'prefecture': RegionConstants.game_to_db_region(profile.version >= 25, profile.get_int('pid', self.config.server.region)),
|
||||||
'settings': self.format_settings(profile.get_dict('settings')),
|
'settings': self.format_settings(profile.get_dict('settings')),
|
||||||
'flags': self.format_flags(profile.get_dict('settings')),
|
'flags': self.format_flags(profile.get_dict('settings')),
|
||||||
'sdjp': playstats.get_int('single_dj_points'),
|
'sdjp': playstats.get_int('single_dj_points'),
|
||||||
|
@ -6,7 +6,7 @@ from flask_caching import Cache # type: ignore
|
|||||||
|
|
||||||
from bemani.backend.mga import MetalGearArcadeFactory
|
from bemani.backend.mga import MetalGearArcadeFactory
|
||||||
from bemani.common import Profile, ValidatedDict, ID, GameConstants
|
from bemani.common import Profile, ValidatedDict, ID, GameConstants
|
||||||
from bemani.data import Data
|
from bemani.data import Data, Config
|
||||||
from bemani.frontend.base import FrontendBase
|
from bemani.frontend.base import FrontendBase
|
||||||
|
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ class MetalGearArcadeFrontend(FrontendBase):
|
|||||||
|
|
||||||
game = GameConstants.MGA
|
game = GameConstants.MGA
|
||||||
|
|
||||||
def __init__(self, data: Data, config: Dict[str, Any], cache: Cache) -> None:
|
def __init__(self, data: Data, config: Config, cache: Cache) -> None:
|
||||||
super().__init__(data, config, cache)
|
super().__init__(data, config, cache)
|
||||||
self.machines: Dict[int, str] = {}
|
self.machines: Dict[int, str] = {}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from flask_caching import Cache # type: ignore
|
|||||||
|
|
||||||
from bemani.backend.museca import MusecaFactory, MusecaBase
|
from bemani.backend.museca import MusecaFactory, MusecaBase
|
||||||
from bemani.common import GameConstants, VersionConstants, DBConstants, Profile, ValidatedDict
|
from bemani.common import GameConstants, VersionConstants, DBConstants, Profile, ValidatedDict
|
||||||
from bemani.data import Attempt, Data, Score, Song, UserID
|
from bemani.data import Attempt, Data, Config, Score, Song, UserID
|
||||||
from bemani.frontend.base import FrontendBase
|
from bemani.frontend.base import FrontendBase
|
||||||
|
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ class MusecaFrontend(FrontendBase):
|
|||||||
MusecaBase.CHART_TYPE_RED,
|
MusecaBase.CHART_TYPE_RED,
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, data: Data, config: Dict[str, Any], cache: Cache) -> None:
|
def __init__(self, data: Data, config: Config, cache: Cache) -> None:
|
||||||
super().__init__(data, config, cache)
|
super().__init__(data, config, cache)
|
||||||
|
|
||||||
def all_games(self) -> Iterator[Tuple[GameConstants, int, str]]:
|
def all_games(self) -> Iterator[Tuple[GameConstants, int, str]]:
|
||||||
|
@ -5,7 +5,7 @@ from flask_caching import Cache # type: ignore
|
|||||||
|
|
||||||
from bemani.backend.reflec import ReflecBeatFactory, ReflecBeatBase
|
from bemani.backend.reflec import ReflecBeatFactory, ReflecBeatBase
|
||||||
from bemani.common import GameConstants, Profile, ValidatedDict
|
from bemani.common import GameConstants, Profile, ValidatedDict
|
||||||
from bemani.data import Attempt, Data, Score, Song, UserID
|
from bemani.data import Attempt, Data, Config, Score, Song, UserID
|
||||||
from bemani.frontend.base import FrontendBase
|
from bemani.frontend.base import FrontendBase
|
||||||
|
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ class ReflecBeatFrontend(FrontendBase):
|
|||||||
'rival',
|
'rival',
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, data: Data, config: Dict[str, Any], cache: Cache) -> None:
|
def __init__(self, data: Data, config: Config, cache: Cache) -> None:
|
||||||
super().__init__(data, config, cache)
|
super().__init__(data, config, cache)
|
||||||
|
|
||||||
def all_games(self) -> Iterator[Tuple[GameConstants, int, str]]:
|
def all_games(self) -> Iterator[Tuple[GameConstants, int, str]]:
|
||||||
|
@ -5,7 +5,7 @@ from flask_caching import Cache # type: ignore
|
|||||||
|
|
||||||
from bemani.backend.sdvx import SoundVoltexFactory, SoundVoltexBase
|
from bemani.backend.sdvx import SoundVoltexFactory, SoundVoltexBase
|
||||||
from bemani.common import GameConstants, Profile, ValidatedDict
|
from bemani.common import GameConstants, Profile, ValidatedDict
|
||||||
from bemani.data import Attempt, Data, Score, Song, UserID
|
from bemani.data import Attempt, Data, Config, Score, Song, UserID
|
||||||
from bemani.frontend.base import FrontendBase
|
from bemani.frontend.base import FrontendBase
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ class SoundVoltexFrontend(FrontendBase):
|
|||||||
'rival',
|
'rival',
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, data: Data, config: Dict[str, Any], cache: Cache) -> None:
|
def __init__(self, data: Data, config: Config, cache: Cache) -> None:
|
||||||
super().__init__(data, config, cache)
|
super().__init__(data, config, cache)
|
||||||
|
|
||||||
def all_games(self) -> Iterator[Tuple[GameConstants, int, str]]:
|
def all_games(self) -> Iterator[Tuple[GameConstants, int, str]]:
|
||||||
|
@ -6,6 +6,7 @@ var card_management = React.createClass({
|
|||||||
new_arcade: {
|
new_arcade: {
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
|
region: window.default_region,
|
||||||
paseli_enabled: window.paseli_enabled,
|
paseli_enabled: window.paseli_enabled,
|
||||||
paseli_infinite: window.paseli_infinite,
|
paseli_infinite: window.paseli_infinite,
|
||||||
mask_services_url: window.mask_services_url,
|
mask_services_url: window.mask_services_url,
|
||||||
@ -34,6 +35,7 @@ var card_management = React.createClass({
|
|||||||
new_arcade: {
|
new_arcade: {
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
|
region: window.default_region,
|
||||||
paseli_enabled: window.paseli_enabled,
|
paseli_enabled: window.paseli_enabled,
|
||||||
paseli_infinite: window.paseli_infinite,
|
paseli_infinite: window.paseli_infinite,
|
||||||
mask_services_url: window.mask_services_url,
|
mask_services_url: window.mask_services_url,
|
||||||
@ -182,6 +184,23 @@ var card_management = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderRegion: function(arcade) {
|
||||||
|
if (this.state.editing_arcade && arcade.id == this.state.editing_arcade.id) {
|
||||||
|
return <SelectInt
|
||||||
|
name="region"
|
||||||
|
value={ this.state.editing_arcade.region }
|
||||||
|
choices={ window.regions }
|
||||||
|
onChange={function(choice) {
|
||||||
|
var arcade = this.state.editing_arcade;
|
||||||
|
arcade.region = event.target.value;
|
||||||
|
this.setState({editing_arcade: arcade});
|
||||||
|
}.bind(this)}
|
||||||
|
/>;
|
||||||
|
} else {
|
||||||
|
return <span>{ window.regions[arcade.region] }</span>;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
sortDescription: function(a, b) {
|
sortDescription: function(a, b) {
|
||||||
return a.description.localeCompare(b.description);
|
return a.description.localeCompare(b.description);
|
||||||
},
|
},
|
||||||
@ -309,6 +328,10 @@ var card_management = React.createClass({
|
|||||||
render: this.renderDescription,
|
render: this.renderDescription,
|
||||||
sort: this.sortDescription,
|
sort: this.sortDescription,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Region",
|
||||||
|
render: this.renderRegion,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Owners',
|
name: 'Owners',
|
||||||
render: this.renderOwners,
|
render: this.renderOwners,
|
||||||
@ -344,6 +367,7 @@ var card_management = React.createClass({
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
|
<th>Region</th>
|
||||||
<th>Owners</th>
|
<th>Owners</th>
|
||||||
<th>PASELI Enabled</th>
|
<th>PASELI Enabled</th>
|
||||||
<th>PASELI Infinite</th>
|
<th>PASELI Infinite</th>
|
||||||
@ -377,6 +401,18 @@ var card_management = React.createClass({
|
|||||||
}.bind(this)}
|
}.bind(this)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<SelectInt
|
||||||
|
name="region"
|
||||||
|
value={ this.state.new_arcade.region }
|
||||||
|
choices={ window.regions }
|
||||||
|
onChange={function(choice) {
|
||||||
|
var arcade = this.state.new_arcade;
|
||||||
|
arcade.region = event.target.value;
|
||||||
|
this.setState({new_arcade: arcade});
|
||||||
|
}.bind(this)}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
<td>{
|
<td>{
|
||||||
this.state.new_arcade.owners.map(function(owner, index) {
|
this.state.new_arcade.owners.map(function(owner, index) {
|
||||||
return (
|
return (
|
||||||
|
@ -32,6 +32,9 @@ var arcade_management = React.createClass({
|
|||||||
pin: window.arcade.pin,
|
pin: window.arcade.pin,
|
||||||
editing_pin: false,
|
editing_pin: false,
|
||||||
new_pin: '',
|
new_pin: '',
|
||||||
|
region: window.arcade.region,
|
||||||
|
editing_region: false,
|
||||||
|
new_region: '',
|
||||||
paseli_enabled_saving: false,
|
paseli_enabled_saving: false,
|
||||||
paseli_infinite_saving: false,
|
paseli_infinite_saving: false,
|
||||||
mask_services_url_saving: false,
|
mask_services_url_saving: false,
|
||||||
@ -103,6 +106,21 @@ var arcade_management = React.createClass({
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
saveRegion: function(event) {
|
||||||
|
AJAX.post(
|
||||||
|
Link.get('update_region'),
|
||||||
|
{region: this.state.new_region},
|
||||||
|
function(response) {
|
||||||
|
this.setState({
|
||||||
|
region: response.region,
|
||||||
|
new_region: '',
|
||||||
|
editing_region: false,
|
||||||
|
});
|
||||||
|
}.bind(this)
|
||||||
|
);
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
|
||||||
getSettingIndex: function(setting_name) {
|
getSettingIndex: function(setting_name) {
|
||||||
var real_index = -1;
|
var real_index = -1;
|
||||||
this.state.settings.map(function(game_settings, index) {
|
this.state.settings.map(function(game_settings, index) {
|
||||||
@ -296,6 +314,46 @@ var arcade_management = React.createClass({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderRegion: function() {
|
||||||
|
return (
|
||||||
|
<LabelledSection vertical={true} label="Region">{
|
||||||
|
!this.state.editing_region ?
|
||||||
|
<span>
|
||||||
|
<span>{ window.regions[this.state.region] }</span>
|
||||||
|
<Edit
|
||||||
|
onClick={function(event) {
|
||||||
|
this.setState({editing_region: true, new_region: this.state.region});
|
||||||
|
}.bind(this)}
|
||||||
|
/>
|
||||||
|
</span> :
|
||||||
|
<form className="inline" onSubmit={this.saveRegion}>
|
||||||
|
<SelectInt
|
||||||
|
name="region"
|
||||||
|
value={ this.state.new_region }
|
||||||
|
choices={ window.regions }
|
||||||
|
onChange={function(choice) {
|
||||||
|
this.setState({new_region: event.target.value});
|
||||||
|
}.bind(this)}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
value="save"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="button"
|
||||||
|
value="cancel"
|
||||||
|
onClick={function(event) {
|
||||||
|
this.setState({
|
||||||
|
new_region: '',
|
||||||
|
editing_region: false,
|
||||||
|
});
|
||||||
|
}.bind(this)}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
}</LabelledSection>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
generateNewMachine: function(event) {
|
generateNewMachine: function(event) {
|
||||||
AJAX.post(
|
AJAX.post(
|
||||||
Link.get('generatepcbid'),
|
Link.get('generatepcbid'),
|
||||||
@ -478,6 +536,7 @@ var arcade_management = React.createClass({
|
|||||||
<span className="placeholder">no description</span>
|
<span className="placeholder">no description</span>
|
||||||
}</LabelledSection>
|
}</LabelledSection>
|
||||||
{this.renderPIN()}
|
{this.renderPIN()}
|
||||||
|
{this.renderRegion()}
|
||||||
<LabelledSection vertical={true} label="PASELI Enabled">
|
<LabelledSection vertical={true} label="PASELI Enabled">
|
||||||
<span>{ this.state.paseli_enabled ? 'yes' : 'no' }</span>
|
<span>{ this.state.paseli_enabled ? 'yes' : 'no' }</span>
|
||||||
<Toggle onClick={this.togglePaseliEnabled.bind(this)} />
|
<Toggle onClick={this.togglePaseliEnabled.bind(this)} />
|
||||||
|
@ -314,12 +314,11 @@ var settings_view = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
renderPrefecture: function(player) {
|
renderPrefecture: function(player) {
|
||||||
regions = this.state.version >= 25 ? Regions2 : Regions;
|
|
||||||
return (
|
return (
|
||||||
<LabelledSection vertical={true} label="Prefecture">{
|
<LabelledSection vertical={true} label="Prefecture">{
|
||||||
!this.state.editing_prefecture ?
|
!this.state.editing_prefecture ?
|
||||||
<span>
|
<span>
|
||||||
<span>{regions[player.prefecture]}</span>
|
<span>{window.regions[player.prefecture]}</span>
|
||||||
<Edit
|
<Edit
|
||||||
onClick={function(event) {
|
onClick={function(event) {
|
||||||
this.setState({editing_prefecture: true});
|
this.setState({editing_prefecture: true});
|
||||||
@ -330,7 +329,7 @@ var settings_view = React.createClass({
|
|||||||
<SelectInt
|
<SelectInt
|
||||||
name="prefecture"
|
name="prefecture"
|
||||||
value={this.state.new_prefecture}
|
value={this.state.new_prefecture}
|
||||||
choices={regions}
|
choices={window.regions}
|
||||||
onChange={function(choice) {
|
onChange={function(choice) {
|
||||||
this.setState({new_prefecture: choice});
|
this.setState({new_prefecture: choice});
|
||||||
}.bind(this)}
|
}.bind(this)}
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
var Regions = [
|
|
||||||
null,
|
|
||||||
"北海道",
|
|
||||||
"青森県",
|
|
||||||
"岩手県",
|
|
||||||
"宮城県",
|
|
||||||
"秋田県",
|
|
||||||
"山形県",
|
|
||||||
"福島県",
|
|
||||||
"茨城県",
|
|
||||||
"栃木県",
|
|
||||||
"群馬県",
|
|
||||||
"埼玉県",
|
|
||||||
"千葉県",
|
|
||||||
"東京都",
|
|
||||||
"神奈川県",
|
|
||||||
"新潟県",
|
|
||||||
"富山県",
|
|
||||||
"石川県",
|
|
||||||
"福井県",
|
|
||||||
"山梨県",
|
|
||||||
"長野県",
|
|
||||||
"岐阜県",
|
|
||||||
"静岡県",
|
|
||||||
"愛知県",
|
|
||||||
"三重県",
|
|
||||||
"滋賀県",
|
|
||||||
"京都府",
|
|
||||||
"大阪府",
|
|
||||||
"兵庫県",
|
|
||||||
"奈良県",
|
|
||||||
"和歌山県",
|
|
||||||
"鳥取県",
|
|
||||||
"島根県",
|
|
||||||
"岡山県",
|
|
||||||
"広島県",
|
|
||||||
"山口県",
|
|
||||||
"徳島県",
|
|
||||||
"香川県",
|
|
||||||
"愛媛県",
|
|
||||||
"高知県",
|
|
||||||
"福岡県",
|
|
||||||
"佐賀県",
|
|
||||||
"長崎県",
|
|
||||||
"熊本県",
|
|
||||||
"大分県",
|
|
||||||
"宮崎県",
|
|
||||||
"鹿児島県",
|
|
||||||
"沖縄県",
|
|
||||||
"香港",
|
|
||||||
"韓国",
|
|
||||||
"台湾",
|
|
||||||
"米国 (USA)",
|
|
||||||
"欧州 (Europe)",
|
|
||||||
"海外 (Other)",
|
|
||||||
];
|
|
||||||
|
|
||||||
Regions2 = [
|
|
||||||
null,
|
|
||||||
"北海道",
|
|
||||||
"青森県",
|
|
||||||
"岩手県",
|
|
||||||
"宮城県",
|
|
||||||
"秋田県",
|
|
||||||
"山形県",
|
|
||||||
"福島県",
|
|
||||||
"茨城県",
|
|
||||||
"栃木県",
|
|
||||||
"群馬県",
|
|
||||||
"埼玉県",
|
|
||||||
"千葉県",
|
|
||||||
"東京都",
|
|
||||||
"神奈川県",
|
|
||||||
"新潟県",
|
|
||||||
"富山県",
|
|
||||||
"石川県",
|
|
||||||
"福井県",
|
|
||||||
"山梨県",
|
|
||||||
"長野県",
|
|
||||||
"岐阜県",
|
|
||||||
"静岡県",
|
|
||||||
"愛知県",
|
|
||||||
"三重県",
|
|
||||||
"滋賀県",
|
|
||||||
"京都府",
|
|
||||||
"大阪府",
|
|
||||||
"兵庫県",
|
|
||||||
"奈良県",
|
|
||||||
"和歌山県",
|
|
||||||
"鳥取県",
|
|
||||||
"島根県",
|
|
||||||
"岡山県",
|
|
||||||
"広島県",
|
|
||||||
"山口県",
|
|
||||||
"徳島県",
|
|
||||||
"香川県",
|
|
||||||
"愛媛県",
|
|
||||||
"高知県",
|
|
||||||
"福岡県",
|
|
||||||
"佐賀県",
|
|
||||||
"長崎県",
|
|
||||||
"熊本県",
|
|
||||||
"大分県",
|
|
||||||
"宮崎県",
|
|
||||||
"鹿児島県",
|
|
||||||
"沖縄県",
|
|
||||||
"香港",
|
|
||||||
"韓国",
|
|
||||||
"台湾",
|
|
||||||
"タイ",
|
|
||||||
"インドネシア",
|
|
||||||
"シンガポール",
|
|
||||||
"フィリピン",
|
|
||||||
"マカオ",
|
|
||||||
"アメリカ",
|
|
||||||
"海外 (Other)",
|
|
||||||
];
|
|
@ -65,6 +65,8 @@
|
|||||||
<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>
|
<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>Default Region</dt>
|
||||||
|
<dd>{{ region[config.server.region] }} (can be overridden by arcade settings)</dd>
|
||||||
<dt>Event Log Preservation Duration</dt>
|
<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>
|
</dl>
|
||||||
|
@ -33,6 +33,11 @@ server:
|
|||||||
# page. Note that this setting is irrelevant if PCBID enforcing is off.
|
# page. Note that this setting is irrelevant if PCBID enforcing is off.
|
||||||
# Set to 0 or delete this setting to disable self-granting PCBIDs.
|
# Set to 0 or delete this setting to disable self-granting PCBIDs.
|
||||||
pcbid_self_grant_limit: 0
|
pcbid_self_grant_limit: 0
|
||||||
|
# Default region for this network (set to USA by default). See RegionConstants
|
||||||
|
# for details on acceptible values. The range of accepted values is 1-56 matching
|
||||||
|
# the 56 normal regions found in RegionConstants, and 1000 for "Europe" and
|
||||||
|
# 2000 for "Other".
|
||||||
|
region: 56
|
||||||
|
|
||||||
# Webhook URLs. These allow for game scores from games with scorecard support to be broadcasted to outside services.
|
# Webhook URLs. These allow for game scores from games with scorecard support to be broadcasted to outside services.
|
||||||
# Delete this to disable this support.
|
# Delete this to disable this support.
|
||||||
|
Loading…
Reference in New Issue
Block a user