Spaces:
Sleeping
Sleeping
| import random | |
| import copy | |
| from datetime import datetime | |
| from app.players import get_all_players, ROLE_ORDER | |
| DEFAULT_SETTINGS = { | |
| "purse_per_team": 1200, # lakhs | |
| "min_squad_size": 18, | |
| "max_squad_size": 25, | |
| "max_overseas": 8, | |
| "timer_seconds": 30, | |
| "timer_reset_on_bid": True, | |
| "bid_increment": 5, | |
| "unsold_recall": True, | |
| "auto_pass_enabled": True, | |
| } | |
| SET_ORDER = ["SET_A","SET_B","SET_C","SET_D","SET_E","SET_F","SET_G","SET_H","SET_I","SET_J"] | |
| def create_room(room_code: str, host_id: str, host_name: str, settings: dict = None) -> dict: | |
| s = copy.deepcopy(DEFAULT_SETTINGS) | |
| if settings: | |
| s.update(settings) | |
| return { | |
| "room_code": room_code, | |
| "host_id": host_id, | |
| "created_at": datetime.utcnow().isoformat(), | |
| "state": "lobby", | |
| "settings": s, | |
| "teams": { | |
| host_id: { | |
| "id": host_id, | |
| "name": host_name, | |
| "team_name": f"{host_name}'s XI", | |
| "purse": s["purse_per_team"], | |
| "players": [], | |
| "is_host": True, | |
| "connected": True, | |
| } | |
| }, | |
| "players": get_all_players(), | |
| "auction_queue": [], | |
| "current_player_id": None, | |
| "current_bid": 0, | |
| "current_bidder_id": None, | |
| "bid_history": [], | |
| "sold_log": [], | |
| "unsold_players": [], | |
| "chat_messages": [], | |
| "status_message": "Waiting for host to start.", | |
| } | |
| def add_team(room: dict, user_id: str, username: str, team_name: str = None) -> dict: | |
| if user_id not in room["teams"]: | |
| room["teams"][user_id] = { | |
| "id": user_id, | |
| "name": username, | |
| "team_name": team_name or f"{username}'s XI", | |
| "purse": room["settings"]["purse_per_team"], | |
| "players": [], | |
| "is_host": False, | |
| "connected": True, | |
| } | |
| else: | |
| room["teams"][user_id]["connected"] = True | |
| return room | |
| def get_player(room: dict, pid: str): | |
| return next((p for p in room["players"] if p["id"] == pid), None) | |
| def build_queue(room: dict, order: str = "set") -> list: | |
| players = [p for p in room["players"] if p["status"] == "available"] | |
| if order == "set": | |
| players.sort(key=lambda p: ( | |
| SET_ORDER.index(p.get("auction_set", "SET_J")) | |
| )) | |
| elif order == "role": | |
| players.sort(key=lambda p: ( | |
| ROLE_ORDER.index(p["role"]) if p["role"] in ROLE_ORDER else 99 | |
| )) | |
| elif order == "marquee_first": | |
| players.sort(key=lambda p: ( | |
| ["MARQUEE","A+","A"].index(p.get("category","A")) | |
| if p.get("category") in ["MARQUEE","A+","A"] else 99 | |
| )) | |
| elif order == "india_first": | |
| players.sort(key=lambda p: (0 if not p["overseas"] else 1)) | |
| elif order == "random": | |
| random.shuffle(players) | |
| return [p["id"] for p in players] | |
| def start_next(room: dict) -> dict: | |
| if not room["auction_queue"]: | |
| room["state"] = "ended" | |
| room["status_message"] = "Auction complete!" | |
| return room | |
| pid = room["auction_queue"].pop(0) | |
| player = get_player(room, pid) | |
| if not player: | |
| return start_next(room) | |
| room["current_player_id"] = pid | |
| room["current_bid"] = player["base_price"] | |
| room["current_bidder_id"] = None | |
| room["state"] = "auction" | |
| room["status_message"] = f"Bidding open for {player['name']}!" | |
| return room | |
| def place_bid(room: dict, bidder_id: str, amount: int): | |
| """Returns (ok, message, room).""" | |
| if room["state"] != "auction": | |
| return False, "Auction not active", room | |
| team = room["teams"].get(bidder_id) | |
| player = get_player(room, room["current_player_id"]) | |
| if not team or not player: | |
| return False, "Invalid state", room | |
| settings = room["settings"] | |
| inc = settings["bid_increment"] | |
| min_bid = room["current_bid"] + inc if room["current_bidder_id"] else room["current_bid"] | |
| if amount < min_bid: | |
| return False, f"Min bid is ₹{min_bid}L", room | |
| if team["purse"] < amount: | |
| return False, "Insufficient purse", room | |
| if len(team["players"]) >= settings["max_squad_size"]: | |
| return False, "Squad full", room | |
| if player["overseas"]: | |
| overseas_count = sum( | |
| 1 for pid in team["players"] | |
| if get_player(room, pid) and get_player(room, pid)["overseas"] | |
| ) | |
| if overseas_count >= settings["max_overseas"]: | |
| return False, "Overseas limit reached", room | |
| if bidder_id == room["current_bidder_id"]: | |
| return False, "You are already the highest bidder", room | |
| room["current_bid"] = amount | |
| room["current_bidder_id"] = bidder_id | |
| room["bid_history"].append({ | |
| "player_id": room["current_player_id"], | |
| "bidder_id": bidder_id, | |
| "bidder_name": team["name"], | |
| "amount": amount, | |
| "ts": datetime.utcnow().isoformat(), | |
| }) | |
| return True, f"₹{amount}L by {team['name']}", room | |
| def sell_current(room: dict): | |
| pid = room["current_player_id"] | |
| bidder = room["current_bidder_id"] | |
| if not pid or not bidder: | |
| return mark_unsold(room) | |
| player = get_player(room, pid) | |
| team = room["teams"][bidder] | |
| amount = room["current_bid"] | |
| player["status"] = "sold" | |
| player["bought_by"] = bidder | |
| team["purse"] -= amount | |
| team["players"].append(pid) | |
| room["sold_log"].append({ | |
| "player_id": pid, | |
| "player_name": player["name"], | |
| "team_id": bidder, | |
| "team_name": team["team_name"], | |
| "price": amount, | |
| "ts": datetime.utcnow().isoformat(), | |
| }) | |
| room["current_player_id"] = None | |
| room["current_bidder_id"] = None | |
| room["current_bid"] = 0 | |
| room["status_message"] = f"🔨 SOLD! {player['name']} → {team['team_name']} ₹{amount}L" | |
| return room | |
| def mark_unsold(room: dict): | |
| pid = room["current_player_id"] | |
| if pid: | |
| p = get_player(room, pid) | |
| if p: | |
| p["status"] = "unsold" | |
| room["unsold_players"].append(pid) | |
| room["status_message"] = f"❌ UNSOLD — {p['name']}" | |
| room["current_player_id"] = None | |
| room["current_bidder_id"] = None | |
| room["current_bid"] = 0 | |
| return room | |
| def recall_unsold(room: dict) -> dict: | |
| for pid in room["unsold_players"]: | |
| p = get_player(room, pid) | |
| if p: | |
| p["status"] = "available" | |
| room["auction_queue"].append(pid) | |
| room["unsold_players"] = [] | |
| room["status_message"] = "Unsold players re-added!" | |
| return room | |
| def final_summary(room: dict) -> dict: | |
| summaries = [] | |
| for tid, team in room["teams"].items(): | |
| bought = [] | |
| for pid in team["players"]: | |
| p = get_player(room, pid) | |
| sale = next((s for s in room["sold_log"] if s["player_id"] == pid), None) | |
| if p: | |
| bought.append({**p, "price_paid": sale["price"] if sale else 0}) | |
| spent = room["settings"]["purse_per_team"] - team["purse"] | |
| summaries.append({ | |
| "team": team, | |
| "players": bought, | |
| "spent": spent, | |
| "purse_remaining": team["purse"], | |
| "overseas_count": sum(1 for p in bought if p.get("overseas")), | |
| "role_counts": {r: sum(1 for p in bought if p["role"] == r) for r in ROLE_ORDER}, | |
| }) | |
| return { | |
| "teams": summaries, | |
| "total_sold": len(room["sold_log"]), | |
| "total_unsold": len(room["unsold_players"]), | |
| "most_expensive": max(room["sold_log"], key=lambda s: s["price"], default=None), | |
| "unsold_players": [get_player(room, pid)["name"] for pid in room["unsold_players"] if get_player(room, pid)], | |
| } |