game_api.py 3.3 KB

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