Initial commit

This commit is contained in:
Smaug123
2018-01-01 15:31:21 +00:00
commit 30b9f068ce
6 changed files with 185 additions and 0 deletions

0
HanabiWeb/__init__.py Normal file
View File

58
HanabiWeb/cache.py Normal file
View File

@@ -0,0 +1,58 @@
"""
Utility functions for storing and retrieving Hanabi server data.
"""
import yaml
# Field names for each field
_players = "players"
_hands = "hands"
_discards = "discards"
_knowledge = "knowledge"
_lives = "lives"
_fieldnames = [_players, _hands, _discards, _knowledge, _lives]
class GameDataStore:
"""
Store complete information about a Hanabi game in a file.
"""
def __init__(self, path):
self.filepath = path
def get(self):
with open(self.filepath) as f:
data = yaml.safe_load(f)
return data
def replace(self, data):
with open(self.filepath) as f:
yaml.dump(data, f)
def replace_field(self, field, data):
existing = self.get()
existing[field] = data
self.replace(existing)
def append_to_field(self, field, data):
existing = self.get()
existing[field].append(data)
self.replace(existing)
def add_player(self, player_name):
self.append_to_field(_players, player_name)
def create(self, players):
"""
Create a new Hanabi game, storing the data in the given file.
:return:
"""
data = {_players: players,
_hands: [],
_discards: [],
_knowledge: {"used": 0, "available": 8},
_lives: {"used": 0, "available": 3}}
self.replace(data)

20
HanabiWeb/card.py Normal file
View File

@@ -0,0 +1,20 @@
import enum
@enum.unique()
class HanabiColour(enum.Enum):
Red = enum.auto()
Green = enum.auto()
White = enum.auto()
Yellow = enum.auto()
Blue = enum.auto()
class HanabiCard:
def __str__(self):
return "{} {}".format(self.rank, self.colour)
def __init__(self):
self.colour = None
self.rank = None

106
HanabiWeb/hanabi.py Normal file
View File

@@ -0,0 +1,106 @@
import os
import re
from flask import Flask
from flask_restful import Resource, Api, abort
from . import hanabi_cache
app = Flask(__name__)
api = Api(app)
_DATA_STORES = os.path.join(os.path.expanduser('~'), '.hanabigames')
def _validate_game_id(game_id):
"""
Test whether a game ID is valid. If it is not, raise a 403 Forbidden.
"""
try:
int(str(game_id))
except ValueError:
abort(403, message="Malformed game ID {}".format(game_id))
def _game_data_path(game_id):
"""
Find the path to the data file for a given game.
This fully trusts game_id, and is not safe on unsanitised input.
"""
return os.path.join(_DATA_STORES, "{}.dat".format(game_id))
def ls(directory):
onlyfiles = [f
for f in os.listdir(directory)
if os.path.isfile(os.path.join(directory, f))]
return onlyfiles
def _get_new_game_index():
files = ls(_DATA_STORES)
indices = [int(name.rstrip('.dat'))
for name in files
if re.match(r"[0-9]+\.dat$", name)]
if not indices:
return 0
indices.sort()
return indices[-1] + 1
class Hand(Resource):
def get(self, game_id, player_id):
return {'hello': 'world'}
class Play(Resource):
def post(self, game_id, player_id, card):
pass
class Game(Resource):
def get(self, game_id, player_id=None):
"""
Return the state of the game as viewed by the given player.
If no player is specified, return the state of the game as viewed by a
spectator.
:param game_id: Lookup ID for the given game.
:param player_id: Lookup ID for a certain player in this game.
:return: Dictionary of game state.
{players: [players],
hands: {player1: [cards], player2: [cards]},
discards: [cards],
knowledge: {used: 5, available: 3},
lives: {used: 0, available: 3}}
"""
_validate_game_id(game_id)
data_path = _game_data_path(game_id)
data = hanabi_cache.GameDataStore(data_path)
if player_id is None:
return data.get()
def put(self, players):
"""
Create a new game, returning the game ID.
"""
new_id = _get_new_game_index()
data_path = _game_data_path(new_id)
data = hanabi_cache.GameDataStore(data_path)
data.create(players)
api.add_resource(Hand, '/hanabi')
@app.route("/hanabi")
def hello():
return "Hello, World!"
if __name__ == "__main__":
app.run(debug=True)

View File

1
server.py Normal file
View File

@@ -0,0 +1 @@
__author__ = 'Patrick'