game_api.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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_guess_set(game_id):
  16. name = require_name()
  17. gs = db.GuessSet.query.get((game_id, name))
  18. if gs is None:
  19. abort(404)
  20. return gs
  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.GuessSet.query.get((g.game_id, name)) is not None:
  38. abort(409)
  39. cs = db.CoordSet()
  40. db.session.add(cs)
  41. db.session.commit()
  42. gs = db.GuessSet(game_id=g.game_id, player_name=name, coord_set=cs)
  43. db.session.add(gs)
  44. db.session.commit()
  45. return "", 201
  46. @game.route("/<game_id>/current")
  47. def current_round(game_id):
  48. g = require_game(game_id)
  49. gs = require_guess_set(game_id)
  50. cur_rnd = gs.get_current_round()
  51. if cur_rnd is None:
  52. coord = None
  53. else:
  54. (lat, lng) = g.coord_set.get_coord(cur_rnd)
  55. coord = {
  56. "lat": float(lat),
  57. "lng": float(lng),
  58. }
  59. return jsonify({
  60. "currentRound": cur_rnd,
  61. "coord": coord,
  62. "timer": g.timer,
  63. })
  64. @game.route("/<game_id>/guesses/<round_num>", methods=["POST"])
  65. def make_guess(game_id, round_num):
  66. gs = require_guess_set(game_id)
  67. if round_num != gs.get_current_round():
  68. abort(409)
  69. timed_out = request.json.get("timeout", False)
  70. if timed_out:
  71. gs.set_timed_out(round_num)
  72. db.session.commit()
  73. return jsonify({
  74. "score": 0,
  75. "totalScore": gs.get_total_score(),
  76. "distance": None,
  77. }), 201
  78. try:
  79. lat = float(request.json.get("lat", None))
  80. lng = float(request.json.get("lng", None))
  81. except ValueError:
  82. abort(400)
  83. target = require_game(game_id).coord_set.get_coord(round_num)
  84. guess_score, distance = lib.score(target, (lat, lng))
  85. gs.set_guess(round_num, lat, lng, guess_score)
  86. db.session.commit()
  87. return jsonify({
  88. "score": guess_score,
  89. "totalScore": gs.get_total_score(),
  90. "distance": distance,
  91. }), 201