from typing import Optional, List, Dict, Any, NewType from bemani.common import ValidatedDict, GameConstants UserID = NewType("UserID", int) ArcadeID = NewType("ArcadeID", int) class User: """ An object representing a user. This is an account that has zero or more cards associated with it (starting with 1 when carding in for the first time), and possibly has a username/password/email if the user has signed up for the frontend. Once that is done, users can remove their only card, or add more cards, or swap out a card for a new one. """ def __init__( self, userid: UserID, username: Optional[str], email: Optional[str], admin: bool ) -> None: """ Initialize the user object. Parameters: userid - The ID of the user. username - An optional string, set if the user has claimed their account on the web UI. email - An optional string, set if the user has claimed their account on the web UI. """ self.id = userid self.username = username self.email = email self.admin = admin def __repr__(self) -> str: return f"User(userid={self.id}, username={self.username}, email={self.email}, admin={self.admin})" class Achievement: """ An object representing a single achievement for a user. Achievements are referred to loosely here. An achievement is really any type/id pair that can have some attached data, such as item unlocks, tran medals, course progress, etc. """ def __init__( self, achievementid: int, achievementtype: str, timestamp: Optional[int], data: Dict[str, Any], ) -> None: """ Initialize the achievement object. Parameters: achievementid - The ID of the achievement, as assigned by a game class. achievementtype - The type of the achievement, as assigned by a game class. timestamp - The timestamp this achievement was earned, if available. data - Any optional data the game wishes to save and retrieve later. """ self.id = achievementid self.type = achievementtype self.timestamp = timestamp self.data = ValidatedDict(data) def __repr__(self) -> str: return f"Achievement(achievementid={self.id}, achievementtype={self.type}, timestamp={self.timestamp}, data={self.data})" class Link: """ An object representing a single link between two users. The type of the link is determined by the game that needs this linkage. """ def __init__( self, userid: UserID, linktype: str, other_userid: UserID, data: Dict[str, Any] ) -> None: """ Initialize the achievement object. Parameters: userid - The ID of the user. linktype - The type of the link, as assigned by a game class. other_userid - The ID of the second user we're linked against. data - Any optional data the game wishes to save and retrieve later. """ self.userid = userid self.type = linktype self.other_userid = other_userid self.data = ValidatedDict(data) def __repr__(self) -> str: return f"Link(userid={self.userid}, linktype={self.type}, other_userid={self.other_userid}, data={self.data})" class Machine: """ An object representing a single machine found in the DB. Machines are potentially owned by arcades, and keyed by PCBID. There will always be a 1:1 mapping between a PCBID seen on the network and a Machine. """ def __init__( self, machineid: int, pcbid: str, name: str, description: str, arcade: Optional[ArcadeID], port: int, game: Optional[GameConstants], version: Optional[int], data: Dict[str, Any], ) -> None: """ Initialize the machine instance. Parameters: machineid - The machine's internal ID, from the DB. pcbid - The PCBID assigned to the machine. name - The name of the machine, as potentially set by the operator. arcade - Optionally, the ID of the arcade this machine belongs in. port - The port this machine is assigned. game - Optionally, the game series that this machine is tied to. version - Optionally, the version of the above game required. If it is negative, then any game equal to or lower in version to the abs of this is required. data - Extra data that a game backend may want to save with a machine. """ self.id = machineid self.pcbid = pcbid self.name = name self.description = description self.arcade = arcade self.port = port self.game = game self.version = version self.data = ValidatedDict(data) def __repr__(self) -> str: return f"Machine(machineid={self.id}, pcbid={self.pcbid}, name={self.name}, description={self.description}, arcade={self.arcade}, port={self.port}, game={self.game}, version={self.version}, data={self.data})" class Arcade: """ An object representing a single arcade found in the DB. Arcades can be given owners and should be seen as a zone of machines. Zones can override PASELI settings and set up events/globals/other settings. In this way, you can give power to operators of arcades on your network, who can then go on to configure events and PASELI including crediting accounts. Machines belong to either no arcade or a single arcase. """ def __init__( self, arcadeid: ArcadeID, name: str, description: str, pin: str, region: int, area: Optional[str], data: Dict[str, Any], owners: List[UserID], ) -> None: """ Initialize the arcade instance. Parameters: arcadeid - The arcade's internal ID, from the DB. name - The name of the arcade. description - The description of the arcade. pin - An eight digit string representing the PIN used to pull up PASELI info. region - An integer representing the region this arcade is in. area - A string representing the custom area this arcade is in, or None if default. data - A dictionary of settings for this arcade. owners - An list of integers specifying the user IDs of owners for this arcade. """ self.id = arcadeid self.name = name self.description = description self.pin = pin self.region = region self.area = area self.data = ValidatedDict(data) self.owners = owners def __repr__(self) -> str: return f"Arcade(arcadeid={self.id}, name={self.name}, description={self.description}, pin={self.pin}, region={self.region}, area={self.area}, data={self.data}, owners={self.owners})" class Song: """ An object representing a single song in the DB. """ def __init__( self, game: GameConstants, version: int, songid: int, songchart: int, name: Optional[str], artist: Optional[str], genre: Optional[str], data: Dict[str, Any], ) -> None: """ Initialize the song object. Parameters: game - The song's game series. version - The song's game version. songid - The song's ID according to the game. songchart - The song's chart number, according to the game. name - The name of the song, from the DB. artist - The artist of the song, from the DB. genre - The genre of the song, from the DB. data - Any optional data that a game class uses for a song. """ self.game = game self.version = version self.id = songid self.chart = songchart self.name = name self.artist = artist self.genre = genre self.data = ValidatedDict(data) def __repr__(self) -> str: return f"Song(game={self.game}, version={self.version}, songid={self.id}, songchart={self.chart}, name={self.name}, artist={self.artist}, genre={self.genre}, data={self.data})" class Score: """ An object representing a single score for a user. """ def __init__( self, key: int, songid: int, songchart: int, points: int, timestamp: int, update: int, location: int, plays: int, data: Dict[str, Any], ) -> None: """ Initialize the score object. Parameters: key - A unique key identifying this exact score. songid - The song's ID according to the game. songchart - The song's chart number, according to the game. points - The points achieved on this song, from the DB. timestamp - The timestamp when the record was earned. update - The timestamp when the record was last updated (including play count). plays - The number of plays the user has recorded for this song and chart. location - The ID of the machine that this score was earned on. data - Any optional data that a game class recorded with this score. """ self.key = key self.id = songid self.chart = songchart self.points = points self.timestamp = timestamp self.update = update self.location = location self.plays = plays self.data = ValidatedDict(data) def __repr__(self) -> str: return f"Score(key={self.key}, songid={self.id}, songchart={self.chart}, points={self.points}, timestamp={self.timestamp}, update={self.update}, location={self.location}, plays={self.plays}, data={self.data})" class Attempt: """ An object representing a single score attempt for a user. """ def __init__( self, key: int, songid: int, songchart: int, points: int, timestamp: int, location: int, new_record: bool, data: Dict[str, Any], ) -> None: """ Initialize the score object. Parameters: key - A unique key identifying this exact attempt. songid - The song's ID according to the game. songchart - The song's chart number, according to the game. points - The points achieved on this song, from the DB. timestamp - The timestamp of the attempt. location - The ID of the machine that this score was earned on. new_record - Whether this attempt resulted in a new record for this user. data - Any optional data that a game class recorded with this score. """ self.key = key self.id = songid self.chart = songchart self.points = points self.timestamp = timestamp self.location = location self.new_record = new_record self.data = ValidatedDict(data) def __repr__(self) -> str: return f"Attempt(key={self.key}, songid={self.id}, songchart={self.chart}, points={self.points}, timestamp={self.timestamp}, location={self.location}, new_record={self.new_record}, data={self.data})" class News: """ An object representing an item of news as displayed on the homepage of the frontend. """ def __init__(self, newsid: int, timestamp: int, title: str, body: str) -> None: """ Initialize the news object. Parameters: newsid - Integer identifier for the news item. timestamp - Integer representing unix timestamp of the news item being created. title - String representing news title. body - String representing news body. """ self.id = newsid self.timestamp = timestamp self.title = title self.body = body def __repr__(self) -> str: return f"News(newsid={self.id}, timestamp={self.timestamp}, title={self.title}, body={self.body})" class Event: """ An object representing an audit event. These are PCB events, errors, exceptions, invalid PCBIDs trying to connect, or more mundate events such as daily selection. """ def __init__( self, auditid: int, timestamp: int, userid: Optional[UserID], arcadeid: Optional[ArcadeID], event: str, data: Dict[str, Any], ) -> None: """ Initialize the audit event object. Parameters: auditid - Integer identifier for the audit entry. timestamp - Integer representing unix timestamp of the audit entrys creation. userid - User ID of the user the event related to, or None if there was no user. arcadeid - Arcade ID of the arcade the event related to, or None if there was no arcade. event - String event type. data - Optional dictionary of values for the event. """ self.id = auditid self.timestamp = timestamp self.userid = userid self.arcadeid = arcadeid self.type = event self.data = ValidatedDict(data) def __repr__(self) -> str: return f"Event(auditid={self.id}, timestamp={self.timestamp}, userid={self.userid}, arcadeid={self.arcadeid}, event={self.type}, data={self.data})" class Item: """ An object representing an item from the catalog for a game. """ def __init__(self, cattype: str, catid: int, data: Dict[str, Any]) -> None: """ Initialize the catalog object. Parameters: cattype - Catalog type. catid - Catalog ID. data - Optional dictionary of values for the catalog item. """ self.type = cattype self.id = catid self.data = ValidatedDict(data) def __repr__(self) -> str: return f"Item(cattype={self.type}, catid={self.id}, data={self.data})" class Client: """ An object representing a client that's been authorized to talk to our BEMAPI server implementation. """ def __init__(self, clientid: int, timestamp: int, name: str, token: str) -> None: """ Initialize the client object. Parameters: clientid - Integer identifier for the client. timestamp - Add time as an integer unix timestamp. name - Name of the client. token - Authorization token given to the client. """ self.id = clientid self.timestamp = timestamp self.name = name self.token = token def __repr__(self) -> str: return f"Client(clientid={self.id}, timestamp={self.timestamp}, name={self.name}, token={self.token})" class Server: """ An object representing a BEMAPI server that's we've been authorized to talk to for pulling data. """ def __init__( self, serverid: int, timestamp: int, uri: str, token: str, allow_stats: bool, allow_scores: bool, ) -> None: """ Initialize the server object. Parameters: serverid - Integer identifier for the server. timestamp - Add time as an integer unix timestamp. uri - Base URI of the server. token - Authorization token given to us. allow_stats - True if we should pull statistics from this server. allow_scores - True if we should pull scores from this server. """ self.id = serverid self.timestamp = timestamp self.uri = uri self.token = token self.allow_stats = allow_stats self.allow_scores = allow_scores def __repr__(self) -> str: return f"Server(serverid={self.id}, timestamp={self.timestamp}, uri={self.uri}, token={self.token}, allow_stats={self.allow_stats}, allow_scores={self.allow_scores})"