# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_school_player_allocation():
    """Optimize player allocation to school teams to maximize performance score."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("school_player")
    
    # Data from the database schema
    player_ids = [1, 2, 3]
    team_ids = [1, 2, 3]
    
    performance_coefficients = {1: 1.8, 2: 2.3, 3: 2.7}
    player_ages = {1: 16, 2: 17, 3: 18}
    
    max_team_sizes = {1: 15, 2: 18, 3: 20}
    max_age_limits = {1: 100, 2: 110, 3: 120}
    
    # CRITICAL: Validate array lengths before loops
    assert len(player_ids) == len(performance_coefficients) == len(player_ages), "Player data length mismatch"
    assert len(team_ids) == len(max_team_sizes) == len(max_age_limits), "Team data length mismatch"
    
    # 2. VARIABLES
    # Decision variables: x[i, j] = 1 if player i is assigned to team j, else 0
    x = model.addVars(player_ids, team_ids, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total performance score of all teams
    model.setObjective(gp.quicksum(performance_coefficients[i] * x[i, j] for i in player_ids for j in team_ids), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Team Size Constraints: Each team cannot exceed its maximum number of players
    model.addConstrs((gp.quicksum(x[i, j] for i in player_ids) <= max_team_sizes[j] for j in team_ids), name="team_size")
    
    # Age Limit Constraints: The total age of players assigned to each team must not exceed the specified limit
    model.addConstrs((gp.quicksum(player_ages[i] * x[i, j] for i in player_ids) <= max_age_limits[j] for j in team_ids), name="age_limit")
    
    # Player Assignment Constraints: Each player can be assigned to at most one team
    model.addConstrs((gp.quicksum(x[i, j] for j in team_ids) <= 1 for i in player_ids), name="player_assignment")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in player_ids:
            for j in team_ids:
                if x[i, j].x > 1e-6:
                    print(f"Player {i} assigned to Team {j}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_school_player_allocation()