# Complete DOCPLEX implementation

from docplex.mp.model import Model

def decoration_competition_optimization():
    """Optimization for decoration competition to maximize rank points"""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="decoration_competition")
    
    # Data from the problem context
    rounds = [1, 2, 3]
    members = [101, 102, 103]
    
    # Rank points data
    rank_points_data = {
        (1, 101): 25.0,
        (2, 102): 30.0,
        (3, 103): 0.0,
        (1, 102): 20.0,
        (2, 101): 0.0
    }
    
    # Validate data consistency
    assert all(isinstance(rank_points_data[key], float) for key in rank_points_data), "Rank points data must be float"
    
    # Safe range for indexing
    safe_rounds = range(len(rounds))
    safe_members = range(len(members))
    
    # 2. VARIABLES
    # Binary decision variables for participation
    x = {(i, j): mdl.binary_var(name=f"x_{i}_{j}") for i in rounds for j in members}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total rank points
    objective = mdl.sum(rank_points_data.get((i, j), 0.0) * x[i, j] for i in rounds for j in members)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    # Each member can participate in a maximum of three rounds
    for j in members:
        mdl.add_constraint(mdl.sum(x[i, j] for i in rounds) <= 3, ctname=f"max_rounds_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in rounds:
            for j in members:
                value = solution.get_value(x[i, j])
                if value > 1e-6:
                    print(f"Member {j} participates in round {i}: {value:.0f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")

    return mdl

# Run the optimization
decoration_competition_optimization()