# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_event_participation():
    """Optimize participant assignments to events to maximize satisfaction scores."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="local_govt_in_alabama")
    
    # Data from the database (mocked for this example)
    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
    }
    
    # Extract unique participants and events
    participants = set(participant_id for participant_id, _, _ in satisfaction_scores)
    events = set(event_id for _, event_id, _ in satisfaction_scores)
    
    # CRITICAL: Validate data consistency
    assert all(event_id in event_capacities for _, event_id, _ in satisfaction_scores), "Event ID mismatch"
    
    # 2. VARIABLES
    # Binary decision variables for participant-event assignments
    x = {(i, j): mdl.binary_var(name=f"x_{i}_{j}") for i, j, _ in satisfaction_scores}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total satisfaction score
    objective = mdl.sum(score * x[i, j] for i, j, score in satisfaction_scores)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Capacity constraints for each event
    for j in events:
        mdl.add_constraint(mdl.sum(x[i, j] for i, _, _ in satisfaction_scores if j == _) <= event_capacities[j], ctname=f"capacity_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i, j, _ in satisfaction_scores:
            if solution.get_value(x[i, j]) > 0.5:  # Binary variable threshold
                print(f"Participant {i} assigned to Event {j}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")

    return mdl

# Run the optimization
optimize_event_participation()