#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for Riding Club Optimization Problem
"""

import gurobipy as gp
from gurobipy import GRB

def riding_club_optimization():
    """Optimize player-coach assignments to maximize total points."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("riding_club")
    
    # Data from the problem
    players = [1, 2, 3]
    coaches = [1, 2, 3]
    
    player_votes = {1: 12, 2: 18, 3: 9}
    coach_ranks = {1: 3, 2: 2, 3: 1}
    
    # CRITICAL: Validate array lengths before loops
    assert len(players) == len(player_votes), "Player data length mismatch"
    assert len(coaches) == len(coach_ranks), "Coach data length mismatch"
    
    # 2. VARIABLES
    # Binary decision variables: x[p, c] = 1 if player p is assigned to coach c
    x = model.addVars(players, coaches, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total points: sum(player_votes[p] * coach_ranks[c] * x[p, c])
    model.setObjective(
        gp.quicksum(player_votes[p] * coach_ranks[c] * x[p, c] for p in players for c in coaches),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Single Assignment Constraint: Each player must be assigned to exactly one coach
    for p in players:
        model.addConstr(
            gp.quicksum(x[p, c] for c in coaches) == 1,
            name=f"single_assignment_{p}"
        )
    
    # Coach Capacity Constraint: Each coach can handle a maximum of four players
    for c in coaches:
        model.addConstr(
            gp.quicksum(x[p, c] for p in players) <= 4,
            name=f"coach_capacity_{c}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for p in players:
            for c in coaches:
                if x[p, c].x > 0.5:  # Check if assignment is active
                    print(f"Player {p} is assigned to Coach {c}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
if __name__ == "__main__":
    riding_club_optimization()