#!/usr/bin/env python3
"""
Gurobipy Implementation for Poker Player Selection Optimization
"""

import gurobipy as gp
from gurobipy import GRB

def poker_player_optimization():
    """Optimization model for selecting poker players to maximize earnings with constraints."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("poker_player_selection")
    
    # Player data
    earnings = [1200.0, 1500.0, 2000.0, 1000.0, 1800.0]
    money_ranks = [45, 55, 60, 50, 58]
    nationalities = ['USA', 'Canada', 'UK', 'Australia', 'Germany']
    
    # Validate array lengths
    n_players = len(earnings)
    assert len(money_ranks) == len(nationalities) == n_players, "Array length mismatch"
    
    # 2. VARIABLES
    # Decision variables for player selection
    x = {i: model.addVar(vtype=GRB.BINARY, name=f"x_{i}") for i in range(n_players)}
    
    # Auxiliary variables for nationality diversity
    y = {j: model.addVar(vtype=GRB.BINARY, name=f"y_{j}") for j in nationalities}
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(gp.quicksum(earnings[i] * x[i] for i in range(n_players)), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    
    # Nationality Diversity Constraint
    # Ensure at least three different nationalities are represented
    model.addConstr(gp.quicksum(y[j] for j in nationalities) >= 3, name="nationality_diversity")
    
    # Link nationality variables to player selection variables
    for i, j in enumerate(nationalities):
        model.addConstr(y[j] <= x[i], name=f"nationality_link_{i}")
    
    # Money Rank Constraint
    # No more than 20% of selected players can have a money rank below 50
    S = gp.quicksum(x[i] for i in range(n_players))
    L = gp.quicksum(x[i] for i in range(n_players) if money_ranks[i] < 50)
    model.addConstr(L <= 0.2 * S, name="money_rank_limit")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_players):
            if x[i].x > 0.5:
                print(f"Player {i+1} selected: Earnings = {earnings[i]}, Nationality = {nationalities[i]}, Money Rank = {money_ranks[i]}")
    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__":
    poker_player_optimization()