queries.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import uuid
  2. from typing import List, Tuple
  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. rule_set=conf.rule_set,
  21. created_at=datetime.now(),
  22. )
  23. db.add(new_game)
  24. db.add_all([Coordinate(
  25. game_id=game_id,
  26. round_number=round_num + 1,
  27. country_code=cc,
  28. latitude=lat,
  29. longitude=lng,
  30. ) for (round_num, (cc, lat, lng)) in enumerate(coords)])
  31. db.commit()
  32. return game_id
  33. def get_recent_games(db: Session, count: int) -> List[Game]:
  34. return db.query(Game).order_by(Game.created_at).limit(count).all()
  35. def get_game(db: Session, game_id: str) -> Game:
  36. return db.query(Game).get(game_id)
  37. def join_game(db: Session, game_id: str, player_name: str) -> str:
  38. existing = db.query(Player).filter(Player.game_id == game_id, Player.player_name == player_name).first()
  39. if existing is not None:
  40. return None
  41. new_player = Player(game_id=game_id, player_name=player_name)
  42. db.add(new_player)
  43. db.commit()
  44. return str(new_player.player_id)
  45. def link_game(db: Session, game_id: str, linked_game: str):
  46. db.query(Game).get(game_id).linked_game = linked_game
  47. db.commit()
  48. def get_player(db: Session, player_id: str) -> Player:
  49. return db.query(Player).get(int(player_id))
  50. def get_total_score(player: Player) -> int:
  51. return sum(g.round_score or 0 for g in player.guesses)
  52. def get_next_round_number(player: Player) -> int:
  53. if len(player.guesses) == 0:
  54. return 1
  55. next_round = player.guesses[-1].round_number + 1
  56. if next_round <= player.game.rounds:
  57. return next_round
  58. return None
  59. def get_coordinate(db: Session, game_id: str, round_number: int) -> Coordinate:
  60. return db.query(Coordinate).get((game_id, round_number))
  61. def get_next_coordinate(db: Session, player: Player) -> Coordinate:
  62. round_number = get_next_round_number(player)
  63. if round_number is None:
  64. return None
  65. return get_coordinate(db, player.game_id, round_number)
  66. def get_next_round_time(player: Player) -> int:
  67. if player.game.rule_set == schemas.RuleSetEnum.time_bank:
  68. if len(player.guesses) == 0:
  69. return player.game.timer * player.game.rounds
  70. return player.guesses[-1].time_remaining
  71. return player.game.timer
  72. def add_guess(db: Session, guess: schemas.Guess, player: Player, round_number: int, score: int) -> bool:
  73. existing = db.query(Guess).filter(Guess.player_id == player.player_id, Guess.round_number == round_number).first()
  74. if existing is not None:
  75. return False
  76. g = Guess(
  77. player_id=player.player_id,
  78. round_number=round_number,
  79. latitude=guess.lat,
  80. longitude=guess.lng,
  81. country_code=guess.country,
  82. round_score=score,
  83. time_remaining=guess.time_remaining,
  84. )
  85. db.add(g)
  86. db.commit()
  87. if guess.time_remaining <= 0 and player.game.rule_set == schemas.RuleSetEnum.time_bank:
  88. for r in range(round_number, player.game.rounds):
  89. add_timeout(db, player, r + 1)
  90. return True
  91. def add_timeout(db: Session, player: Player, round_number: int) -> bool:
  92. return add_guess(db, schemas.Guess(lat=0, lng=0, time_remaining=0), player, round_number, None)
  93. def get_first_submitter(db: Session, game_id: str, round_number: int) -> str:
  94. first = db.query(Player.player_name, Guess).filter(
  95. Player.game_id == game_id,
  96. Guess.round_number == round_number,
  97. Player.player_id == Guess.player_id,
  98. ).order_by(Guess.created_at.desc()).first()
  99. if first is None:
  100. return None
  101. return first[0]