123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- from flask import Blueprint, abort, request, jsonify
- import db
- import lib
- from sources import sources, restock_all
- restock_all()
- game = Blueprint("game", __name__)
- def require_game(game_id):
- g = db.Game.query.get(game_id)
- if g is None:
- abort(404)
- return g
- def require_player(game_id):
- auth = request.headers.get("Authorization", type=str)
- if auth is None:
- abort(401)
- try:
- pid = int(auth.split(maxsplit=1)[-1])
- except ValueError:
- abort(401)
- player = db.Player.query.get(pid)
- if player is None:
- abort(404)
- return player
- @game.route("", methods=["PUT"])
- def create_game():
- js = request.get_json()
- if js is None:
- abort(400)
- timer = js.get("timer", None)
- if not isinstance(timer, int) or timer <= 0:
- abort(400)
- rounds = js.get("rounds", None)
- if not isinstance(rounds, int) or rounds <= 0:
- abort(400)
- only_america = js.get("onlyAmerica", False)
- if not isinstance(only_america, bool):
- abort(400)
- gen_method = js.get("generationMethod", "MAPCRUNCH")
- if not isinstance(gen_method, str):
- abort(400)
- rule_set = js.get("ruleSet", "NORMAL")
- if not isinstance(rule_set, str):
- abort(400)
- src = sources.get((gen_method, only_america), None)
- if src is None:
- abort(400)
-
- coords = src.get_points(n=rounds)
- new_game = db.Game.create(timer, rounds, only_america, gen_method, rule_set, coords)
- return jsonify({"gameId": new_game.game_id})
- @game.route("/<game_id>/config")
- def game_config(game_id):
- g = require_game(game_id)
- return jsonify({
- "timer": g.timer,
- "rounds": g.rounds,
- "onlyAmerica": g.only_america,
- "generationMethod": g.gen_method,
- "ruleSet": g.rule_set,
- })
- @game.route("/<game_id>/coords")
- def coords(game_id):
- g = require_game(game_id)
- return jsonify({
- str(c.round_number): {
- "lat": c.latitude,
- "lng": c.longitude,
- } for c in g.coordinates
- })
- @game.route("/<game_id>/players")
- def players(game_id):
- g = require_game(game_id)
- return jsonify({
- "players": [{
- "name": p.player_name,
- "currentRound": p.get_current_round(),
- "totalScore": p.get_total_score(),
- "guesses": {
- str(g.round_number): {
- "lat": g.latitude,
- "lng": g.longitude,
- "score": g.round_score,
- "timeRemaining": g.time_remaining,
- } for g in p.guesses
- },
- } for p in g.players]
- })
- @game.route("/<game_id>/linked", methods=["GET", "POST"])
- def link_game(game_id):
- g = require_game(game_id)
- if request.method == "GET":
- return jsonify({"linkedGame": g.linked_game})
- js = request.get_json()
- if js is None:
- abort(400)
- link_id = js.get("linkedGame", None)
- if link_id is None or db.Game.query.get(link_id) is None:
- abort(401)
-
- g.link(link_id)
- return "", 201
- @game.route("/<game_id>/round/<int:round_num>/first")
- def first_submitter(game_id, round_num):
- fs = db.FirstSubmission.query.get((game_id, round_num))
- if fs is None:
- abort(404)
- return jsonify({
- "first": fs.player_name
- })
-
- @game.route("/<game_id>/join", methods=["POST"])
- def join(game_id):
- js = request.get_json()
- if js is None:
- abort(400)
- name = js.get("playerName", None)
- if name is None:
- abort(400)
- g = require_game(game_id)
- if db.Player.query.filter(db.Player.game_id == game_id, db.Player.player_name == name).first() is not None:
- abort(409)
- p = g.join(name)
- return jsonify({
- "playerId": str(p.player_id)
- }), 201
- @game.route("/<game_id>/current")
- def current_round(game_id):
- g = require_game(game_id)
- player = require_player(game_id)
- cur_rnd = player.get_current_round()
- if cur_rnd is None:
- coord = None
- else:
- lookup = db.Coordinate.query.get((game_id, cur_rnd))
- cur_rnd = str(cur_rnd)
- if lookup is None:
- coord = None
- else:
- coord = {
- "lat": lookup.latitude,
- "lng": lookup.longitude,
- }
- if g.rule_set == "TIMEBANK":
- timer = player.get_last_round_time_remaining()
- if timer is None:
- timer = g.timer * g.rounds
- else:
- timer = g.timer
- return jsonify({
- "currentRound": cur_rnd,
- "coord": coord,
- "timer": int(timer),
- })
- @game.route("/<game_id>/guesses/<int:round_num>", methods=["POST"])
- def make_guess(game_id, round_num):
- g = require_game(game_id)
- player = require_player(game_id)
- if round_num != player.get_current_round():
- abort(409)
- js = request.get_json()
- if js is None:
- abort(400)
- timed_out = js.get("timeout", False)
- if timed_out:
- player.add_timeout(round_num)
- if g.rule_set == "TIMEBANK":
- player.timeout_remaining_rounds()
- db.session.commit()
- return jsonify({
- "score": 0,
- "totalScore": player.get_total_score(),
- "distance": None,
- }), 201
- try:
- lat = float(js.get("lat", None))
- lng = float(js.get("lng", None))
- remaining = int(js.get("timeRemaining", None))
- except ValueError:
- abort(400)
- target = db.Coordinate.query.get((game_id, round_num))
- if target is None:
- abort(400)
- guess_score, distance = lib.score((target.latitude, target.longitude), (lat, lng))
- player.add_guess(round_num, lat, lng, guess_score, remaining)
- if remaining <= 0 and g.rule_set == "TIMEBANK":
- player.timeout_remaining_rounds()
- return jsonify({
- "score": guess_score,
- "totalScore": player.get_total_score(),
- "distance": distance,
- }), 201
|