game_api.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from flask import Blueprint, abort, request, jsonify
  2. import db
  3. import lib
  4. game = Blueprint("game", __name__)
  5. def require_name():
  6. name = request.headers.get("Authorization", type=str)
  7. if name is None:
  8. abort(401)
  9. return name.split(maxsplit=1)[-1]
  10. def require_game(game_id):
  11. g = db.Game.query.get(game_id)
  12. if g is None:
  13. abort(404)
  14. return g
  15. def require_player(game_id):
  16. name = require_name()
  17. player = db.Player.query.filter(db.Player.game_id == game_id, db.Player.player_name == name).first()
  18. if player is None:
  19. abort(404)
  20. return player
  21. @game.route("", methods=["PUT"])
  22. def create_game():
  23. name = require_name()
  24. timer = request.json.get("timer", None)
  25. if not isinstance(timer, int) or timer <= 0:
  26. abort(400)
  27. new_game = db.Game.create(timer, name)
  28. return jsonify({"gameId": new_game.game_id})
  29. @game.route("/<game_id>")
  30. def game_settings(game_id):
  31. g = require_game(game_id)
  32. return jsonify(g.to_dict())
  33. @game.route("/<game_id>/join", methods=["POST"])
  34. def join(game_id):
  35. name = require_name()
  36. g = require_game(game_id)
  37. if db.Player.query.filter(db.Player.game_id == game_id, db.Player.player_name == name).first() is not None:
  38. abort(409)
  39. g.join(name)
  40. return "", 201
  41. @game.route("/<game_id>/current")
  42. def current_round(game_id):
  43. g = require_game(game_id)
  44. player = require_player(game_id)
  45. cur_rnd = player.get_current_round()
  46. if cur_rnd is None:
  47. coord = None
  48. else:
  49. lookup = db.Coordinate.query.get((game_id, cur_rnd))
  50. if lookup is None:
  51. coord = None
  52. else:
  53. coord = {
  54. "lat": lookup.latitude,
  55. "lng": lookup.longitude,
  56. }
  57. return jsonify({
  58. "currentRound": cur_rnd,
  59. "coord": coord,
  60. "timer": g.timer,
  61. })
  62. @game.route("/<game_id>/guesses/<int:round_num>", methods=["POST"])
  63. def make_guess(game_id, round_num):
  64. player = require_player(game_id)
  65. if round_num != player.get_current_round():
  66. abort(409)
  67. timed_out = request.json.get("timeout", False)
  68. if timed_out:
  69. player.add_timeout(round_num)
  70. db.session.commit()
  71. return jsonify({
  72. "score": 0,
  73. "totalScore": player.get_total_score(),
  74. "distance": None,
  75. }), 201
  76. try:
  77. lat = float(request.json.get("lat", None))
  78. lng = float(request.json.get("lng", None))
  79. except ValueError:
  80. abort(400)
  81. target = db.Coordinate.query.get((game_id, round_num))
  82. if target is None:
  83. abort(400)
  84. guess_score, distance = lib.score((target.latitude, target.longitude), (lat, lng))
  85. player.add_guess(round_num, lat, lng, guess_score)
  86. return jsonify({
  87. "score": guess_score,
  88. "totalScore": player.get_total_score(),
  89. "distance": distance,
  90. }), 201