| Division | Eligible | Share % | Raw Allocation | Cap/Floor | Pool Alloc | Remainder | Final |
|---|---|---|---|---|---|---|---|
| Total | 100% |
| # | Athlete | Division | Birth Year | MO | DM | Total Events (thru 2/28) | Reason(s) |
|---|
| Athlete | Registered Division | Events by Division | Reassigned To | Reason |
|---|
Implement two allocation calculators for the MNRL app:
Both use the same general approach (proportional allocation with min/max constraints and redistribution) but differ in eligible population, maximum allocation, and min/max values.
Eligible athletes: FIS-eligible athletes (U15 or above) who have competed in a minimum of three scored moguls and/or dual moguls events in the active season as of February 28. Counted per division per gender.
Division reassignment rule: Athletes registered in divisions that do not meet the minimum event-hosting requirement (three days of scored freestyle competition including moguls and/or dual moguls) are reassigned to the division in which they skied the majority of their scored events during the season.
Maximum allocation: 15 spots per gender (referred to as "maximum number of divisional allocation spots" in the proposal)
Minimum per division: 1 per gender
Maximum per division: 6 per gender
Data source: Eligible athlete counts as of February 28
Eligible athletes: U15+ athletes (same eligible population as Path 3) in each division who have competed in a minimum of three scored moguls and/or dual moguls events in the current season as of February 28. Counted per division per gender.
Division reassignment rule: Same as Path 3.
Maximum allocation: 80 spots per gender
Minimum per division: 5 per gender
Maximum per division: None specified
Data source: Same as Path 3 (eligible athlete counts as of February 28)
The algorithm is identical for both Path 3 and Path 4, parameterized by the values above.
divisions[] - list of divisions with eligible athlete counts
max_allocation - total spots to distribute (15 for Path 3, 80 for Path 4)
min_per_division - minimum guarantee per division (1 for Path 3, 5 for Path 4)
max_per_division - maximum cap per division (6 for Path 3, null for Path 4)
For each division, count the number of eligible athletes per gender.
division.eligible_count = count of eligible athletes in division
total_eligible = sum of all division.eligible_count
division.share = division.eligible_count / total_eligible
Both paths round down (floor) to the nearest whole number.
division.raw_allocation = floor(division.share * max_allocation)
for each division:
if max_per_division is not null and division.raw_allocation > max_per_division:
division.allocation = max_per_division
division.capped = true
else:
division.capped = false
for each division:
if division.raw_allocation < min_per_division:
division.allocation = min_per_division
division.floored = true
else:
division.floored = false
After applying cap and floor constraints, distribute remaining spots among unconstrained divisions using proportional allocation with fractional remainder assignment.
spots_constrained = sum of allocation for all capped + floored divisions
remaining_spots = max_allocation - spots_constrained
Unconstrained divisions are those not subject to a minimum floor or maximum cap:
redistribution_pool = divisions where capped == false and floored == false
pool_eligible_total = sum of eligible_count for divisions in redistribution_pool
for each division in redistribution_pool:
division.pool_share = division.eligible_count / pool_eligible_total
division.pool_raw = division.pool_share * remaining_spots
division.allocation = floor(division.pool_raw)
division.fractional_remainder = division.pool_raw - division.allocation
leftover = remaining_spots - sum of allocation for redistribution_pool
Sort redistribution_pool by:
1. fractional_remainder descending
2. eligible_count descending (tie-break)
3. division_code ascending (second tie-break)
for i = 1 to leftover:
assign +1 spot to the next division in sorted order
This ensures all available spots are distributed. The fractional remainder step recovers spots lost to floor rounding.
total_allocated = sum of all division.allocation
unallocated = max_allocation - total_allocated
Note: fractional remainder allocation in Step 6d ensures all available spots are distributed. Unallocated spots should be 0 in normal operation.