432 lines
15 KiB
Python
432 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()
|
|
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()
|