def generate_demands(
rng: random.Random,
customer_ll: list[tuple[float, float]],
demand_type: int,
avg_route_size: int,
) -> tuple[list[int], int, int, float]:
"""Per-customer demands; returns (demands, total, max, target route size r)."""
n = len(customer_ll)
if n < 1:
raise ValueError("At least one customer is required")
rlo, rhi = avg_route_size_bounds(avg_route_size)
r = rng.random() * (rhi - rlo) + rlo
if demand_type == 1:
demands = [1] * n
return demands, n, 1, r
lo, hi = demand_distribution_bounds(demand_type)
lat_center = sum(p[0] for p in customer_ll) / n
lon_center = sum(p[1] for p in customer_ll) / n
demands = []
for i in range(n):
d = rng.randint(lo, hi)
if demand_type == 6:
lat, lon = customer_ll[i]
same_diagonal = (lat < lat_center and lon < lon_center) or (lat >= lat_center and lon >= lon_center)
d = rng.randint(51, 100) if same_diagonal else rng.randint(1, 50)
elif demand_type == 7:
# Julia iterates 1-based: the first ceil-ish 1.5*n/r customers in
# POSITION get bulky demands, the rest small ones (then shuffled).
if (i + 1) < (n / r) * 1.5:
d = rng.randint(50, 100)
else:
d = rng.randint(1, 10)
demands.append(d)
if demand_type != 6:
rng.shuffle(demands)
return demands, sum(demands), max(demands), r