Configure: WP Cycling Road League Leaderboard
|
This procedure assumes the Leaderboard
Model — it is the operator’s "set it up" companion to that design. The concrete ids below are
for the 2026 Autumn Road League (Org 4); for a later season substitute that season’s series,
event, and CustomList ids. Design rationale is captured in design journal
|
1. Outcome
Three configured leaderboards for the WP Cycling Road League season, ready to be populated from imported race results:
| Board | type |
Scope |
|---|---|---|
Individual |
|
All scored events except the TTT; per- |
Team/Club |
|
All scored events including the TTT; grouped by |
All Rounder |
|
Starred events only (the multi-discipline subset); per- |
All three score with WpcaRoadLeaguePointsCalculator (positions 1–12 →
50/45/40/36/34/32/30/28/26/24/22/20; 13+ → 2 participation points) and aggregate per series
category — no separate gender filter, because the category structure already splits men and
women.
2. Cadence
Once per season, after the series and its events exist. The per-event result import that feeds these boards is the recurring task — see Import Operations Guide, selecting the WPCA calculator (next section).
3. Prerequisites
-
The Road League Series exists (2026: Series 10, "2026 Road League", Org 4) with its eight series categories in place (2026: ids 2480–2487 — Cat 1–4, Women, U/19 Men, U/19 Women, Under 19 Development).
-
All scored events exist under the series with their
EventCategorylinked to the series categories (2026: events 119, 120, 121, 127, 128, 129, 130, 131, 132 — Duynefontein, Red Hill, Killarney 1, Simonstown, TTT, Paardeberg, Philadelphia, Slent, Killarney 2). -
The Club CustomList is mapped to
custom_list_1and the Team CustomList tocustom_list_2on every Road League event (2026: club list 1504; Team listcustom_list.id = 1505, "WP Teams 2026",custom_list_2_name = 'Team', set on all nine events).
4. Steps
4.1. 1. Import results with the WPCA calculator
The boards read RaceResult.points, so each event’s results must be imported with the Road
League scale, not the default. Pass the calculator on the results-import endpoints:
PUT /api/result-sets/import?...&pointsCalculator=WpcaRoadLeaguePointsCalculator
PUT /api/result-sets/import-bulk?...&pointsCalculator=WpcaRoadLeaguePointsCalculator
pointsCalculator accepts the short code or the fully-qualified class name; omitting it falls
back to the default SASchoolCyclingSeriesPointsCalculator. Full operator steps:
Import Operations Guide.
|
Default behaviour is unchanged: any import that does not pass |
4.2. 2. Create the three Leaderboard rows
All three reference the Road League series, set pointsCalculatorClass =
WpcaRoadLeaguePointsCalculator, gender = NULL, and active = true.
| Board | type |
groupByList |
|---|---|---|
Individual — Road League 2026 |
|
— (groups by Person) |
Team/Club — Road League 2026 |
|
the Team list (1505), with Club (1504) as fallback |
All Rounder — Road League 2026 |
|
— (groups by Person) |
4.3. 3. Wire each board to all eight series categories
Add a LeaderboardCategory row per board for each of the eight series categories (no
pointsMultiplier). All three boards aggregate across the full category set; the event scope
(not the category scope) is what differs between them.
4.4. 4. Apply the Team/Club overlay (Team/Club board only)
A rider on a registered team scores for that team on the Team/Club board, while remaining a member of their club on every other report:
-
The Team/Club aggregation key is
COALESCE(EventParticipant.custom_2_id /* team /, EventParticipant.custom_1_id / club */)— team overrides club when set; riders without a team fall back to their club. -
Individual and All Rounder boards are unaffected — a rider’s club there comes from
custom_1_id(normalise NULL / "None" / "Other" to "None"). -
Team CustomListValues are populated as teams register; the only operational addition to EP imports is a "Team" column.
4.5. 5. Apply the event-scope rules
For this season the event sets are hardcoded event-ID lists in the manual aggregation queries (a first-class per-leaderboard event set is deferred — see Leaderboard Sync):
-
Individual and All Rounder — exclude the TTT (2026: event 128) from the aggregation.
-
Team/Club — include the TTT. The TTT produces a
RaceResultrow for every rider with the team’s finishing-position points, so club/team aggregation has the numbers it needs with no special import path. -
All Rounder — restrict to the starred events (2026: Duynefontein, Simonstown, Paardeberg, Slent), which reward performance across Road + Hill Climb + ITT.
4.6. 6. Populate the standings
Until Leaderboard Sync lands, aggregate
the standings manually from RaceResult.points per the event-scope rules above. Points on
RaceResult must be correct (step 1), because manual SQL aggregation reads from them.
5. Verification
-
Three
Leaderboardrows exist under the Road League series, each withpointsCalculatorClass = WpcaRoadLeaguePointsCalculatorand the full eight-category set. -
For one imported event, position→points follows 50/45/40/36/34/32/30/28/26/24/22/20 exactly (13+ → 2).
-
Individual and All Rounder exclude the TTT; Team/Club includes it.
-
A team-registered rider scores under their team on Team/Club but under their club on Individual.
6. Recovery
-
Wrong points (e.g. default scale applied) → re-import the event with
pointsCalculator=WpcaRoadLeaguePointsCalculator, then re-aggregate. See Import Operations Guide. -
Rider on wrong team → correct the EP’s
custom_2_id; Individual/All Rounder are unaffected. -
All Rounder includes a non-starred event → audit the hardcoded event-ID list in the aggregation query.
7. References
-
Leaderboard Model & Result Classification — the schema and classification this procedure configures.
-
Configure: WC Schools Cycling Annual Leaderboard — the sibling procedure; same model, different scoring and grouping.
-
Import Operations Guide — importing results with the
pointsCalculatorquery parameter.