123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- from functools import wraps
- import uuid
- from flask import Blueprint, abort, request, jsonify
- from db import db, Game, CoordSet, GuessSet
- from lib import generate_coord, score
- game = Blueprint("game", __name__)
- def require_name():
- name = request.headers.get("Authorization", type=str)
- if name is None:
- abort(401)
- return name.split(maxsplit=1)[-1]
- def require_game(game_id):
- g = Game.query.get(game_id)
- if g is None:
- abort(404)
- return g
- def require_guess_set(game_id):
- name = require_name()
- gs = GuessSet.query.get((game_id, name))
- if gs is None:
- abort(404)
- return gs
- @game.route("", methods=["PUT"])
- def create_game():
- name = require_name()
- timer = request.json.get("timer", None)
- if not isinstance(timer, int) or timer <= 0:
- abort(400)
- game_id = str(uuid.uuid4())
- while Game.query.get(game_id) is not None:
- # basically impossible collision, but let's be safe
- game_id = str(uuid.uuid4())
- cs = CoordSet()
- for round_num in "12345":
- coord = generate_coord()
- while coord is None:
- # very unlikely, but it is possible for generate_coord to fail
- coord = generate_coord()
- cs.set_coord(round_num, *coord)
- db.session.add(cs)
- db.session.commit()
- new_game = Game(
- game_id=game_id,
- timer=timer,
- creator=name,
- coord_set=cs
- )
- db.session.add(new_game)
- db.session.commit()
- gs = GuessSet(game_id=game_id, player_name=name, coord_set=CoordSet())
- db.session.add(gs)
- db.session.commit()
- return jsonify({
- "gameId": game_id
- })
- @game.route("/<game_id>")
- def game_settings(game_id):
- g = require_game(game_id)
- return jsonify({
- "gameId": g.game_id,
- "creator": g.creator,
- "timer": g.timer,
- "coords": g.coord_set.to_dict(),
- "players": sorted([
- {
- "name": gs.player_name,
- "currentRound": gs.get_current_round(),
- "totalScore": gs.get_total_score(),
- "guesses": gs.to_dict(),
- } for gs in g.guess_sets
- ], key=lambda x: x["totalScore"] or 0, reverse=True),
- })
- @game.route("/<game_id>/join", methods=["POST"])
- def join(game_id):
- name = require_name()
- g = require_game(game_id)
- if GuessSet.query.get((g.game_id, name)) is not None:
- abort(409)
- cs = CoordSet()
- db.session.add(cs)
- db.session.commit()
- gs = GuessSet(game_id=g.game_id, player_name=name, coord_set=cs)
- db.session.add(gs)
- db.session.commit()
- return "", 201
- @game.route("/<game_id>/guesses")
- def guesses(game_id):
- gs = require_guess_set(game_id)
- return jsonify({
- "currentRound": gs.get_current_round(),
- "guesses": gs.to_dict(),
- })
- @game.route("/<game_id>/guesses/<round_num>", methods=["POST"])
- def make_guess(game_id, round_num):
- gs = require_guess_set(game_id)
- if round_num != gs.get_current_round():
- abort(409)
- timed_out = request.json.get("timeout", False)
- if timed_out:
- gs.set_timed_out(round_num)
- db.session.commit()
- return jsonify({
- "score": 0,
- "totalScore": gs.get_total_score(),
- }), 201
- lat = request.json.get("lat", None)
- lng = request.json.get("lng", None)
- if not isinstance(lat, float) or not isinstance(lng, float):
- abort(400)
- target = require_game(game_id).coord_set.get_coord(round_num)
- guess_score = score(target, (lat, lng))
- gs.set_guess(round_num, lat, lng, guess_score)
- db.session.commit()
- return jsonify({
- "score": guess_score,
- "totalScore": gs.get_total_score(),
- }), 201
|