|
|
@@ -0,0 +1,1282 @@
|
|
|
+import json
|
|
|
+from flask import render_template, url_for, flash, redirect, session, jsonify, Response, request, current_app, Blueprint, send_file
|
|
|
+from project.models import db, Game, Player, Object, Image, User, SingleplayerGame, get_game_images, reset_db, \
|
|
|
+ ActionCard, GoalCard, CharacterCard
|
|
|
+from PIL import Image as PImage
|
|
|
+from flask_login import LoginManager, login_user, logout_user
|
|
|
+from project.forms import LoginForm
|
|
|
+from flask_limiter import Limiter
|
|
|
+from flask_limiter.util import get_remote_address
|
|
|
+from pathlib import Path
|
|
|
+from werkzeug.utils import secure_filename
|
|
|
+from base64 import b64encode
|
|
|
+from io import BytesIO
|
|
|
+from flask_login import login_required
|
|
|
+import os
|
|
|
+import glob
|
|
|
+
|
|
|
+limiter = Limiter(
|
|
|
+ get_remote_address,
|
|
|
+ default_limits=["20 per second"]
|
|
|
+)
|
|
|
+
|
|
|
+api = Blueprint('api', __name__)
|
|
|
+limiter.limit('20/second')(api)
|
|
|
+
|
|
|
+singleplayer = Blueprint('singleplayer', __name__)
|
|
|
+limiter.limit('20/second')(singleplayer)
|
|
|
+
|
|
|
+login_manager = LoginManager()
|
|
|
+
|
|
|
+
|
|
|
+def __is_game_closed(gameid):
|
|
|
+ game = db.session.query(Game).filter(Game.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return True
|
|
|
+
|
|
|
+ return game.closed
|
|
|
+
|
|
|
+
|
|
|
+# DONE check whether players are claimed before relevant functions
|
|
|
+# DONE restrict interaction with closed games (needed?)
|
|
|
+
|
|
|
+"""
|
|
|
+####################
|
|
|
+
|
|
|
+ MULTIPLAYER
|
|
|
+
|
|
|
+####################
|
|
|
+"""
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/create_game", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def create_game():
|
|
|
+ """ POST like this
|
|
|
+ {
|
|
|
+ players: <int> # numberof players
|
|
|
+ location: <str>
|
|
|
+ }
|
|
|
+
|
|
|
+ returns game instance number(used to refer to game instance in other calls)
|
|
|
+ """
|
|
|
+
|
|
|
+ # extract values and check validity
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # players = content["players"]
|
|
|
+ # location = content["location"]
|
|
|
+ players = request.form.get("players")
|
|
|
+ location = request.form.get("location")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ if (players is None) or (location is None):
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ players = int(players)
|
|
|
+
|
|
|
+ # create Player objects
|
|
|
+ player_list = []
|
|
|
+ for i in range(0, players):
|
|
|
+ p = Player(
|
|
|
+ player_number=i + 1,
|
|
|
+ )
|
|
|
+ player_list.append(p)
|
|
|
+
|
|
|
+ # create game object
|
|
|
+ game = Game(
|
|
|
+ number_of_players=players,
|
|
|
+ location=location,
|
|
|
+ players=player_list
|
|
|
+ )
|
|
|
+
|
|
|
+ # save game to db
|
|
|
+ db.session.add(game)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ # create a response json
|
|
|
+ response = {
|
|
|
+ 'data': game.id,
|
|
|
+ 'message': f'Game {game.id} created successfully'
|
|
|
+ }
|
|
|
+
|
|
|
+ return response, 200, {'Content-Type': 'application/json; charset=utf-8'}
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/is_player_available/<int:gameid>/<int:playerid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def is_player_available(gameid=None, playerid=None):
|
|
|
+ """
|
|
|
+
|
|
|
+ :param gameid: game id
|
|
|
+ :param playerid:game-specific player id
|
|
|
+ :return: "True" or "False" as str
|
|
|
+ """
|
|
|
+ if gameid is None or playerid is None:
|
|
|
+ return "Missing game id or player id", 400
|
|
|
+
|
|
|
+ result = db.session.query(Player.is_taken).filter(Player.game_id == gameid,
|
|
|
+ Player.player_number == playerid).first()
|
|
|
+
|
|
|
+ if result is None:
|
|
|
+ return "No such Game or Player", 400
|
|
|
+
|
|
|
+ return str(not result[0]), 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/select_player", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def select_player():
|
|
|
+ """ POST like this
|
|
|
+ {
|
|
|
+ game: <int> # game id
|
|
|
+ player: <int> # player id in game
|
|
|
+ }
|
|
|
+ """
|
|
|
+
|
|
|
+ # extract values and check validity
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # playerid = content["player"]
|
|
|
+ # gameid = content["game"]
|
|
|
+ playerid = request.form.get("player")
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ if (playerid is None) or (gameid is None):
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ playerid = int(playerid)
|
|
|
+ gameid = int(gameid)
|
|
|
+
|
|
|
+ # check if game is closed. if yes or not found ignore request
|
|
|
+ if __is_game_closed(gameid):
|
|
|
+ return "Game is closed or does not exist", 400
|
|
|
+
|
|
|
+ player = db.session.query(Player).filter(Player.game_id == gameid,
|
|
|
+ Player.player_number == playerid).first()
|
|
|
+
|
|
|
+ # no player found / player already taken
|
|
|
+ if player is None:
|
|
|
+ return "Game or Player does not exist", 400
|
|
|
+ elif player.is_taken:
|
|
|
+ return f"Player {playerid} is already taken", 400
|
|
|
+
|
|
|
+ player.is_taken = True
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Player claimed successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/add_object", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def add_object():
|
|
|
+ """ POST like this
|
|
|
+ {
|
|
|
+ game: <int> # game id
|
|
|
+ player: <int> # player id in game
|
|
|
+ points: <int> # how many points?
|
|
|
+ oid: <int> # id of object
|
|
|
+ }
|
|
|
+ """
|
|
|
+ # extract values and check validity
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # gameid = content["game"]
|
|
|
+ # playerid = content["player"]
|
|
|
+ # points = content["points"]
|
|
|
+ # oid = content["oid"]
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ playerid = request.form.get("player")
|
|
|
+ points = request.form.get("points")
|
|
|
+ oid = request.form.get("oid")
|
|
|
+ longitude = request.form.get("longitude") # optional
|
|
|
+ latitude = request.form.get("latitude") # optional
|
|
|
+ name = request.form.get("name") # optional
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ if (playerid is None) or (gameid is None) or (points is None) or (oid is None):
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+ playerid = int(playerid)
|
|
|
+ points = int(points)
|
|
|
+ oid = int(oid)
|
|
|
+
|
|
|
+ # check if game is closed. if yes or not found ignore request
|
|
|
+ if __is_game_closed(gameid):
|
|
|
+ return "Game is closed or does not exist", 400
|
|
|
+
|
|
|
+ # query player
|
|
|
+ player = db.session.query(Player).filter(Player.game_id == gameid,
|
|
|
+ Player.player_number == playerid).first()
|
|
|
+ # no player found
|
|
|
+ if player is None:
|
|
|
+ return "Game or Player does not exist", 400
|
|
|
+
|
|
|
+ # if player is not taken error
|
|
|
+ if not player.is_taken:
|
|
|
+ return "Player is not taken!", 400
|
|
|
+
|
|
|
+ # it is not the players turn
|
|
|
+ # if not player.is_player_turn:
|
|
|
+ # return "Other players turn", 400
|
|
|
+
|
|
|
+ # check whether object already in play
|
|
|
+ already_in_play = db.session.query(Object).filter(Object.game_id == gameid,
|
|
|
+ Object.object_type == oid).first() is not None
|
|
|
+ if already_in_play:
|
|
|
+ return f"Object {oid} is already in play", 400
|
|
|
+
|
|
|
+ # create and add object to db
|
|
|
+ obj = Object(
|
|
|
+ game_id=gameid,
|
|
|
+ player_number=playerid,
|
|
|
+ object_type=oid,
|
|
|
+ object_points=points,
|
|
|
+ latitude=latitude,
|
|
|
+ longitude=longitude,
|
|
|
+ object_name=name,
|
|
|
+ )
|
|
|
+ db.session.add(obj)
|
|
|
+
|
|
|
+ # add points to player
|
|
|
+ player.points = player.points + points
|
|
|
+
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Object played successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/object_in_play/<int:gameid>/<int:objectid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def object_in_play(gameid=None, objectid=None):
|
|
|
+ # extract and validate
|
|
|
+ if gameid is None or objectid is None:
|
|
|
+ return "Missing game id or object id", 400
|
|
|
+
|
|
|
+ # query object
|
|
|
+ result = db.session.query(Object).filter(Object.game_id == gameid, Object.object_type == objectid).first()
|
|
|
+
|
|
|
+ return str(result is not None), 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/get_all_objects_in_game/<int:gameid>", methods=['GET'])
|
|
|
+@limiter.limit("1/2minute", override_defaults=True)
|
|
|
+def get_all_objects_in_game(gameid=None):
|
|
|
+ objects = db.session.query(Object).filter(Object.game_id == gameid).all()
|
|
|
+
|
|
|
+ obj_json = {}
|
|
|
+
|
|
|
+ for [key, obj] in enumerate(objects):
|
|
|
+ obj_json[key] = obj.to_json()
|
|
|
+
|
|
|
+ response = json.dumps(obj_json)
|
|
|
+
|
|
|
+ return response, 200, {'Content-Type': 'application/json; charset=utf-8'}
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/delete_object", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def delete_object():
|
|
|
+ """ POST like this
|
|
|
+ //TODO only take game and oid
|
|
|
+ {
|
|
|
+ game: <int> # game id
|
|
|
+ oid: <int> # id/type of object
|
|
|
+ }
|
|
|
+ """
|
|
|
+ # extract values and check validity
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # gameid = content["game"]
|
|
|
+ # playerid = content["player"]
|
|
|
+ # points = content["points"]
|
|
|
+ # oid = content["oid"]
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ oid = request.form.get("oid")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ if (gameid is None) or (oid is None):
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+ oid = int(oid)
|
|
|
+
|
|
|
+ # check if game is closed. if yes or not found ignore request
|
|
|
+ if __is_game_closed(gameid):
|
|
|
+ return "Game is closed or does not exist", 400
|
|
|
+
|
|
|
+ obj = db.session.query(Object).filter(Object.game_id == gameid,
|
|
|
+ Object.object_type == oid).first()
|
|
|
+
|
|
|
+ if obj is None:
|
|
|
+ return f"Game {gameid} has no Object with type {oid}", 400
|
|
|
+
|
|
|
+ # query player
|
|
|
+ player = db.session.query(Player).filter(Player.game_id == gameid,
|
|
|
+ Player.player_number == obj.player_number).first()
|
|
|
+ # no player found
|
|
|
+ if player is None:
|
|
|
+ return "Player does not exist", 400
|
|
|
+
|
|
|
+ # if player is not taken error
|
|
|
+ if not player.is_taken:
|
|
|
+ return "Player is not taken!", 400
|
|
|
+
|
|
|
+ player.points = player.points - obj.object_points
|
|
|
+
|
|
|
+ db.session.delete(obj)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Object deleted successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+"""
|
|
|
+@api.route("/set_turn_to_next_player", methods=['POST'])
|
|
|
+def set_turn_to_next_player():
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # gameid = content["game"]
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+
|
|
|
+ if type(gameid) is not int:
|
|
|
+ return "Wrong Data", 400
|
|
|
+
|
|
|
+ game = db.session.query(Game).filter(Game.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ # no longer current player's turn
|
|
|
+ player_curr = db.session.query(Player).filter(Player.game_id == gameid,
|
|
|
+ Player.is_player_turn).first()
|
|
|
+
|
|
|
+ # who's turn is it next?
|
|
|
+ number_of_player = game.number_of_players
|
|
|
+ next_player = game.current_player + 1
|
|
|
+ if next_player > number_of_player:
|
|
|
+ next_player = 1
|
|
|
+
|
|
|
+ # set turn to next players in Game and Player Objects
|
|
|
+ game.current_player = next_player
|
|
|
+ player_next = db.session.query(Player).filter(Player.game_id == gameid,
|
|
|
+ Player.player_number == next_player).first()
|
|
|
+
|
|
|
+ if not player_next.is_taken:
|
|
|
+ return "Next player is not taken!", 400
|
|
|
+
|
|
|
+ player_curr.is_player_turn = False
|
|
|
+ player_next.is_player_turn = True
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return f"Game {gameid}: Turn switched successfully", 200
|
|
|
+"""
|
|
|
+
|
|
|
+"""@api.route("/get_current_player_turn/<int:gameid>", methods=['GET'])
|
|
|
+def get_current_player_turn(gameid=None):
|
|
|
+ if gameid is None:
|
|
|
+ return "Missing game id", 400
|
|
|
+
|
|
|
+ game = db.session.query(Game).filter(Game.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ current_player = game.current_player
|
|
|
+
|
|
|
+ # create a response json
|
|
|
+ response = {
|
|
|
+ 'data': current_player,
|
|
|
+ 'message': f"Game {game.id}: Player {current_player}'s turn"
|
|
|
+ }
|
|
|
+
|
|
|
+ return response, 200, {'Content-Type': 'application/json; charset=utf-8'}"""
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/get_all_player_points/<int:gameid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def get_all_player_points(gameid=None):
|
|
|
+ """
|
|
|
+
|
|
|
+ :param gameid: game id
|
|
|
+ :return: {
|
|
|
+ 1: 20 <playerid>: <points>
|
|
|
+ 2: 15
|
|
|
+ 3: 12
|
|
|
+ }
|
|
|
+ """
|
|
|
+ if gameid is None:
|
|
|
+ return "Missing game id", 400
|
|
|
+
|
|
|
+ players = db.session.query(Player).filter(Player.game_id == gameid).all()
|
|
|
+
|
|
|
+ if len(players) == 0:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ players_points = {}
|
|
|
+ for player in players:
|
|
|
+ players_points[f'{player.player_number}'] = player.points
|
|
|
+
|
|
|
+ return players_points, 200, {'Content-Type': 'application/json; charset=utf-8'}
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/get_total_number_of_players/<int:gameid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def get_total_number_of_players(gameid=None):
|
|
|
+ if gameid is None:
|
|
|
+ return "Missing game id", 400
|
|
|
+
|
|
|
+ game = db.session.query(Game).filter(Game.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ # create a response json
|
|
|
+ response = {
|
|
|
+ 'data': game.number_of_players,
|
|
|
+ 'message': f"Game {game.id} has {game.number_of_players} Players"
|
|
|
+ }
|
|
|
+
|
|
|
+ return response, 200, {'Content-Type': 'application/json; charset=utf-8'}
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/get_cards_in_game/<int:gameid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def get_cards_in_game(gameid=None):
|
|
|
+ """
|
|
|
+
|
|
|
+ :param gameid: game id
|
|
|
+ :return: {
|
|
|
+ 1: 20 <playerid>: <goal card>
|
|
|
+ 2: 15
|
|
|
+ 3: 12
|
|
|
+ }
|
|
|
+ """
|
|
|
+ if gameid is None:
|
|
|
+ return "Missing game id", 400
|
|
|
+
|
|
|
+ players = db.session.query(Player).filter(Player.game_id == gameid).all()
|
|
|
+
|
|
|
+ if len(players) == 0:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ players_goal = {}
|
|
|
+ for player in players:
|
|
|
+ players_goal[f'{player.player_number}'] = player.goal_card_id
|
|
|
+
|
|
|
+ return players_goal, 200, {'Content-Type': 'application/json; charset=utf-8'}
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/add_card_to_player", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def add_card_to_player():
|
|
|
+ """ POST like this
|
|
|
+ {
|
|
|
+ game: <int> # game id
|
|
|
+ player: <int> # player id in game
|
|
|
+ cid: <int> # id of card
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # gameid = content["game"]
|
|
|
+ # playerid = content["player"]
|
|
|
+ # cid = content["cid"]
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ playerid = request.form.get("player")
|
|
|
+ cid = request.form.get("cid")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ if (gameid is None) or (playerid is None) or (cid is None):
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+ playerid = int(playerid)
|
|
|
+ cid = int(cid)
|
|
|
+
|
|
|
+ # check if game is closed. if yes or not found ignore request
|
|
|
+ if __is_game_closed(gameid):
|
|
|
+ return "Game is closed or does not exist", 400
|
|
|
+
|
|
|
+ player = db.session.query(Player).filter(Player.game_id == gameid,
|
|
|
+ Player.player_number == playerid).first()
|
|
|
+
|
|
|
+ # no player found
|
|
|
+ if player is None:
|
|
|
+ return "Game or Player does not exist", 400
|
|
|
+
|
|
|
+ goal_card = db.session.query(GoalCard).filter(GoalCard.card_id == cid).first()
|
|
|
+
|
|
|
+ # no such char card exists
|
|
|
+ if goal_card is None:
|
|
|
+ return f"There is no goal card with the id {cid}", 400
|
|
|
+
|
|
|
+ # assign goal card
|
|
|
+ goal_card.players.append(player)
|
|
|
+
|
|
|
+ # player.goal_card_id = cid
|
|
|
+
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Goal Card saved successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/add_char_card_to_player", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def add_char_card_to_player():
|
|
|
+ """
|
|
|
+ Adds the specified character card id to the specified player of a specified game
|
|
|
+
|
|
|
+ POST like this
|
|
|
+ {
|
|
|
+ game: <int> # game id
|
|
|
+ player: <int> # player id in game
|
|
|
+ charid: <int> # id of character card
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # gameid = content["game"]
|
|
|
+ # playerid = content["player"]
|
|
|
+ # cid = content["cid"]
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ playerid = request.form.get("player")
|
|
|
+ charid = request.form.get("charid")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ if (gameid is None) or (playerid is None) or (charid is None):
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+ playerid = int(playerid)
|
|
|
+ charid = int(charid)
|
|
|
+
|
|
|
+ # check if game is closed. if yes or not found ignore request
|
|
|
+ if __is_game_closed(gameid):
|
|
|
+ return "Game is closed or does not exist", 400
|
|
|
+
|
|
|
+ player = db.session.query(Player).filter(Player.game_id == gameid,
|
|
|
+ Player.player_number == playerid).first()
|
|
|
+
|
|
|
+ # no player found
|
|
|
+ if player is None:
|
|
|
+ return "Game or Player does not exist", 400
|
|
|
+
|
|
|
+ char_card = db.session.query(CharacterCard).filter(CharacterCard.card_id == charid).first()
|
|
|
+
|
|
|
+ # no such char card exists
|
|
|
+ if char_card is None:
|
|
|
+ return f"There is no character card with the id {charid}", 400
|
|
|
+
|
|
|
+ # assign char card
|
|
|
+ char_card.players.append(player)
|
|
|
+ # player.character_card_id = charid
|
|
|
+
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Character Card saved successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/add_action_card_to_player", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def add_action_card_to_player():
|
|
|
+ """
|
|
|
+ Adds the specified action card to the specified player of a specified game
|
|
|
+
|
|
|
+ POST like this
|
|
|
+ {
|
|
|
+ game: <int> # game id
|
|
|
+ player: <int> # player id in game
|
|
|
+ actionCardID: <int> # id of character card
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # gameid = content["game"]
|
|
|
+ # playerid = content["player"]
|
|
|
+ # cid = content["cid"]
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ playerid = request.form.get("player")
|
|
|
+ actionid = request.form.get("actionCardID")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ if (gameid is None) or (playerid is None) or (actionid is None):
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+ playerid = int(playerid)
|
|
|
+ actionid = int(actionid)
|
|
|
+
|
|
|
+ # check if game is closed. if yes or not found ignore request
|
|
|
+ if __is_game_closed(gameid):
|
|
|
+ return "Game is closed or does not exist", 400
|
|
|
+
|
|
|
+ player = db.session.query(Player).filter(Player.game_id == gameid,
|
|
|
+ Player.player_number == playerid).first()
|
|
|
+
|
|
|
+ # no player found
|
|
|
+ if player is None:
|
|
|
+ return "Game or Player does not exist", 400
|
|
|
+
|
|
|
+ action_card = db.session.query(ActionCard).filter(ActionCard.card_id == actionid).first()
|
|
|
+
|
|
|
+ # no such char card exists
|
|
|
+ if action_card is None:
|
|
|
+ return f"There is no action card with the id {actionid}", 400
|
|
|
+
|
|
|
+ # assign char card
|
|
|
+ player.drawn_action_cards.append(action_card)
|
|
|
+ # player.character_card_id = charid
|
|
|
+
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Action Card assigned successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/get_char_cards_in_game/<int:gameid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def get_char_cards_in_game(gameid=None):
|
|
|
+ """
|
|
|
+ returns a dictionary listing the character card id for every player of a game
|
|
|
+ :param gameid: game id
|
|
|
+ :return: {
|
|
|
+ 1: 20 <playerid>: <character card>
|
|
|
+ 2: 15
|
|
|
+ 3: 12
|
|
|
+ }
|
|
|
+ """
|
|
|
+ if gameid is None:
|
|
|
+ return "Missing game id", 400
|
|
|
+
|
|
|
+ players = db.session.query(Player).filter(Player.game_id == gameid).all()
|
|
|
+
|
|
|
+ if len(players) == 0:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ players_char = {}
|
|
|
+ for player in players:
|
|
|
+ players_char[f'{player.player_number}'] = player.character_card_id
|
|
|
+
|
|
|
+ return players_char, 200, {'Content-Type': 'application/json; charset=utf-8'}
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/add_action_card", methods=["POST"])
|
|
|
+@limiter.exempt()
|
|
|
+@login_required
|
|
|
+def add_action_card():
|
|
|
+ """
|
|
|
+ Add an action card to the game database
|
|
|
+
|
|
|
+ POST like this
|
|
|
+ {
|
|
|
+ cardid: <int> # id of action card
|
|
|
+ action: <str> # description of the action
|
|
|
+ img: file # img file
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ cardid = request.form.get('cardid')
|
|
|
+ action = request.form.get('action')
|
|
|
+ img = request.files['img']
|
|
|
+
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ if (cardid is None) or (action is None) or (img.content_type is None):
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ cardid = int(cardid)
|
|
|
+
|
|
|
+ action_card = db.session.query(ActionCard).filter(ActionCard.card_id == cardid).first()
|
|
|
+
|
|
|
+ if action_card is not None:
|
|
|
+ return "An action card with this id already exists", 400
|
|
|
+
|
|
|
+ filename = f"actioncard_{cardid}.png"
|
|
|
+ img_path = os.path.join(f"{os.getenv('APP_FOLDER')}/project/images/", filename)
|
|
|
+ img.save(img_path)
|
|
|
+
|
|
|
+ ac = ActionCard(
|
|
|
+ card_id=cardid,
|
|
|
+ action=action,
|
|
|
+ img_path=img_path
|
|
|
+ )
|
|
|
+
|
|
|
+ db.session.add(ac)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Action card added successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/delete_action_card", methods=["POST"])
|
|
|
+@limiter.exempt()
|
|
|
+@login_required
|
|
|
+def delete_action_card():
|
|
|
+ """
|
|
|
+ Add an action card to the game database
|
|
|
+
|
|
|
+ POST like this
|
|
|
+ {
|
|
|
+ cardid: <int> # id of action card
|
|
|
+ action: <str> # description of the action
|
|
|
+ img: file # img file
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ cardid = request.form.get('cardid')
|
|
|
+
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ if (cardid is None):
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ cardid = int(cardid)
|
|
|
+
|
|
|
+ action_card = db.session.query(ActionCard).filter(ActionCard.card_id == cardid).first()
|
|
|
+
|
|
|
+ if action_card is None:
|
|
|
+ return "An action card with this id does not exists", 400
|
|
|
+
|
|
|
+ filename = f"actioncard_{cardid}.png"
|
|
|
+ img_path = os.path.join(f"{os.getenv('APP_FOLDER')}/project/images/", filename)
|
|
|
+ os.remove(img_path)
|
|
|
+
|
|
|
+ db.session.delete(action_card)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Action card deleted successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/add_goal_card", methods=["POST"])
|
|
|
+@limiter.exempt()
|
|
|
+@login_required
|
|
|
+def add_goal_card():
|
|
|
+ """
|
|
|
+ Add a goal card to the game database
|
|
|
+
|
|
|
+ POST like this
|
|
|
+ {
|
|
|
+ cardid: <int> # id of goal card
|
|
|
+ goal: <str> # description of the action
|
|
|
+ img: file # img file
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ cardid = request.form.get('cardid')
|
|
|
+ goal = request.form.get('goal')
|
|
|
+ img = request.files['img']
|
|
|
+
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ if (cardid is None) or (goal is None) or (img.content_type is None):
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ cardid = int(cardid)
|
|
|
+
|
|
|
+ goal_card = db.session.query(GoalCard).filter(GoalCard.card_id == cardid).first()
|
|
|
+
|
|
|
+ if goal_card is not None:
|
|
|
+ return "A goal card with this id already exists", 400
|
|
|
+
|
|
|
+ filename = f"goalcard_{cardid}.png"
|
|
|
+ img_path = os.path.join(f"{os.getenv('APP_FOLDER')}/project/images/", filename)
|
|
|
+ img.save(img_path)
|
|
|
+
|
|
|
+ gc = GoalCard(
|
|
|
+ card_id=cardid,
|
|
|
+ goal=goal,
|
|
|
+ img_path=img_path
|
|
|
+ )
|
|
|
+
|
|
|
+ db.session.add(gc)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Goal card added successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/delete_goal_card", methods=["POST"])
|
|
|
+@limiter.exempt()
|
|
|
+@login_required
|
|
|
+def delete_goal_card():
|
|
|
+ """
|
|
|
+ Delete a Goal Card from the database
|
|
|
+
|
|
|
+ POST like this
|
|
|
+ {
|
|
|
+ cardid: <int> # id of goal card
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ cardid = request.form.get('cardid')
|
|
|
+
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ if (cardid is None):
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ cardid = int(cardid)
|
|
|
+
|
|
|
+ goal_card = db.session.query(GoalCard).filter(GoalCard.card_id == cardid).first()
|
|
|
+
|
|
|
+ if goal_card is None:
|
|
|
+ return "A goal card with this id does not exists", 400
|
|
|
+
|
|
|
+ filename = f"goalcard_{cardid}.png"
|
|
|
+ img_path = os.path.join(f"{os.getenv('APP_FOLDER')}/project/images/", filename)
|
|
|
+ os.remove(img_path)
|
|
|
+
|
|
|
+ db.session.delete(goal_card)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Goal card deleted successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/add_char_card", methods=["POST"])
|
|
|
+@limiter.exempt()
|
|
|
+@login_required
|
|
|
+def add_char_card():
|
|
|
+ """
|
|
|
+ Add a character card to the game database
|
|
|
+
|
|
|
+ POST like this
|
|
|
+ {
|
|
|
+ cardid: <int> # id of character card
|
|
|
+ img: file # img file
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ cardid = request.form.get('cardid')
|
|
|
+ name = request.form.get('name')
|
|
|
+ age = request.form.get('age')
|
|
|
+ role = request.form.get('role')
|
|
|
+ interest = request.form.get('interest')
|
|
|
+ quote = request.form.get('quote')
|
|
|
+ img = request.files['img']
|
|
|
+
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ if (cardid is None) or (name is None) or (age is None) or (role is None) or (interest is None) or (
|
|
|
+ quote is None) or (img.content_type is None):
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ cardid = int(cardid)
|
|
|
+
|
|
|
+ char_card = db.session.query(CharacterCard).filter(CharacterCard.card_id == cardid).first()
|
|
|
+
|
|
|
+ if char_card is not None:
|
|
|
+ return "A character card with this id already exists", 400
|
|
|
+
|
|
|
+ filename = f"charactercard_{cardid}.png"
|
|
|
+ img_path = os.path.join(f"{os.getenv('APP_FOLDER')}/project/images/", filename)
|
|
|
+ img.save(img_path)
|
|
|
+
|
|
|
+ cc = CharacterCard(
|
|
|
+ card_id=cardid,
|
|
|
+ name=name,
|
|
|
+ age=age,
|
|
|
+ role=role,
|
|
|
+ interest=interest,
|
|
|
+ quote=quote,
|
|
|
+ img_path=img_path
|
|
|
+ )
|
|
|
+
|
|
|
+ db.session.add(cc)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Character card added successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/delete_char_card", methods=["POST"])
|
|
|
+@limiter.exempt()
|
|
|
+@login_required
|
|
|
+def delete_char_card():
|
|
|
+ """
|
|
|
+ delete a char card from the game database
|
|
|
+
|
|
|
+ POST like this
|
|
|
+ {
|
|
|
+ cardid: <int> # id of action card
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ cardid = request.form.get('cardid')
|
|
|
+
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ if (cardid is None):
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ cardid = int(cardid)
|
|
|
+
|
|
|
+ char_card = db.session.query(CharacterCard).filter(CharacterCard.card_id == cardid).first()
|
|
|
+
|
|
|
+ if char_card is None:
|
|
|
+ return "A character card with this id does not exists", 400
|
|
|
+
|
|
|
+ filename = f"charactercard_{cardid}.png"
|
|
|
+ img_path = os.path.join(f"{os.getenv('APP_FOLDER')}/project/images/", filename)
|
|
|
+ os.remove(img_path)
|
|
|
+
|
|
|
+ db.session.delete(char_card)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Action card deleted successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route('/get_card_image/<subpath>', methods=['GET'])
|
|
|
+@limiter.exempt()
|
|
|
+@login_required
|
|
|
+def get_card_image(subpath):
|
|
|
+ # Here you would dynamically serve the file based on subpath
|
|
|
+ # For demonstration purposes, let's assume all images are in /static/images/
|
|
|
+ img_path = os.path.join(f"{os.getenv('APP_FOLDER')}/project/images", subpath)
|
|
|
+ return send_file(img_path)
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/add_image_to_game", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def add_image_to_game():
|
|
|
+ """
|
|
|
+ send data as form-data, otherwise wont work
|
|
|
+ 2 keys:
|
|
|
+ 'game' which should contain game id
|
|
|
+ 'img' the image file
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ gameid = request.form.get('game')
|
|
|
+ img = request.files['img']
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ if gameid is None or img.content_type is None:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+
|
|
|
+ # does game exist?
|
|
|
+ game = db.session.query(Game).filter(Game.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ if game.closed:
|
|
|
+ return f"Game {gameid} is closed", 400
|
|
|
+
|
|
|
+ # how many images are there already?
|
|
|
+ image_count = db.session.query(Image).filter(Image.game_id == gameid).count()
|
|
|
+
|
|
|
+ # if there are already 5 discard request
|
|
|
+ if image_count >= 5:
|
|
|
+ return f"Game {gameid} already has 5 images saved.", 400
|
|
|
+
|
|
|
+ # else save image to path and create db entry
|
|
|
+ # img = PImage.open(img)
|
|
|
+ # this_folder = Path(__file__).parent.resolve()
|
|
|
+ # img_path = str(this_folder / f"images/{gameid}_{image_count + 1}.png")
|
|
|
+ ## img_path = f'/server/images/{gameid}_{image_count + 1}.png'
|
|
|
+ # img.save(img_path)
|
|
|
+
|
|
|
+ filename = f"{gameid}_{image_count + 1}.png"
|
|
|
+ img_path = os.path.join(f"{os.getenv('APP_FOLDER')}/project/images", filename)
|
|
|
+ img.save(img_path)
|
|
|
+
|
|
|
+ image = Image(
|
|
|
+ game_id=gameid,
|
|
|
+ img_path=img_path
|
|
|
+ )
|
|
|
+
|
|
|
+ db.session.add(image)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return "Image saved successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/get_next_game_id", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def get_next_game_id():
|
|
|
+ game = db.session.query(Game.id).order_by(Game.id.desc()).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return "1", 200
|
|
|
+
|
|
|
+ next_id = game[0] + 1
|
|
|
+
|
|
|
+ return f"{next_id}", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/close_game", methods=['POST'])
|
|
|
+@limiter.exempt
|
|
|
+def close_game():
|
|
|
+ """ POST like this
|
|
|
+ {
|
|
|
+ game: <int> # game id to close
|
|
|
+ }
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ # content = request.get_json()
|
|
|
+ # gameid = content["game"]
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ if gameid is None:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+
|
|
|
+ game = db.session.query(Game).filter(Game.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return "Game does not exist", 400
|
|
|
+
|
|
|
+ if game.closed:
|
|
|
+ return "Game already closed", 400
|
|
|
+
|
|
|
+ game.closed = True
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return f"Game {gameid} closed successfully", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/is_game_closed/<int:gameid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def is_game_closed(gameid=None):
|
|
|
+ if gameid is None:
|
|
|
+ return "game id is missing", 400
|
|
|
+
|
|
|
+ game = db.session.query(Game).filter(Game.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return "Game does not exist", 400
|
|
|
+
|
|
|
+ return f"{game.closed}", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route("/get_object_owner/<int:gameid>/<int:oid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def get_object_owner(gameid=None, oid=None):
|
|
|
+ """
|
|
|
+
|
|
|
+ :param gameid: id of game
|
|
|
+ :param oid: object id
|
|
|
+ :return: number of player who owns object
|
|
|
+ """
|
|
|
+ if gameid is None or oid is None:
|
|
|
+ return "game id or object id is missing", 400
|
|
|
+
|
|
|
+ owner = db.session.query(Object).filter(Object.game_id == gameid,
|
|
|
+ Object.object_type == oid).first()
|
|
|
+
|
|
|
+ if owner is None:
|
|
|
+ return f"No player has played object {oid}", 400
|
|
|
+
|
|
|
+ return f"{owner.player_number}", 200
|
|
|
+
|
|
|
+
|
|
|
+@api.route('/get_images/<int:id>', methods=["GET"])
|
|
|
+@limiter.exempt
|
|
|
+@login_required
|
|
|
+def get_images(id=None):
|
|
|
+ if id is None:
|
|
|
+ return "Attribute is None", 400
|
|
|
+
|
|
|
+ imgs = get_game_images(id)
|
|
|
+
|
|
|
+ images = {}
|
|
|
+
|
|
|
+ for img in imgs:
|
|
|
+ if f"{img.game_id}" not in images:
|
|
|
+ images[f"{img.game_id}"] = []
|
|
|
+
|
|
|
+ image = PImage.open(img.img_path)
|
|
|
+ image_io = BytesIO()
|
|
|
+ image.save(image_io, 'PNG')
|
|
|
+ images[f"{img.game_id}"].append('data:image/png;base64,' + b64encode(image_io.getvalue()).decode('ascii'))
|
|
|
+
|
|
|
+ return {'data': images}, 200, {'Content-Type': 'application/json; charset=utf-8'}
|
|
|
+
|
|
|
+
|
|
|
+@api.route('/reset_database', methods=["POST"])
|
|
|
+@limiter.exempt
|
|
|
+@login_required
|
|
|
+def reset_database():
|
|
|
+ """
|
|
|
+ Deletes every entry in database apart from User. Game ID sequence will not be resetted
|
|
|
+ Also dleets all images from the file system
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ content = request.get_json()
|
|
|
+ password = content["password"]
|
|
|
+ except KeyError:
|
|
|
+ return "Missing data or wrong key name", 400
|
|
|
+
|
|
|
+ user = db.session.query(User).first()
|
|
|
+ if not user.verify_password(password):
|
|
|
+ return "Wrong Password", 401
|
|
|
+
|
|
|
+ db.session.query(Game).delete()
|
|
|
+ db.session.query(SingleplayerGame).delete()
|
|
|
+ db.session.query(Player).delete()
|
|
|
+ db.session.query(Object).delete()
|
|
|
+ db.session.query(CharacterCard).delete()
|
|
|
+ db.session.query(GoalCard).delete()
|
|
|
+ db.session.query(ActionCard).delete()
|
|
|
+
|
|
|
+ files = glob.glob(f"{current_app.config['MEDIA_FOLDER']}/*")
|
|
|
+ for f in files:
|
|
|
+ print(f)
|
|
|
+ os.remove(f)
|
|
|
+
|
|
|
+ db.session.query(Image).delete()
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ # This resets the Primary Key sequence for Game table such that the game ids start with 1 again.
|
|
|
+ # Alternatively one can also continue the ids however this is a problem when retrieving the last_value of the sequence
|
|
|
+ # This is because for the 1st and 2nd interation of the sequence last_value returns 2, since nextval() does not increment on first call
|
|
|
+ db.engine.execute("ALTER SEQUENCE game_id_seq RESTART WITH 1")
|
|
|
+
|
|
|
+ return "DB is empty again", 200
|
|
|
+
|
|
|
+
|
|
|
+"""
|
|
|
+####################
|
|
|
+
|
|
|
+ SINGLEPLAYER
|
|
|
+
|
|
|
+####################
|
|
|
+"""
|
|
|
+
|
|
|
+
|
|
|
+@singleplayer.route("/new_game", methods=["POST"])
|
|
|
+@limiter.exempt
|
|
|
+def new_game():
|
|
|
+ game = SingleplayerGame()
|
|
|
+
|
|
|
+ db.session.add(game)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return f"{game.id}", 200
|
|
|
+
|
|
|
+
|
|
|
+@singleplayer.route("/add_point_information", methods=["POST"])
|
|
|
+@limiter.exempt
|
|
|
+def add_point_information():
|
|
|
+ """ POST like this
|
|
|
+ {
|
|
|
+ game: <int> # game id
|
|
|
+ player: <int> # player id in game 1-5
|
|
|
+ points: <int> # how many points?
|
|
|
+ }
|
|
|
+ """
|
|
|
+ # extract values and check validity
|
|
|
+ try:
|
|
|
+ gameid = request.form.get("game")
|
|
|
+ playerid = request.form.get("player")
|
|
|
+ points = request.form.get("points")
|
|
|
+ except KeyError:
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ if (gameid is None) or (playerid is None) or (points is None):
|
|
|
+ return "Missing Data", 400
|
|
|
+
|
|
|
+ gameid = int(gameid)
|
|
|
+ playerid = int(playerid)
|
|
|
+ points = int(points)
|
|
|
+
|
|
|
+ if playerid < 1 or playerid > 5:
|
|
|
+ return f"Player {playerid} does not exist.", 400
|
|
|
+
|
|
|
+ game = db.session.query(SingleplayerGame).filter(SingleplayerGame.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ setattr(game, f"player_{playerid}_points", getattr(game, f"player_{playerid}_points") + points)
|
|
|
+
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ return f"Successfully added {points} points to player {playerid}.", 200
|
|
|
+
|
|
|
+
|
|
|
+@singleplayer.route("/get_point_information/<int:gameid>", methods=['GET'])
|
|
|
+@limiter.exempt
|
|
|
+def get_point_information(gameid=None):
|
|
|
+ game = db.session.query(SingleplayerGame).filter(SingleplayerGame.id == gameid).first()
|
|
|
+
|
|
|
+ if game is None:
|
|
|
+ return f"Game {gameid} does not exist", 400
|
|
|
+
|
|
|
+ response_json = {
|
|
|
+ 'player1': str(game.player_1_points),
|
|
|
+ 'player2': str(game.player_2_points),
|
|
|
+ 'player3': str(game.player_3_points),
|
|
|
+ 'player4': str(game.player_4_points),
|
|
|
+ 'player5': str(game.player_5_points)
|
|
|
+ }
|
|
|
+
|
|
|
+ return Response(json.dumps(response_json), status=200, mimetype='application/json')
|
|
|
+
|
|
|
+
|
|
|
+"""
|
|
|
+####################
|
|
|
+
|
|
|
+ AUTHENTICATION
|
|
|
+
|
|
|
+####################
|
|
|
+"""
|
|
|
+
|
|
|
+auth = Blueprint('auth', __name__)
|
|
|
+limiter.limit('20/second')(auth)
|
|
|
+
|
|
|
+
|
|
|
+@login_manager.user_loader
|
|
|
+def get_user(user_id):
|
|
|
+ return db.session.get(User, user_id)
|
|
|
+
|
|
|
+
|
|
|
+@auth.route("/login", methods=["GET", "POST"])
|
|
|
+@limiter.exempt
|
|
|
+def login():
|
|
|
+ form = LoginForm()
|
|
|
+ username = form.username.data
|
|
|
+ password = form.password.data
|
|
|
+
|
|
|
+ if form.validate_on_submit():
|
|
|
+ user = User.query.filter_by(username=username).first()
|
|
|
+
|
|
|
+ if user and user.verify_password(password):
|
|
|
+ login_user(user)
|
|
|
+ flash("logged in!")
|
|
|
+ return redirect(url_for('index'))
|
|
|
+ else:
|
|
|
+ flash("login failed!")
|
|
|
+ else:
|
|
|
+ print(form.errors)
|
|
|
+
|
|
|
+ return render_template('login.html', form=form)
|
|
|
+
|
|
|
+
|
|
|
+@auth.route('/logout')
|
|
|
+@limiter.exempt
|
|
|
+def logout():
|
|
|
+ logout_user()
|
|
|
+ return redirect(url_for('auth.login'))
|