queries.py 4.0 KB

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