diff --git a/templates/solver.html b/templates/solver.html
index dad7ffe..5099dee 100644
--- a/templates/solver.html
+++ b/templates/solver.html
@@ -414,6 +414,47 @@
+
+
+
Solver Settings
@@ -699,6 +740,17 @@
data[input.name] = input.checked;
});
+ // Collect objective mode and factors (only nonzero factors; missing = excluded)
+ data.objective_mode = document.getElementById('objective_mode').value;
+ const objectiveFactors = {};
+ ['E', 'B', 'S', 'C'].forEach(r => {
+ const factor = parseInt(document.getElementById(`objective_factor_${r}`).value);
+ if (factor) {
+ objectiveFactors[r] = factor;
+ }
+ });
+ data.objective_factors = objectiveFactors;
+
// Collect fixed action constraints
const fixedActions = {};
form.querySelectorAll('[id^="action-constraint-"]').forEach(row => {
diff --git a/web_solve.py b/web_solve.py
index 7cb520d..7267171 100644
--- a/web_solve.py
+++ b/web_solve.py
@@ -21,6 +21,8 @@ def index():
actions=solve.ENABLED_ACTIONS,
agents=solve.AGENT_AVAILABILITY,
num_steps=solve.NUM_STEPS,
+ objective_factors=solve.OBJECTIVE_FACTORS,
+ objective_mode=solve.OBJECTIVE_MODE,
)
@@ -138,6 +140,18 @@ def solve_handler():
city, step = int(city), int(step)
fixed_choices["governors"][(city, step, agent)] = enabled
+ # Parse objective (factor = exponent in "product" mode, weight in
+ # "sum" mode; missing keys = resource excluded). Factors are NOT x10
+ # scaled — they apply to the scaled resource totals and the report
+ # descales the objective. None falls back to solve.py's defaults.
+ objective_mode = data.get("objective_mode") or None
+ objective_factors = None
+ objective_factors_data = data.get("objective_factors")
+ if objective_factors_data is not None:
+ # All-zero dict passes through so solve()'s validation rejects it
+ # with a clear error instead of silently using the defaults.
+ objective_factors = {r: int(f) for r, f in objective_factors_data.items()}
+
# Parse resource constraints
resource_constraints = None
resource_constraints_data = data.get("resource_constraints", [])
@@ -165,6 +179,8 @@ def solve_handler():
verbose=verbose,
fixed_choices=fixed_choices,
resource_constraints=resource_constraints,
+ objective_factors=objective_factors,
+ objective_mode=objective_mode,
)
output = output_buffer.getvalue()