db.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. creator = db.Column(db.String)
  10. coord_id = db.Column(db.Integer, db.ForeignKey("coord_set.coord_id"))
  11. coord_set = db.relationship("CoordSet")
  12. guess_sets = db.relationship("GuessSet", backref="game", lazy=True)
  13. @staticmethod
  14. def create(timer, creator):
  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. cs = CoordSet()
  20. for round_num in "12345":
  21. coord = generate_coord()
  22. cs.set_coord(round_num, *coord)
  23. db.session.add(cs)
  24. db.session.commit()
  25. new_game = Game(
  26. game_id=game_id,
  27. timer=timer,
  28. creator=creator,
  29. coord_set=cs
  30. )
  31. db.session.add(new_game)
  32. db.session.commit()
  33. gs = GuessSet(
  34. game_id=game_id,
  35. player_name=creator,
  36. coord_set=CoordSet()
  37. )
  38. db.session.add(gs)
  39. db.session.commit()
  40. return new_game
  41. def __str__(self):
  42. return f"Game({self.game_id}, {self.timer})"
  43. def to_dict(self):
  44. return {
  45. "gameId": self.game_id,
  46. "timer": self.timer,
  47. "creator": self.creator,
  48. "coords": self.coord_set.to_dict(),
  49. "players": [
  50. {
  51. "name": gs.player_name,
  52. "currentRound": gs.get_current_round(),
  53. "totalScore": gs.get_total_score(),
  54. "guesses": gs.to_dict(),
  55. } for gs in self.guess_sets
  56. ],
  57. }
  58. class CoordSet(db.Model):
  59. coord_id = db.Column(db.Integer, primary_key=True)
  60. coord_1 = db.Column(db.String)
  61. coord_2 = db.Column(db.String)
  62. coord_3 = db.Column(db.String)
  63. coord_4 = db.Column(db.String)
  64. coord_5 = db.Column(db.String)
  65. def to_dict(self):
  66. to_return = {}
  67. for r, c in zip("12345", (self.coord_1, self.coord_2, self.coord_3, self.coord_4, self.coord_5)):
  68. if c is None:
  69. continue
  70. lat, lng = c.split(",")
  71. to_return[r] = {
  72. "lat": float(lat),
  73. "lng": float(lng)
  74. }
  75. return to_return
  76. def get_coord(self, round_num):
  77. # TODO this logic is a little gross
  78. if round_num == "1":
  79. c = self.coord_1
  80. elif round_num == "2":
  81. c = self.coord_2
  82. elif round_num == "3":
  83. c = self.coord_3
  84. elif round_num == "4":
  85. c = self.coord_4
  86. elif round_num == "5":
  87. c = self.coord_5
  88. else:
  89. raise ValueError(f"Invalid round number {round_num}")
  90. if c is not None:
  91. return tuple(float(x) for x in c.split(","))
  92. # returns None if the selected coord was None
  93. def set_coord(self, round_num, lat, lng):
  94. # TODO this logic is a little gross
  95. if round_num == "1":
  96. self.coord_1 = f"{lat},{lng}"
  97. elif round_num == "2":
  98. self.coord_2 = f"{lat},{lng}"
  99. elif round_num == "3":
  100. self.coord_3 = f"{lat},{lng}"
  101. elif round_num == "4":
  102. self.coord_4 = f"{lat},{lng}"
  103. elif round_num == "5":
  104. self.coord_5 = f"{lat},{lng}"
  105. else:
  106. raise ValueError(f"Invalid round number {round_num}")
  107. class GuessSet(db.Model):
  108. game_id = db.Column(db.String, db.ForeignKey(
  109. "game.game_id"), primary_key=True)
  110. player_name = db.Column(db.String, primary_key=True)
  111. coord_id = db.Column(db.Integer, db.ForeignKey("coord_set.coord_id"))
  112. coord_set = db.relationship("CoordSet")
  113. score_1 = db.Column(db.Integer)
  114. score_2 = db.Column(db.Integer)
  115. score_3 = db.Column(db.Integer)
  116. score_4 = db.Column(db.Integer)
  117. score_5 = db.Column(db.Integer)
  118. def to_dict(self):
  119. c = self.coord_set.to_dict()
  120. for r, s in zip("12345", (self.score_1, self.score_2, self.score_3, self.score_4, self.score_5)):
  121. if r in c:
  122. c[r]["score"] = s
  123. else:
  124. c[r] = None
  125. return c
  126. def get_current_round(self):
  127. for r, s in zip("12345", (self.score_1, self.score_2, self.score_3, self.score_4, self.score_5)):
  128. if s is None:
  129. return r
  130. # returns None if all rounds completed
  131. def get_total_score(self):
  132. return ((self.score_1 or 0) +
  133. (self.score_2 or 0) +
  134. (self.score_3 or 0) +
  135. (self.score_4 or 0) +
  136. (self.score_5 or 0))
  137. def set_timed_out(self, round_num):
  138. self.set_guess(round_num, -200, -200, 0)
  139. def set_guess(self, round_num, lat, lng, score):
  140. self.coord_set.set_coord(round_num, lat, lng)
  141. # TODO this logic is a little gross
  142. if round_num == "1":
  143. self.score_1 = score
  144. elif round_num == "2":
  145. self.score_2 = score
  146. elif round_num == "3":
  147. self.score_3 = score
  148. elif round_num == "4":
  149. self.score_4 = score
  150. elif round_num == "5":
  151. self.score_5 = score
  152. else:
  153. raise ValueError(f"Invalid round number {round_num}")