#!/usr/bin/env python3
"""
DOCplex 2.29.245 Implementation for Party People Optimization Problem
"""

from docplex.mp.model import Model

def party_people_optimization():
    """Optimize the allocation of party members to events across regions."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="party_people")
    
    # Data from the problem statement
    regions = [1, 2, 3]
    influence_coefficients = {1: 0.6, 2: 0.7, 3: 0.5}
    total_members_available = {1: 20, 2: 25, 3: 15}
    max_events = {1: 5, 2: 6, 3: 4}
    min_members = {1: 5, 2: 6, 3: 4}
    min_events = {1: 1, 2: 2, 3: 1}
    cost_per_event = 6000
    total_budget = 150000
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(regions) == len(influence_coefficients) == len(total_members_available) == len(max_events) == len(min_members) == len(min_events), "Array length mismatch"
    
    # 2. VARIABLES
    x = {i: mdl.integer_var(name=f"x_{i}", lb=0) for i in regions}  # Members assigned
    y = {i: mdl.integer_var(name=f"y_{i}", lb=0) for i in regions}  # Events organized
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(influence_coefficients[i] * x[i] for i in regions)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Budget Constraint
    total_cost = mdl.sum(cost_per_event * y[i] for i in regions)
    mdl.add_constraint(total_cost <= total_budget, ctname="budget_constraint")
    
    # Member Assignment Upper Bound
    for i in regions:
        mdl.add_constraint(x[i] <= total_members_available[i], ctname=f"member_upper_{i}")
    
    # Member Assignment Lower Bound
    for i in regions:
        mdl.add_constraint(x[i] >= min_members[i], ctname=f"member_lower_{i}")
    
    # Event Organization Upper Bound
    for i in regions:
        mdl.add_constraint(y[i] <= max_events[i], ctname=f"event_upper_{i}")
    
    # Event Organization Lower Bound
    for i in regions:
        mdl.add_constraint(y[i] >= min_events[i], ctname=f"event_lower_{i}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in regions:
            x_value = solution.get_value(x[i])
            y_value = solution.get_value(y[i])
            print(f"Region {i}: Members assigned = {x_value}, Events organized = {y_value}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

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