#!/usr/bin/env python3
"""
DOCplex implementation for music ensemble performance attendance optimization
"""

from docplex.mp.model import Model

def optimize_performance_attendance():
    """Optimize the number of pieces each member performs to maximize attendance"""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="performance_attendance")
    
    # Data from the provided SQL inserts
    members = [1, 2, 3]
    performances = [1, 2, 3]
    
    member_max_pieces = {1: 5, 2: 4, 3: 3}
    performance_max_pieces = {1: 10, 2: 8, 3: 6}
    attendance = {1: 200, 2: 150, 3: 100}
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(members) == len(member_max_pieces) == 3, "Member data length mismatch"
    assert len(performances) == len(performance_max_pieces) == len(attendance) == 3, "Performance data length mismatch"
    
    # 2. VARIABLES
    x = {(m, p): mdl.continuous_var(name=f"x_{m}_{p}", lb=0) for m in members for p in performances}
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(attendance[p] * x[(m, p)] for m in members for p in performances)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Maximum Pieces per Member
    for m in members:
        mdl.add_constraint(mdl.sum(x[(m, p)] for p in performances) <= member_max_pieces[m], ctname=f"max_pieces_member_{m}")
    
    # Maximum Pieces per Performance
    for p in performances:
        mdl.add_constraint(mdl.sum(x[(m, p)] for m in members) <= performance_max_pieces[p], ctname=f"max_pieces_performance_{p}")
    
    # Minimum Pieces per Member
    for m in members:
        mdl.add_constraint(mdl.sum(x[(m, p)] for p in performances) >= 1, ctname=f"min_pieces_member_{m}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for m in members:
            for p in performances:
                value = solution.get_value(x[(m, p)])
                if value > 1e-6:
                    print(f"x[{m},{p}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

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