# Complete DOCPLEX implementation - Retry Attempt 4

from docplex.mp.model import Model

def optimize_club_assignment():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="club_assignment")
    
    # Data from the database
    engagement_scores = [
        (1, 101, 0.6),
        (2, 102, 0.8),
        (3, 103, 0.4)
    ]
    
    club_capacities = [
        (101, 20),
        (102, 25),
        (103, 15)
    ]
    
    # Extract unique students and clubs
    students = list(set(score[0] for score in engagement_scores))
    clubs = list(set(capacity[0] for capacity in club_capacities))
    
    # Create dictionaries for engagement scores and capacities
    engagement_dict = {(s, c): score for s, c, score in engagement_scores}
    capacity_dict = {c: cap for c, cap in club_capacities}
    
    # CRITICAL: Validate array lengths
    assert len(engagement_scores) == len(students) * len(clubs), "Engagement scores length mismatch"
    
    # 2. VARIABLES
    x = mdl.binary_var_dict(keys=[(s, c) for s in students for c in clubs], name="x")
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(engagement_dict[(s, c)] * x[(s, c)] for s in students for c in clubs)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Club Capacity Constraint
    for c in clubs:
        mdl.add_constraint(mdl.sum(x[(s, c)] for s in students) <= capacity_dict[c], ctname=f"club_capacity_{c}")
    
    # Student Assignment Constraint
    for s in students:
        mdl.add_constraint(mdl.sum(x[(s, c)] for c in clubs) <= 1, ctname=f"student_assignment_{s}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for s in students:
            for c in clubs:
                if solution.get_value(x[(s, c)]) > 0.5:
                    print(f"Student {s} assigned to Club {c}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")

# Execute the optimization
optimize_club_assignment()