# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_event_assignments():
    """Optimize participant assignments to events to maximize satisfaction scores."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("local_govt_in_alabama")
    
    # Sample data based on the provided schema and data
    satisfaction_scores = {
        (1, 101): 0.7,
        (1, 102): 0.9,
        (2, 101): 0.6,
        (2, 103): 0.8,
        (3, 102): 0.5
    }
    
    event_capacities = {
        101: 50,
        102: 100,
        103: 150
    }
    
    participants = {1, 2, 3}
    events = {101, 102, 103}
    
    # CRITICAL: Validate array lengths before loops
    assert all(isinstance(satisfaction_scores[(i, j)], float) for i in participants for j in events if (i, j) in satisfaction_scores), "Satisfaction scores must be floats"
    assert all(isinstance(event_capacities[j], int) for j in events), "Event capacities must be integers"
    
    # 2. VARIABLES
    # Decision variables: x[i, j] = 1 if participant i is assigned to event j, 0 otherwise
    x = model.addVars(participants, events, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total satisfaction score
    model.setObjective(gp.quicksum(satisfaction_scores[i, j] * x[i, j] for i, j in satisfaction_scores), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Capacity constraints: Ensure no event exceeds its capacity
    model.addConstrs((gp.quicksum(x[i, j] for i in participants) <= event_capacities[j] for j in events), name="capacity_limit")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in participants:
            for j in events:
                if x[i, j].x > 1e-6:
                    print(f"Participant {i} assigned to Event {j} with satisfaction score {satisfaction_scores[i, 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_event_assignments()