Merge pull request #21 from sorrelbri/sj-game-logic

sj game logic
This commit is contained in:
sorrelbri 2019-10-13 21:46:30 -07:00 committed by GitHub
commit 0bca86cf79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 103 additions and 36 deletions

View file

@ -9,18 +9,31 @@ import os
import json import json
from websockets.roomSocket import new_game_notice, join_game_notice from websockets.roomSocket import new_game_notice, join_game_notice
from marshmallow import pprint
api_games = Blueprint('api_games', __name__, url_prefix='/api/games') api_games = Blueprint('api_games', __name__, url_prefix='/api/games')
@api_games.route('/<game_id>', methods=['GET']) @api_games.route('/<game_id>', methods=['GET'])
def get_room(game_id): def get_room(game_id):
print(game_id) print(game_id)
game = Game.query.filter_by(id=game_id).first() game = Game.query.filter_by(id=game_id).first()
response = game_schema.dumps(game)
# TODO create decorator that returns user from header # TODO create decorator that returns user from header
auth_header = request.headers.get('Authorization') auth_header = request.headers.get('Authorization')
user = jwt.decode(auth_header.split(" ")[1], os.environ.get('SECRET_KEY'))['user'] user = jwt.decode(auth_header.split(" ")[1], os.environ.get('SECRET_KEY'))['user']
print(user) user = json.loads(user)
join_game_notice(game_id, user) # add user to game if open position available
if user and not game.player_black and game.player_white != user['id']:
game.player_black = user['id']
db.session.add(game)
db.session.commit()
print(game.player_black)
join_game_notice(game)
response = {'game': game_schema.dumps(game)}
if game.player_black:
response['black'] = user_schema.dumps(User.query.filter_by(id=game.player_black).first())
else:
response['black'] = ''
response['white'] = user_schema.dumps(User.query.filter_by(id=game.player_white).first())
return jsonify(response) return jsonify(response)
@api_games.route('/', methods=['POST']) @api_games.route('/', methods=['POST'])

3
app.py
View file

@ -17,7 +17,8 @@ app.config.from_object(os.getenv('CONFIGURATION_OBJECT'))
# ! Environment Variable # ! Environment Variable
# TODO export ALLOWED_ORIGIN= whatever the react server is # TODO export ALLOWED_ORIGIN= whatever the react server is
socketio = SocketIO(app, cors_allowed_origins=os.getenv('ALLOWED_ORIGIN')) # TODO cors_allowed_origins=os.getenv('ALLOWED_ORIGIN')
socketio = SocketIO(app, cors_allowed_origins=['http://localhost:3000', 'http://localhost:3001'])
def create_app(): def create_app():
CORS(app, resources={ CORS(app, resources={

View file

@ -8,19 +8,21 @@ from database import db
from app import create_app from app import create_app
app = create_app() app = create_app()
migrate = Migrate(app, db) migrate = Migrate(app, db)
manager = Manager(app) manager = Manager(app)
# migrations
manager.add_command('db', MigrateCommand)
from models.Game import Game from models.Game import Game
from models.GameRoom import GameRoom from models.GameRoom import GameRoom
from models.Message import Message from models.Message import Message
from models.Move import Move from models.Move import Move
from models.User import User from models.User import User
# migrations
manager.add_command('db', MigrateCommand)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/browser-go'
@manager.command @manager.command
def test(): def test():
"""Runs the unit tests without test coverage.""" """Runs the unit tests without test coverage."""

View file

@ -1,8 +1,8 @@
"""empty message """empty message
Revision ID: 45f01fb15e26 Revision ID: 77a6ccbab312
Revises: Revises:
Create Date: 2019-10-10 17:50:40.846864 Create Date: 2019-10-12 19:28:48.173762
""" """
from alembic import op from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '45f01fb15e26' revision = '77a6ccbab312'
down_revision = None down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None

View file

@ -1,7 +1,7 @@
from app import db, ma from app import db, ma
from marshmallow import fields from marshmallow import fields, Schema, pre_dump
import enum import enum
from models.User import user_schema from models.User import UserSchema, user_schema, User
# ! Games >-< Users join table # ! Games >-< Users join table
games_users = db.Table('games_users', games_users = db.Table('games_users',
@ -55,9 +55,9 @@ class Game(db.Model):
overtime_length = db.Column(db.Integer) # seconds overtime_length = db.Column(db.Integer) # seconds
# foreign keys # foreign keys
game_room = db.Column(db.Integer, db.ForeignKey("game_rooms.id")) game_room = db.Column(db.ForeignKey("game_rooms.id"))
player_black = db.Column(db.Integer, db.ForeignKey("users.id")) player_black = db.Column(db.ForeignKey("users.id"))
player_white = db.Column(db.Integer, db.ForeignKey("users.id")) player_white = db.Column(db.ForeignKey("users.id"))
def __init__( def __init__(
self, name, description, board_size, game_room, player_white, self, name, description, board_size, game_room, player_white,
@ -73,13 +73,17 @@ class Game(db.Model):
self.main_time = main_time self.main_time = main_time
self.overtime = overtime self.overtime = overtime
class GameSchema(ma.ModelSchema): class GameSchema(ma.Schema):
id = fields.Int() id = fields.Int()
name = fields.Str() name = fields.Str()
description = fields.Str() description = fields.Str()
board_size = fields.Int() board_size = fields.Int()
player = fields.Nested(user_schema)
game_room = fields.Int() game_room = fields.Int()
# TODO change players to fields.Nested(UserSchema)
# TODO when you figure out why it's not working
player_black = fields.Int()
player_white = fields.Int()
game_schema = GameSchema() game_schema = GameSchema()
games_schema = GameSchema(many=True) games_schema = GameSchema(many=True)

View file

@ -15,7 +15,7 @@ class Message(db.Model):
content = db.Column(db.String(200), nullable=False) content = db.Column(db.String(200), nullable=False)
# foreign key # foreign key
move = db.Column(db.Integer, db.ForeignKey("moves.id"), nullable=False) move = db.Column(db.ForeignKey("moves.id"), nullable=False)
def __init__(self): def __init__(self):
pass pass

View file

@ -19,14 +19,26 @@ class Move(db.Model):
is_main = db.Column(db.Boolean, nullable=False, default=True) is_main = db.Column(db.Boolean, nullable=False, default=True)
# foreign keys # foreign keys
game = db.Column(db.Integer, db.ForeignKey("games.id"), nullable=False) game = db.Column(db.ForeignKey("games.id"), nullable=False)
preceding_move = db.Column(db.Integer, db.ForeignKey("moves.id")) preceding_move = db.Column(db.Integer, db.ForeignKey("moves.id"))
succeeding_moves = db.relationship(
def __init__(self, game_id, player, x_point, y_point, move_number, is_pass=True, is_main=True, preceding_move=None):
self.game = game_id
if player == 'black':
self.player = 'BLACK'
else:
self.player = 'WHITE'
self.x_point = x_point
self.y_point = y_point
self.move_number = move_number
self.is_pass = is_pass
self.is_main = is_main
self.preceding_move = preceding_move
Move.succeeding_moves = db.relationship(
'Move', 'Move',
lazy='subquery', lazy='subquery',
backref=db.backref('moves', lazy=True) backref=db.backref('moves', lazy=True),
) remote_side=Move.id
)
def __init__(self):
pass

View file

@ -1,5 +1,5 @@
from database import db, ma from database import db, ma
from marshmallow import fields from marshmallow import fields, Schema
from app import bcrypt from app import bcrypt
from configuration import config from configuration import config
import datetime import datetime
@ -63,7 +63,7 @@ class User(db.Model):
rank_certainty = db.Column(db.Boolean, nullable=False, default=False) rank_certainty = db.Column(db.Boolean, nullable=False, default=False)
def __init__(self, username, email, password, rank=Ranks.K1, admin=False): def __init__(self, username, email, password, rank=Ranks.UR, admin=False):
self.username = username self.username = username
self.email = email self.email = email
self.password = bcrypt.generate_password_hash( self.password = bcrypt.generate_password_hash(
@ -107,7 +107,7 @@ class User(db.Model):
except jwt.InvalidTokenError: except jwt.InvalidTokenError:
return 'Invalid token. Please log in again.' return 'Invalid token. Please log in again.'
class UserSchema(ma.ModelSchema): class UserSchema(Schema):
id = fields.Int() id = fields.Int()
username = fields.Str() username = fields.Str()
email = fields.Str() email = fields.Str()
@ -116,6 +116,8 @@ class UserSchema(ma.ModelSchema):
rank_certainty = fields.Bool() rank_certainty = fields.Bool()
elo = fields.Int() elo = fields.Int()
class Meta:
register=True
user_schema = UserSchema() user_schema = UserSchema()
users_schema = UserSchema(many=True) users_schema = UserSchema(many=True)

View file

@ -15,13 +15,14 @@ Flask-SocketIO==4.2.1
Flask-SQLAlchemy==2.4.1 Flask-SQLAlchemy==2.4.1
Flask-Testing==0.7.1 Flask-Testing==0.7.1
greenlet==0.4.15 greenlet==0.4.15
gunicorn==19.9.0
isort==4.3.21 isort==4.3.21
itsdangerous==1.1.0 itsdangerous==1.1.0
Jinja2==2.10.1 Jinja2==2.10.1
lazy-object-proxy==1.4.2 lazy-object-proxy==1.4.2
Mako==1.1.0 Mako==1.1.0
MarkupSafe==1.1.1 MarkupSafe==1.1.1
marshmallow==3.2.0 marshmallow==3.2.1
marshmallow-sqlalchemy==0.19.0 marshmallow-sqlalchemy==0.19.0
mccabe==0.6.1 mccabe==0.6.1
monotonic==1.5 monotonic==1.5

View file

@ -1,6 +1,11 @@
from app import socketio from app import socketio
from flask_socketio import send, emit, join_room, leave_room from flask_socketio import send, emit, join_room, leave_room
import json import json
from models.Game import Game
from models.User import User, user_schema
from models.Move import Move
from database import db
def join_room_notice(room): def join_room_notice(room):
@socketio.on('join room', namespace=f'/{room}') @socketio.on('join room', namespace=f'/{room}')
@ -16,9 +21,36 @@ def new_game_notice(room, game):
def new_room_notice(room): def new_room_notice(room):
socketio.emit('new room', room, broadcast=True) socketio.emit('new room', room, broadcast=True)
def join_game_notice(game_id, user): def join_game_notice(game):
@socketio.on('join game') print('join game')
def return_join_game_notice(data): print(game)
game = data['game'] black = user_schema.dumps(User.query.filter_by(id=game.player_black).first())
join_room(game) white = user_schema.dumps(User.query.filter_by(id=game.player_white).first())
emit('join game', data, room=f'game') room_id = game.game_room
game_id = game.id
print(black)
@socketio.on('join game', namespace=f'/{room_id}')
def handle_join_game(data):
print('emit join game')
join_room(game_id)
emit('join game', {'black': black, 'white': white}, broadcast=True)
@socketio.on('add move', namespace=f'/{room_id}')
def handle_new_move(data):
game_id = data['game']
player = data['move']['player']
x_point = data['move']['x_point']
y_point = data['move']['y_point']
move_number = data['move_number']
try:
move = Move(
game_id=game_id,
player=player,
x_point=x_point,
y_point=y_point,
move_number=move_number
)
db.session.add(move)
db.session.commit()
except Exception as e:
emit('move rejected', e)