|
@@ -11,169 +11,117 @@ session = db.session
|
|
|
class Game(db.Model):
|
|
|
game_id = db.Column(db.String, primary_key=True)
|
|
|
timer = db.Column(db.Integer)
|
|
|
- creator = db.Column(db.String)
|
|
|
- coord_id = db.Column(db.Integer, db.ForeignKey("coord_set.coord_id"))
|
|
|
- coord_set = db.relationship("CoordSet")
|
|
|
- guess_sets = db.relationship("GuessSet", backref="game", lazy=True)
|
|
|
+ rounds = db.Column(db.Integer)
|
|
|
+ coordinates = db.relationship("Coordinate", lazy=True, order_by="Coordinate.round_number")
|
|
|
+ players = db.relationship("Player", lazy=True)
|
|
|
|
|
|
@staticmethod
|
|
|
- def create(timer, creator):
|
|
|
+ def create(timer, creator, rounds=5):
|
|
|
game_id = str(uuid.uuid4())
|
|
|
while Game.query.get(game_id) is not None:
|
|
|
# basically impossible collision, but let's be safe
|
|
|
game_id = str(uuid.uuid4())
|
|
|
|
|
|
- cs = CoordSet()
|
|
|
- for round_num in "12345":
|
|
|
- coord = generate_coord()
|
|
|
- cs.set_coord(round_num, *coord)
|
|
|
- db.session.add(cs)
|
|
|
- db.session.commit()
|
|
|
-
|
|
|
new_game = Game(
|
|
|
game_id=game_id,
|
|
|
timer=timer,
|
|
|
- creator=creator,
|
|
|
- coord_set=cs
|
|
|
+ rounds=rounds
|
|
|
)
|
|
|
db.session.add(new_game)
|
|
|
- db.session.commit()
|
|
|
|
|
|
- gs = GuessSet(
|
|
|
- game_id=game_id,
|
|
|
- player_name=creator,
|
|
|
- coord_set=CoordSet()
|
|
|
- )
|
|
|
- db.session.add(gs)
|
|
|
- db.session.commit()
|
|
|
+ for round_num in range(rounds):
|
|
|
+ (lat, lng) = generate_coord()
|
|
|
+ coord = Coordinate(
|
|
|
+ game_id=game_id,
|
|
|
+ round_number=round_num+1,
|
|
|
+ latitude=lat,
|
|
|
+ longitude=lng
|
|
|
+ )
|
|
|
+ db.session.add(coord)
|
|
|
|
|
|
- return new_game
|
|
|
+ new_game.join(creator) # commits the session
|
|
|
|
|
|
+ return new_game
|
|
|
|
|
|
- def __str__(self):
|
|
|
- return f"Game({self.game_id}, {self.timer})"
|
|
|
+ def join(self, player_name):
|
|
|
+ p = Player(
|
|
|
+ game_id=self.game_id,
|
|
|
+ player_name=player_name
|
|
|
+ )
|
|
|
+ db.session.add(p)
|
|
|
+ db.session.commit()
|
|
|
|
|
|
def to_dict(self):
|
|
|
return {
|
|
|
"gameId": self.game_id,
|
|
|
"timer": self.timer,
|
|
|
- "creator": self.creator,
|
|
|
- "coords": self.coord_set.to_dict(),
|
|
|
- "players": [
|
|
|
- {
|
|
|
- "name": gs.player_name,
|
|
|
- "currentRound": gs.get_current_round(),
|
|
|
- "totalScore": gs.get_total_score(),
|
|
|
- "guesses": gs.to_dict(),
|
|
|
- } for gs in self.guess_sets
|
|
|
- ],
|
|
|
+ "rounds": self.rounds,
|
|
|
+ "coords": [{
|
|
|
+ str(c.round_number): {
|
|
|
+ "lat": c.latitude,
|
|
|
+ "lng": c.longitude,
|
|
|
+ }
|
|
|
+ } for c in self.coordinates],
|
|
|
+ "players": [p.to_dict() for p in self.players],
|
|
|
}
|
|
|
|
|
|
|
|
|
-class CoordSet(db.Model):
|
|
|
- coord_id = db.Column(db.Integer, primary_key=True)
|
|
|
- coord_1 = db.Column(db.String)
|
|
|
- coord_2 = db.Column(db.String)
|
|
|
- coord_3 = db.Column(db.String)
|
|
|
- coord_4 = db.Column(db.String)
|
|
|
- coord_5 = db.Column(db.String)
|
|
|
+class Player(db.Model):
|
|
|
+ player_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
|
|
+ game_id = db.Column(db.String, db.ForeignKey("game.game_id"))
|
|
|
+ player_name = db.Column(db.String)
|
|
|
+ guesses = db.relationship("Guess", lazy=True, order_by="Guess.round_number")
|
|
|
|
|
|
- def to_dict(self):
|
|
|
- to_return = {}
|
|
|
- for r, c in zip("12345", (self.coord_1, self.coord_2, self.coord_3, self.coord_4, self.coord_5)):
|
|
|
- if c is None:
|
|
|
- continue
|
|
|
- lat, lng = c.split(",")
|
|
|
- to_return[r] = {
|
|
|
- "lat": float(lat),
|
|
|
- "lng": float(lng)
|
|
|
- }
|
|
|
- return to_return
|
|
|
-
|
|
|
- def get_coord(self, round_num):
|
|
|
- # TODO this logic is a little gross
|
|
|
- if round_num == "1":
|
|
|
- c = self.coord_1
|
|
|
- elif round_num == "2":
|
|
|
- c = self.coord_2
|
|
|
- elif round_num == "3":
|
|
|
- c = self.coord_3
|
|
|
- elif round_num == "4":
|
|
|
- c = self.coord_4
|
|
|
- elif round_num == "5":
|
|
|
- c = self.coord_5
|
|
|
- else:
|
|
|
- raise ValueError(f"Invalid round number {round_num}")
|
|
|
-
|
|
|
- if c is not None:
|
|
|
- return tuple(float(x) for x in c.split(","))
|
|
|
- # returns None if the selected coord was None
|
|
|
-
|
|
|
- def set_coord(self, round_num, lat, lng):
|
|
|
- # TODO this logic is a little gross
|
|
|
- if round_num == "1":
|
|
|
- self.coord_1 = f"{lat},{lng}"
|
|
|
- elif round_num == "2":
|
|
|
- self.coord_2 = f"{lat},{lng}"
|
|
|
- elif round_num == "3":
|
|
|
- self.coord_3 = f"{lat},{lng}"
|
|
|
- elif round_num == "4":
|
|
|
- self.coord_4 = f"{lat},{lng}"
|
|
|
- elif round_num == "5":
|
|
|
- self.coord_5 = f"{lat},{lng}"
|
|
|
- else:
|
|
|
- raise ValueError(f"Invalid round number {round_num}")
|
|
|
-
|
|
|
-
|
|
|
-class GuessSet(db.Model):
|
|
|
- game_id = db.Column(db.String, db.ForeignKey(
|
|
|
- "game.game_id"), primary_key=True)
|
|
|
- player_name = db.Column(db.String, primary_key=True)
|
|
|
- coord_id = db.Column(db.Integer, db.ForeignKey("coord_set.coord_id"))
|
|
|
- coord_set = db.relationship("CoordSet")
|
|
|
- score_1 = db.Column(db.Integer)
|
|
|
- score_2 = db.Column(db.Integer)
|
|
|
- score_3 = db.Column(db.Integer)
|
|
|
- score_4 = db.Column(db.Integer)
|
|
|
- score_5 = db.Column(db.Integer)
|
|
|
+ def get_total_score(self):
|
|
|
+ return sum(g.round_score for g in self.guesses)
|
|
|
+
|
|
|
+ def get_current_round(self):
|
|
|
+ if len(self.guesses) == 0:
|
|
|
+ return 1
|
|
|
+ next_round = self.guesses[-1].round_number + 1
|
|
|
+ if next_round <= Game.query.get(self.game_id).rounds:
|
|
|
+ return next_round
|
|
|
+ return None
|
|
|
+
|
|
|
+ def add_guess(self, round_num, lat, lng, score):
|
|
|
+ g = Guess(
|
|
|
+ player_id=self.player_id,
|
|
|
+ round_number=round_num,
|
|
|
+ latitude=lat,
|
|
|
+ longitude=lng,
|
|
|
+ round_score=score,
|
|
|
+ )
|
|
|
+ db.session.add(g)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ def add_timeout(self, round_num):
|
|
|
+ self.add_guess(round_num, -200, -200, 0)
|
|
|
|
|
|
def to_dict(self):
|
|
|
- c = self.coord_set.to_dict()
|
|
|
- for r, s in zip("12345", (self.score_1, self.score_2, self.score_3, self.score_4, self.score_5)):
|
|
|
- if r in c:
|
|
|
- c[r]["score"] = s
|
|
|
- else:
|
|
|
- c[r] = None
|
|
|
- return c
|
|
|
+ return {
|
|
|
+ "name": self.player_name,
|
|
|
+ "currentRound": self.get_current_round(),
|
|
|
+ "totalScore": self.get_total_score(),
|
|
|
+ "guesses": [{
|
|
|
+ str(g.round_number): {
|
|
|
+ "lat": g.latitude,
|
|
|
+ "lng": g.longitude,
|
|
|
+ "score": g.round_score,
|
|
|
+ }
|
|
|
+ } for g in self.guesses],
|
|
|
+ }
|
|
|
|
|
|
- def get_current_round(self):
|
|
|
- for r, s in zip("12345", (self.score_1, self.score_2, self.score_3, self.score_4, self.score_5)):
|
|
|
- if s is None:
|
|
|
- return r
|
|
|
- # returns None if all rounds completed
|
|
|
|
|
|
- def get_total_score(self):
|
|
|
- return ((self.score_1 or 0) +
|
|
|
- (self.score_2 or 0) +
|
|
|
- (self.score_3 or 0) +
|
|
|
- (self.score_4 or 0) +
|
|
|
- (self.score_5 or 0))
|
|
|
-
|
|
|
- def set_timed_out(self, round_num):
|
|
|
- self.set_guess(round_num, -200, -200, 0)
|
|
|
-
|
|
|
- def set_guess(self, round_num, lat, lng, score):
|
|
|
- self.coord_set.set_coord(round_num, lat, lng)
|
|
|
- # TODO this logic is a little gross
|
|
|
- if round_num == "1":
|
|
|
- self.score_1 = score
|
|
|
- elif round_num == "2":
|
|
|
- self.score_2 = score
|
|
|
- elif round_num == "3":
|
|
|
- self.score_3 = score
|
|
|
- elif round_num == "4":
|
|
|
- self.score_4 = score
|
|
|
- elif round_num == "5":
|
|
|
- self.score_5 = score
|
|
|
- else:
|
|
|
- raise ValueError(f"Invalid round number {round_num}")
|
|
|
+class Coordinate(db.Model):
|
|
|
+ game_id = db.Column(db.String, db.ForeignKey("game.game_id"), primary_key=True)
|
|
|
+ round_number = db.Column(db.Integer, primary_key=True, autoincrement=False)
|
|
|
+ latitude = db.Column(db.Float)
|
|
|
+ longitude = db.Column(db.Float)
|
|
|
+
|
|
|
+
|
|
|
+class Guess(db.Model):
|
|
|
+ player_id = db.Column(db.String, db.ForeignKey("player.player_id"), primary_key=True)
|
|
|
+ round_number = db.Column(db.Integer, primary_key=True, autoincrement=False)
|
|
|
+ latitude = db.Column(db.Float)
|
|
|
+ longitude = db.Column(db.Float)
|
|
|
+ round_score = db.Column(db.Integer)
|