# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def sports_competition_optimization():
    """Optimize player assignments to clubs to maximize total points."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("sports_competition")
    
    # Data from the problem context
    players = [1, 2, 3]
    clubs = [1, 2, 3]
    points = {1: 15, 2: 25, 3: 10}
    max_apps = {1: 3, 2: 4, 3: 2}
    capacities = {1: 5, 2: 10, 3: 8}
    
    # CRITICAL: Validate array lengths before loops
    assert len(players) == len(points) == len(max_apps), "Player data length mismatch"
    assert len(clubs) == len(capacities), "Club data length mismatch"
    
    # 2. VARIABLES
    # Binary decision variables for player-club assignments
    x = model.addVars(players, clubs, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total points scored by all clubs
    model.setObjective(gp.quicksum(points[i] * x[i, j] for i in players for j in clubs), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Player application limit constraints
    model.addConstrs((gp.quicksum(x[i, j] for j in clubs) <= max_apps[i] for i in players), name="player_app_limit")
    
    # Club capacity limit constraints
    model.addConstrs((gp.quicksum(x[i, j] for i in players) <= capacities[j] for j in clubs), name="club_capacity_limit")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in players:
            for j in clubs:
                if x[i, j].x > 1e-6:
                    print(f"Player {i} assigned to Club {j}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
sports_competition_optimization()