db.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import uuid
  2. from flask_sqlalchemy import SQLAlchemy
  3. from lib import generate_coord
  4. db = SQLAlchemy()
  5. session = db.session
  6. class Game(db.Model):
  7. game_id = db.Column(db.String, primary_key=True)
  8. timer = db.Column(db.Integer)
  9. rounds = db.Column(db.Integer)
  10. linked_game = db.Column(db.String)
  11. coordinates = db.relationship("Coordinate", lazy=True, order_by="Coordinate.round_number")
  12. players = db.relationship("Player", lazy=True, backref="game")
  13. @staticmethod
  14. def create(timer, rounds, only_america=False):
  15. game_id = str(uuid.uuid4())
  16. while Game.query.get(game_id) is not None:
  17. # basically impossible collision, but let's be safe
  18. game_id = str(uuid.uuid4())
  19. new_game = Game(
  20. game_id=game_id,
  21. timer=timer,
  22. rounds=rounds
  23. )
  24. db.session.add(new_game)
  25. for round_num in range(rounds):
  26. maybe_coord = generate_coord(only_america=only_america)
  27. while maybe_coord is None:
  28. maybe_coord = generate_coord(only_america=only_america)
  29. (lat, lng) = maybe_coord
  30. coord = Coordinate(
  31. game_id=game_id,
  32. round_number=round_num+1,
  33. latitude=lat,
  34. longitude=lng
  35. )
  36. db.session.add(coord)
  37. db.session.commit()
  38. return new_game
  39. def join(self, player_name):
  40. p = Player(
  41. game_id=self.game_id,
  42. player_name=player_name
  43. )
  44. db.session.add(p)
  45. db.session.commit()
  46. return p
  47. def link(self, linked_game):
  48. self.linked_game = linked_game
  49. db.session.commit()
  50. def to_dict(self):
  51. return {
  52. "gameId": self.game_id,
  53. "timer": self.timer,
  54. "rounds": self.rounds,
  55. "coords": {
  56. str(c.round_number): {
  57. "lat": c.latitude,
  58. "lng": c.longitude,
  59. } for c in self.coordinates
  60. },
  61. "players": [p.to_dict() for p in self.players],
  62. "linkedGame": self.linked_game,
  63. }
  64. class Player(db.Model):
  65. player_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  66. game_id = db.Column(db.String, db.ForeignKey("game.game_id"))
  67. player_name = db.Column(db.String)
  68. guesses = db.relationship("Guess", lazy=True, order_by="Guess.round_number")
  69. def get_total_score(self):
  70. return sum(g.round_score or 0 for g in self.guesses)
  71. def get_current_round(self):
  72. if len(self.guesses) == 0:
  73. return 1
  74. next_round = self.guesses[-1].round_number + 1
  75. if next_round <= self.game.rounds:
  76. return next_round
  77. return None
  78. def add_guess(self, round_num, lat, lng, score):
  79. g = Guess(
  80. player_id=self.player_id,
  81. round_number=round_num,
  82. latitude=lat,
  83. longitude=lng,
  84. round_score=score,
  85. )
  86. db.session.add(g)
  87. db.session.commit()
  88. def add_timeout(self, round_num):
  89. self.add_guess(round_num, -200, -200, None)
  90. def to_dict(self):
  91. return {
  92. "name": self.player_name,
  93. "currentRound": self.get_current_round(),
  94. "totalScore": self.get_total_score(),
  95. "guesses": {
  96. str(g.round_number): {
  97. "lat": g.latitude,
  98. "lng": g.longitude,
  99. "score": g.round_score,
  100. } for g in self.guesses
  101. },
  102. }
  103. class Coordinate(db.Model):
  104. game_id = db.Column(db.String, db.ForeignKey("game.game_id"), primary_key=True)
  105. round_number = db.Column(db.Integer, primary_key=True, autoincrement=False)
  106. latitude = db.Column(db.Float)
  107. longitude = db.Column(db.Float)
  108. class Guess(db.Model):
  109. player_id = db.Column(db.String, db.ForeignKey("player.player_id"), primary_key=True)
  110. round_number = db.Column(db.Integer, primary_key=True, autoincrement=False)
  111. latitude = db.Column(db.Float)
  112. longitude = db.Column(db.Float)
  113. round_score = db.Column(db.Integer)