db.py 5.2 KB

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