from flask import Flask, redirect, flash, render_template, session, g, request, get_flashed_messages import werkzeug.exceptions import json import hra.config as config import hra.db as db from hra.web import app, NeedLoginError import hra.web.jinja_mac as jinja_mac def args_get(name, type, optional=False, default=None): v = request.args.get(name) if v is None: if optional: return default else: raise werkzeug.exceptions.BadRequest(f"Missing mandatory option {name}.") try: return type(v) except ValueError: raise werkzeug.exceptions.BadRequest(f"Option {name} have wrong type.") def get_context(): if g.user is None: raise NeedLoginError game_name = args_get("game", str, True, "main") team = db.get_session().query(db.Team).filter_by(user_id=g.user.id, name=game_name).one_or_none() if team is None: raise werkzeug.exceptions.NotFound("No such game") return team @app.route("/api/state", methods=['GET']) def api_state(): team = get_context() game = team.game team_id = team.team_id min_round = args_get("min_round", int, True) if min_round is not None and min_round > game.current_round: return json.dumps({ "status": "too-early", "wait": 5.0, }) state = game.current_state() if state is None: return json.dumps({ "status": "working", "wait": 1.0, }) return json.dumps({ "status": "ok", "round": state.round, "team_id": team_id, "state": game.get_logic().personalize_state(state.state, team_id, state.round), }) @app.route("/api/action", methods=['POST']) def api_action(): def to_late(): return json.dumps({ "status": "too-late", }) team = get_context() game = team.game team_id = team.team_id j = request.get_json() state = game.current_state() round_id = args_get('round', int) if round_id < 0 or round_id > game.current_round: raise werkzeug.exceptions.BadRequest("Wrong round.") if game.working_on_next_state or round_id < game.current_round: return to_late() try: warnings = game.get_logic().validate_move(state.state, team_id, j, round_id) except Exception as e: return json.dumps({ "error": "error", "description": f"{type(e).__name__}: {e}" }) db.get_session().expire_all() game = game.lock() if game.working_on_next_state or round_id < game.current_round: db.get_session().commit() return to_late() move = db.get_session().query(db.Move).filter_by(game_id=game.game_id, team_id=team_id, round=round_id).one_or_none() if move is None: move = db.Move(game_id=game.game_id, team_id=team_id, round=round_id) db.get_session().add(move) move.move = j db.get_session().commit() if warnings is not None: return json.dumps(warnings) return json.dumps({ "status": "ok", })