queries.py 4.4 KB

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