Renamed the library code to be in src/ to follow conventions

This commit is contained in:
2025-06-16 21:10:19 +01:00
parent 8f7b524c45
commit 1938ff4c90
5 changed files with 0 additions and 0 deletions

1
src/__init__.py Normal file
View File

@ -0,0 +1 @@
pass

7
src/expansion.py Normal file
View File

@ -0,0 +1,7 @@
class Expansion:
def __init__(self, parent, globalConfig):
setattr(parent, self.__class__.ID, self)
class PlayerExpansion:
def __init__(self, player, localConfig):
pass

216
src/player_settings.py Normal file
View File

@ -0,0 +1,216 @@
"""
Needs to manage any number of players
Needs to work with mulitple rounds/turns
Needs to handle modifying number of players
"""
import copy
import json
import logging
from pathlib import Path
_log = logging.getLogger('NoPE-Lib')
class PlayersManager:
"""
Manager of players for a given game.
This class implements most methods available to classic dict.
Attributes:
gameID (str): The gameID of the active game
Methods:
save:
"""
defaultPlayerConfig = {"flags": [], "expansions": {}, "games": {}}
def __init__(self, gameID: str=None, activePlayers: list[str]=None, playersPath: str='./players.json', loggerID: str='PlayersManager'):
"""
Initialises a list of players.
Args:
gameID (str): The ID of the game used in the configuration file.
activePlayers (list of str): The names of the players that are playing. Defaults to none which includes all players.
playersPath (str, optional): The path of the players.json file. Defaults to './players.json'.
loggerID (str, optional): The ID used for logging. Defaults to 'Players'.
"""
# Store the arguments
self._log = _log.getChild(loggerID)
self._currentGameID = gameID
# Deal with the path
self._playersPath = Path(playersPath)
# Get the config file
with open(self._playersPath, 'r') as f:
self._cfg = json.load(f)
# Create the players
activePlayers = activePlayers if activePlayers is not None else self._cfg["players"].keys()
self._player_data = {
name: Player(name, self, **player_cfg)
for name, player_cfg in self._cfg["players"].items()
if name in activePlayers
}
def __getitem__(self, playerName: str):
"""
Get a player object.
If the player wasn't active, make them active.
If the player didn't exist previously, create a default config and make them active.
"""
if playerName not in self._cfg["players"]:
# Create the brand new player
self._cfg["players"][playerName] = copy.deepcopy(self.defaultPlayerConfig)
newPlayer = Player(playerName, self, **self._cfg["players"][playerName])
# Make the player active
self._player_data[playerName] = newPlayer
self._log.debug(f"Created a new player called {playerName}")
return newPlayer
elif playerName not in self._player_data:
# Fetch the player's data and make them active
playerAdded = Player(playerName, self, **self._cfg["players"][playerName])
self._player_data[playerName] = playerAdded
self._log.debug(f"Fetched {playerName}'s data and made them active")
return playerAdded
else:
return self._player_data[playerName]
def __setitem__(self, playerName: str, config: dict, makeNewPlayerObject=False):
"""
Replace a player's config with another one. It possible to also automatically replace the
player object by specifying the corresponding argument.
"""
self._log.debug(f"Changed {playerName}'s config")
if makeNewPlayerObject:
previousInstance = self._player_data[playerName]
self._player_data[playerName] = Player(playerName, self, **config)
del previousInstance
self._cfg["players"][playerName] = config
def __delitem__(self, playerName):
self._log.debug(f"Removing {playerName} from active players")
del self._player_data[playerName]
def __len__(self):
return len(self._player_data)
def __iter__(self):
return self._player_data.__iter__()
def __repr__(self):
return f"Manager is playing {self.gameID} with {len(self._player_data)} active players"
@property
def gameID(self):
return self._currentGameID
@gameID.setter
def gameID(self, gameID: str):
self._currentGameID = gameID
self._player_data = {name: Player(name, self, **cfg) for name, cfg in self._cfg["players"].items()}
@gameID.deleter
def gameID(self):
self._currentGameID = None
self._player_data = {name: Player(name, self, **cfg) for name, cfg in self._cfg["players"].items()}
def keys(self):
""" Iterator of the active players' names """
return self._player_data.keys()
def values(self):
""" Iterator of the active players' objects """
return self._player_data.keys()
def items(self):
""" Two iterators of the activate players' names and object """
return self._player_data.items()
def save(self):
with open(self._playersPath, 'w') as f:
self._cfg = json.dump(f, self._cfg)
def addExpansion(self, expansion):
"""
Adds an expansion, used by things like PDO-Lib.
Args:
expansion (Expansion): The expansion to add.
"""
expID = expansion.__class__.ID
_log.debug(f'Adding expansion {expID}...')
expansion = expansion(self._cfg.get(expID))
class Player:
"""
The game settings are not guaranteed to have data in it.
Attributes:
flags:
expansions:
gameSave:
Methods:
generateConfig:
"""
def __init__(self, name: str, manager: PlayersManager, **cfg):
self._name = name
self._manager = manager
for key, val in cfg.items():
setattr(self, "_" + key, val)
def __repr__(self):
return f"Player {self._name} has {len(self._flags)} flag(s), {len(self._expansions)} expansions and {len(self._games)} saved game"
@property
def name(self):
return self._name
@property
def flags(self):
return self._flags
@flags.setter
def flags(self, newFlags):
self._flags = newFlags
# The container was changed and must be transmited to the manager
self._manager[self._name] = self.generateConfig()
@property
def expansions(self):
return self._expansions
@expansions.setter
def expansions(self, newExpansions):
self._expansions = newExpansions
# The container was changed and must be transmited to the manager
self._manager[self._name] = self.generateConfig()
@property
def gameSave(self):
"""The save for the current game. If no configuration was found None is returned."""
return self._games.get(self._manager.gameID)
@gameSave.setter
def gameSave(self, newGameSave):
self._games[self._manager.gameID] = newGameSave
def generateConfig(self):
return {"flags": self._flags, "expansions": self._expansions, "games": self._games}
if __name__ == "__main__":
# Test run to make sure nothing is flagrantly flawed
configPath = Path(__file__).parent / "players.json"
manager = PlayersManager(playersPath=configPath, gameID="gameID0")
# Iteration
for name in manager:
print(name)
# Modification of a players data
brosef = manager["Brosef"]
brosef.gameSave = [1]
print(manager["Brosef"].gameSave)

19
src/players.json Normal file
View File

@ -0,0 +1,19 @@
{
"exampleExpansion": {
"optionA": 1,
"optionB": 2
},
"availableExpansion":
{
"bracelet1": "Brosef",
"robotic_barman": "Tango",
"challenge": "TRS"
},
"players": {
"Brosef": {"flags": [], "expansions": {"exampleExpansion": {"playerOption": 5}}, "games": {"gameID0": 2}},
"TRS_MML": {"flags": [], "expansions": {"exampleExpansion": {"playerOption": 5}}, "games": {"gameID0": 1}},
"Tango": {"flags": [], "expansions": {"exampleExpansion": {"playerOption": 5}}, "games": {"gameID0": 0}}
}
}

6
src/standardFlags.py Normal file
View File

@ -0,0 +1,6 @@
NO_ALCOHOL = 'no-alcohol'
NO_SHOCK = 'no-shock'
NO_SPICE = 'no-spice'
NO_SOUR = 'no-sour'
EASY_MODE = 'pussy-mode'
HARD_MODE = 'hard-mode'