"""Seed demo data for ServeSync""" import sys import os sys.path.insert(0, '/app') from sqlalchemy.orm import Session from app.database import engine, SessionLocal from app.models.player import Player, MembershipTier from app.models.court import Court from app.models.booking import Booking, BookingStatus from app.models.match import Match, MatchPlayer, MatchStage, MatchStatus, MatchType from app.models.tournament import Tournament, TournamentEntry, TournamentMatch, TournamentStatus, BracketType, TournamentMatchStatus from datetime import datetime, timedelta import random def clear_data(db: Session): db.query(TournamentMatch).delete() db.query(TournamentEntry).delete() db.query(Tournament).delete() db.query(MatchPlayer).delete() db.query(Match).delete() db.query(Booking).delete() db.query(Court).delete() db.query(Player).delete() db.commit() print("Cleared existing data") def seed_players(db: Session) -> list: players_data = [ {"name": "Marco Santos", "email": "marco@demo.com", "elo": 1850, "tier": MembershipTier.ELITE, "color": "#EF4444", "wins": 45, "losses": 8}, {"name": "Sofia Reyes", "email": "sofia@demo.com", "elo": 1720, "tier": MembershipTier.ELITE, "color": "#EC4899", "wins": 38, "losses": 12}, {"name": "Carlos Mendez", "email": "carlos@demo.com", "elo": 1630, "tier": MembershipTier.PLATINUM, "color": "#8B5CF6", "wins": 32, "losses": 15}, {"name": "Ana Cruz", "email": "ana@demo.com", "elo": 1580, "tier": MembershipTier.PLATINUM, "color": "#06B6D4", "wins": 28, "losses": 18}, {"name": "Juan Dela Cruz", "email": "juan@demo.com", "elo": 1450, "tier": MembershipTier.GOLD, "color": "#F59E0B", "wins": 22, "losses": 20}, {"name": "Maria Garcia", "email": "maria@demo.com", "elo": 1380, "tier": MembershipTier.GOLD, "color": "#10B981", "wins": 18, "losses": 22}, {"name": "Pedro Lopez", "email": "pedro@demo.com", "elo": 1250, "tier": MembershipTier.SILVER, "color": "#3B82F6", "wins": 14, "losses": 19}, {"name": "Rosa Martinez", "email": "rosa@demo.com", "elo": 1190, "tier": MembershipTier.SILVER, "color": "#F97316", "wins": 11, "losses": 21}, {"name": "Diego Torres", "email": "diego@demo.com", "elo": 1100, "tier": MembershipTier.SILVER, "color": "#84CC16", "wins": 9, "losses": 18}, {"name": "Lucia Flores", "email": "lucia@demo.com", "elo": 980, "tier": MembershipTier.BRONZE, "color": "#14B8A6", "wins": 6, "losses": 20}, {"name": "Miguel Ortega", "email": "miguel@demo.com", "elo": 920, "tier": MembershipTier.BRONZE, "color": "#6366F1", "wins": 4, "losses": 15}, {"name": "Isabella Vega", "email": "isabella@demo.com", "elo": 850, "tier": MembershipTier.BRONZE, "color": "#D946EF", "wins": 2, "losses": 12}, ] players = [] for pd in players_data: p = Player( name=pd["name"], email=pd["email"], elo_rating=pd["elo"], membership_tier=pd["tier"], avatar_color=pd["color"], wins=pd["wins"], losses=pd["losses"], total_matches=pd["wins"] + pd["losses"], ) db.add(p) players.append(p) db.commit() for p in players: db.refresh(p) print(f"Created {len(players)} players") return players def seed_courts(db: Session) -> list: courts_data = [ {"name": "Court 1", "number": 1, "rate": 200.0, "surface": "Sport Court", "features": "LED Lighting, Pro Net System"}, {"name": "Court 2", "number": 2, "rate": 200.0, "surface": "Sport Court", "features": "LED Lighting, Spectator Seating"}, {"name": "Court 3", "number": 3, "rate": 250.0, "surface": "Cushioned", "features": "Tournament Grade, Scoreboards"}, {"name": "Court 4", "number": 4, "rate": 250.0, "surface": "Cushioned", "features": "Tournament Grade, VIP Lounge Access"}, ] courts = [] for cd in courts_data: c = Court( name=cd["name"], court_number=cd["number"], hourly_rate=cd["rate"], surface_type=cd["surface"], features=cd["features"], ) db.add(c) courts.append(c) db.commit() for c in courts: db.refresh(c) print(f"Created {len(courts)} courts") return courts def seed_bookings(db: Session, players: list, courts: list): now = datetime.utcnow() bookings = [] # Future bookings for i in range(8): player = players[i % len(players)] court = courts[i % len(courts)] start = now + timedelta(hours=i + 2) end = start + timedelta(hours=1) b = Booking( player_id=player.id, court_id=court.id, start_time=start, end_time=end, duration_hours=1.0, total_cost=court.hourly_rate, status=BookingStatus.CONFIRMED, ) db.add(b) bookings.append(b) db.commit() print(f"Created {len(bookings)} bookings") def seed_active_matches(db: Session, players: list, courts: list) -> list: matches = [] # Match 1: Active doubles on Court 1 (Open match) m1 = Match( court_id=courts[0].id, stage=MatchStage.OPEN, match_type=MatchType.DOUBLES, status=MatchStatus.IN_PROGRESS, title="Open Doubles - Court 1", max_players=4, team1_score=7, team2_score=5, started_at=datetime.utcnow() - timedelta(minutes=25), ) db.add(m1) db.flush() for player_id, team in [(players[0].id, 1), (players[1].id, 1), (players[2].id, 2), (players[3].id, 2)]: mp = MatchPlayer(match_id=m1.id, player_id=player_id, team=team, elo_before=db.query(Player).filter(Player.id == player_id).first().elo_rating) db.add(mp) matches.append(m1) # Match 2: Active skill-based on Court 2 m2 = Match( court_id=courts[1].id, stage=MatchStage.SKILL_BASED, match_type=MatchType.DOUBLES, status=MatchStatus.IN_PROGRESS, title="Skill Match - Platinum League", max_players=4, min_elo=1300, max_elo=1700, team1_score=3, team2_score=6, started_at=datetime.utcnow() - timedelta(minutes=15), ) db.add(m2) db.flush() for player_id, team in [(players[4].id, 1), (players[5].id, 1), (players[6].id, 2), (players[7].id, 2)]: mp = MatchPlayer(match_id=m2.id, player_id=player_id, team=team, elo_before=db.query(Player).filter(Player.id == player_id).first().elo_rating) db.add(mp) matches.append(m2) # Match 3: Lobby (waiting for players) m3 = Match( stage=MatchStage.OPEN, match_type=MatchType.DOUBLES, status=MatchStatus.LOBBY, title="Evening Open Game", max_players=4, ) db.add(m3) db.flush() for player_id, team in [(players[8].id, 1), (players[9].id, 2)]: mp = MatchPlayer(match_id=m3.id, player_id=player_id, team=team, elo_before=db.query(Player).filter(Player.id == player_id).first().elo_rating) db.add(mp) matches.append(m3) # Match 4: Skill-based lobby m4 = Match( stage=MatchStage.SKILL_BASED, match_type=MatchType.DOUBLES, status=MatchStatus.LOBBY, title="Gold Tier Challenge", max_players=4, min_elo=1200, max_elo=1600, ) db.add(m4) db.flush() mp = MatchPlayer(match_id=m4.id, player_id=players[4].id, team=1, elo_before=players[4].elo_rating) db.add(mp) matches.append(m4) db.commit() for m in matches: db.refresh(m) print(f"Created {len(matches)} matches (2 active, 2 lobby)") return matches def seed_tournament(db: Session, players: list, courts: list): """Create a sample double elimination tournament in progress""" t = Tournament( name="ServeSync Grand Prix - March 2024", status=TournamentStatus.IN_PROGRESS, max_participants=8, current_round=2, started_at=datetime.utcnow() - timedelta(hours=2), ) db.add(t) db.flush() # Register 8 players tournament_players = players[:8] entries = [] for i, player in enumerate(tournament_players): entry = TournamentEntry( tournament_id=t.id, player_id=player.id, seed=i + 1, wins=0, losses=0, ) db.add(entry) entries.append(entry) db.flush() # Round 1 Winners Bracket (4 matches) - all completed r1_matches = [ (players[0].id, players[7].id, 11, 5), # 1 vs 8 (players[1].id, players[6].id, 11, 7), # 2 vs 7 (players[2].id, players[5].id, 8, 11), # 3 vs 6 - player 5 wins (players[3].id, players[4].id, 11, 9), # 4 vs 5 ] winners_r1 = [] # winner player IDs after round 1 losers_r1 = [] # loser player IDs after round 1 for i, (p1_id, p2_id, s1, s2) in enumerate(r1_matches): tm = TournamentMatch( tournament_id=t.id, round_number=1, match_number=i + 1, bracket_type=BracketType.WINNERS, status=TournamentMatchStatus.COMPLETED, player1_id=p1_id, player2_id=p2_id, team1_score=s1, team2_score=s2, winner_team=1 if s1 > s2 else 2, completed_at=datetime.utcnow() - timedelta(hours=1, minutes=30), ) db.add(tm) winner_id = p1_id if s1 > s2 else p2_id loser_id = p2_id if s1 > s2 else p1_id winners_r1.append(winner_id) losers_r1.append(loser_id) # Update entry stats for entry in entries: if entry.player_id == winner_id: entry.wins += 1 elif entry.player_id == loser_id: entry.losses += 1 entry.is_in_losers = True db.flush() # Round 2 Winners Bracket - 2 matches - 1 completed, 1 in progress # Match 1: players[0] vs players[1] wm1 = TournamentMatch( tournament_id=t.id, round_number=2, match_number=1, bracket_type=BracketType.WINNERS, status=TournamentMatchStatus.COMPLETED, player1_id=winners_r1[0], player2_id=winners_r1[1], team1_score=11, team2_score=8, winner_team=1, completed_at=datetime.utcnow() - timedelta(minutes=45), ) db.add(wm1) # Update entries for entry in entries: if entry.player_id == winners_r1[0]: entry.wins += 1 elif entry.player_id == winners_r1[1]: entry.losses += 1 entry.is_in_losers = True # Match 2: players[3] (seed4 winner) vs players[5] (seed6 winner) wm2 = TournamentMatch( tournament_id=t.id, round_number=2, match_number=2, bracket_type=BracketType.WINNERS, status=TournamentMatchStatus.IN_PROGRESS, player1_id=winners_r1[2], player2_id=winners_r1[3], team1_score=6, team2_score=7, ) db.add(wm2) # Assign court 3 for active tournament match m_active = Match( court_id=courts[2].id, stage=MatchStage.TOURNAMENT, match_type=MatchType.SINGLES, status=MatchStatus.IN_PROGRESS, title=f"Tournament R2 - {db.query(Player).filter(Player.id == winners_r1[2]).first().name} vs {db.query(Player).filter(Player.id == winners_r1[3]).first().name}", max_players=2, team1_score=6, team2_score=7, started_at=datetime.utcnow() - timedelta(minutes=20), ) db.add(m_active) db.flush() for player_id, team in [(winners_r1[2], 1), (winners_r1[3], 2)]: mp = MatchPlayer(match_id=m_active.id, player_id=player_id, team=team, elo_before=db.query(Player).filter(Player.id == player_id).first().elo_rating) db.add(mp) # Losers Bracket Round 1 - 2 matches (losers from r1 matched up) lb1 = TournamentMatch( tournament_id=t.id, round_number=1, match_number=1, bracket_type=BracketType.LOSERS, status=TournamentMatchStatus.COMPLETED, player1_id=losers_r1[0], player2_id=losers_r1[1], team1_score=9, team2_score=11, winner_team=2, completed_at=datetime.utcnow() - timedelta(minutes=90), ) db.add(lb1) lb2 = TournamentMatch( tournament_id=t.id, round_number=1, match_number=2, bracket_type=BracketType.LOSERS, status=TournamentMatchStatus.COMPLETED, player1_id=losers_r1[2], player2_id=losers_r1[3], team1_score=11, team2_score=6, winner_team=1, completed_at=datetime.utcnow() - timedelta(minutes=60), ) db.add(lb2) # Update loser entries for entry in entries: if entry.player_id == losers_r1[0]: entry.losses += 1 entry.is_eliminated = True entry.final_rank = 8 elif entry.player_id == losers_r1[3]: entry.losses += 1 entry.is_eliminated = True entry.final_rank = 7 db.commit() db.refresh(t) print(f"Created tournament: {t.name}") return t def seed_completed_matches(db: Session, players: list, courts: list): """Create some historical completed matches""" past_matches = [] for i in range(6): start = datetime.utcnow() - timedelta(days=i + 1, hours=2) p_list = random.sample(players, 4) m = Match( court_id=courts[i % len(courts)].id, stage=MatchStage.OPEN if i % 2 == 0 else MatchStage.SKILL_BASED, match_type=MatchType.DOUBLES, status=MatchStatus.COMPLETED, title=f"Completed Match #{i + 1}", max_players=4, team1_score=11, team2_score=random.randint(5, 10), started_at=start, ended_at=start + timedelta(hours=1), ) db.add(m) db.flush() for player, team in zip(p_list, [1, 1, 2, 2]): mp = MatchPlayer(match_id=m.id, player_id=player.id, team=team, elo_before=player.elo_rating, elo_after=player.elo_rating + random.uniform(-10, 10), elo_change=random.uniform(-10, 10), is_winner=(team == 1)) db.add(mp) past_matches.append(m) db.commit() print(f"Created {len(past_matches)} completed matches") def main(): print("🌱 Seeding ServeSync demo data...") db = SessionLocal() try: clear_data(db) players = seed_players(db) courts = seed_courts(db) seed_bookings(db, players, courts) seed_active_matches(db, players, courts) seed_tournament(db, players, courts) seed_completed_matches(db, players, courts) print("✅ Seed complete!") finally: db.close() if __name__ == "__main__": main()