# Complete DOCPLEX implementation - Retry Attempt 1

from docplex.mp.model import Model

def climbing_optimization():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="Climbing_Optimization")
    
    # Data from the database
    climber_ids = [1, 2, 3]
    mountain_ids = [1, 2, 3]
    
    # Points and Time data
    points = {
        (1, 1): 10,
        (2, 2): 20,
        (3, 3): 30
    }
    
    time_spent = {
        (1, 1): 5,
        (2, 2): 10,
        (3, 3): 15
    }
    
    total_time_limit = 100
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(climber_ids) == len(mountain_ids), "Climber and Mountain ID length mismatch"
    
    # 2. VARIABLES
    x = mdl.binary_var_matrix(climber_ids, mountain_ids, name="x")
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(points[(i, j)] * x[(i, j)] for i in climber_ids for j in mountain_ids if (i, j) in points)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Total Time Constraint
    total_time = mdl.sum(time_spent[(i, j)] * x[(i, j)] for i in climber_ids for j in mountain_ids if (i, j) in time_spent)
    mdl.add_constraint(total_time <= total_time_limit, ctname="total_time_limit")
    
    # Single Assignment Constraint
    for i in climber_ids:
        mdl.add_constraint(mdl.sum(x[(i, j)] for j in mountain_ids if (i, j) in x) == 1, ctname=f"single_assignment_{i}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in climber_ids:
            for j in mountain_ids:
                if (i, j) in x and solution.get_value(x[(i, j)]) > 0.5:
                    print(f"Climber {i} assigned to Mountain {j}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Execute the optimization
climbing_optimization()