queries.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import uuid
  2. from typing import List, Tuple
  3. from sqlalchemy.orm import Session
  4. from .models import Game, Coordinate, Player, Guess
  5. from .. import schemas
  6. def create_game(db: Session, conf: schemas.GameConfig, coords: List[Tuple[float, float]]) -> str:
  7. if len(coords) != conf.rounds:
  8. raise ValueError("Insufficient number of coordinates")
  9. game_id = str(uuid.uuid4())
  10. while db.query(Game).get(game_id) is not None:
  11. # basically impossible collision, but let's be safe
  12. game_id = str(uuid.uuid4())
  13. new_game = Game(
  14. game_id=game_id,
  15. timer=conf.timer,
  16. rounds=conf.rounds,
  17. only_america=conf.only_america,
  18. generation_method=conf.generation_method,
  19. rule_set=conf.rule_set,
  20. )
  21. db.add(new_game)
  22. db.add_all([Coordinate(
  23. game_id=game_id,
  24. round_number=round_num + 1,
  25. latitude=lat,
  26. longitude=lng,
  27. ) for (round_num, (lat, lng)) in enumerate(coords)])
  28. db.commit()
  29. return game_id
  30. def get_game(db: Session, game_id: str) -> Game:
  31. return db.query(Game).get(game_id)
  32. def join_game(db: Session, game_id: str, player_name: str) -> str:
  33. existing = db.query(Player).filter(Player.game_id == game_id, Player.player_name == player_name).first()
  34. if existing is not None:
  35. return None
  36. new_player = Player(game_id=game_id, player_name=player_name)
  37. db.add(new_player)
  38. db.commit()
  39. return str(new_player.player_id)
  40. def link_game(db: Session, game_id: str, linked_game: str):
  41. db.query(Game).get(game_id).linked_game = linked_game
  42. db.commit()
  43. def get_player(db: Session, player_id: str) -> Player:
  44. return db.query(Player).get(int(player_id))
  45. def get_total_score(player: Player) -> int:
  46. return sum(g.round_score or 0 for g in player.guesses)
  47. def get_next_round_number(player: Player) -> int:
  48. if len(player.guesses) == 0:
  49. return 1
  50. next_round = player.guesses[-1].round_number + 1
  51. if next_round <= player.game.rounds:
  52. return next_round
  53. return None
  54. def get_coordinate(db: Session, game_id: str, round_number: int) -> Coordinate:
  55. return db.query(Coordinate).get((game_id, round_number))
  56. def get_next_coordinate(db: Session, player: Player) -> Coordinate:
  57. round_number = get_next_round_number(player)
  58. if round_number is None:
  59. return None
  60. return get_coordinate(db, player.game_id, round_number)
  61. def get_next_round_time(player: Player) -> int:
  62. if player.game.rule_set == schemas.RuleSetEnum.time_bank:
  63. if len(player.guesses) == 0:
  64. return player.game.timer * player.game.rounds
  65. return player.guesses[-1].time_remaining
  66. return player.game.timer
  67. def add_guess(db: Session, guess: schemas.Guess, player: Player, round_number: int, score: int) -> bool:
  68. existing = db.query(Guess).filter(Guess.player_id == player.player_id, Guess.round_number == round_number).first()
  69. if existing is not None:
  70. return False
  71. g = Guess(
  72. player_id=player.player_id,
  73. round_number=round_number,
  74. latitude=guess.lat,
  75. longitude=guess.lng,
  76. round_score=score,
  77. time_remaining=guess.time_remaining,
  78. )
  79. db.add(g)
  80. db.commit()
  81. if guess.time_remaining <= 0 and player.game.rule_set == schemas.RuleSetEnum.time_bank:
  82. for r in range(round_number, player.game.rounds):
  83. add_timeout(db, player, r + 1)
  84. return True
  85. def add_timeout(db: Session, player: Player, round_number: int) -> bool:
  86. return add_guess(db, schemas.Guess(lat=0, lng=0, time_remaining=0), player, round_number, None)
  87. def get_first_submitter(db: Session, game_id: str, round_number: int) -> str:
  88. first = db.query(Player.player_name, Guess).filter(
  89. Player.game_id == game_id,
  90. Guess.round_number == round_number,
  91. Player.player_id == Guess.player_id,
  92. ).order_by(Guess.created_at.desc()).first()
  93. if first is None:
  94. return None
  95. return first[0]