Files
servesync-demo/backend/seed.py

440 lines
15 KiB
Python

"""Seed demo data for ServeSync"""
import sys
import os
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()
# Reset sequences
for table in ['players', 'courts', 'bookings', 'matches', 'match_players',
'tournaments', 'tournament_entries', 'tournament_matches']:
try:
db.execute(__import__('sqlalchemy').text(f"ALTER SEQUENCE {table}_id_seq RESTART WITH 1"))
except Exception:
pass
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()