Dev blog Season planning Bordure · October 17, 2026

A season is planned before it is raced

Dozens of races to spread across about twenty riders: nobody should fill in that table by hand. In Bordure, the staff proposes a complete programme as soon as the season opens, you only touch the exceptions, and what you decide is never overwritten. Here is how that programme is built, and then kept up to date, month after month.

career state 38 dossiers 2 injuries 2

A saved career is refused if any of these numbers has changed: a programme is never resumed under different rules from the ones that produced it.

In Bordure you are the sporting director: you choose neither a rider’s power nor his line, you choose where he races. Season planning is therefore the heaviest decision in the game, and in many management games the most painful: form peaks set race by race, future assignments lost, an assistant who wears out the riders. Bordure’s planner turns the problem around: the staff proposes a complete annual programme, you edit the exceptions, and a decision you took is never silently undone.

This post follows a season in the order the engine builds it: the guarantees, priorities, hierarchy, objectives and their preparation, race-day targets, the generator, young riders, the three ways to play the programme, the monthly revision, what the staff actually knows, then how a planner is measured and what it still does badly. What happens once the race has started is in the post on the race engine. The planner lives in a TypeScript package with no clock and no randomness: same inputs, same programme.

3A races at most per team, and at most 25 % of the race days it is invited to.
18 dof preparation reserved before every A objective: taper, specific work, intensity.
8revisions per season, on the last day of each month, from February to September.
1single generator for every team, yours included, and no random draw.
00

Six guarantees before the first calculation

Before talking about scores or priorities, the planner commits to six invariants. They are checked by tests that replay the well-known traps of season planners: a future assignment overwritten, an earlier race blocking a later one, a programme undone by a simple reload.

Guarantee 1

An entered race has all its starters

Before the start, an entered race has exactly the number of starters its rules require. Not one fewer, not one more.

Guarantee 2

No rider in two places

Two starts on the same day are refused, as are two races whose dates overlap: a stage race reserves its whole interval.

Guarantee 3

Your decision stays protected

A manual decision holds until you give an explicit command. Removing a rider from a race protects his absence.

Guarantee 4

The past is not rewritten

A race that has started or finished is frozen. A revision only touches the future.

Guarantee 5

Looking changes nothing

Browsing, sorting or previewing a draft changes neither the programme nor the career.

Guarantee 6

All or nothing

A grouped change applies entirely or not at all, and only if the career is in the state you read it in.

01

Propose, don’t impose

The two screens every player expects from a planner are the riders’ objectives and the table assigning races. In Bordure they edit the same programme: a rider’s sheet explains his season, the team table spreads the entries, and they are two readings of the same assignments, not two lists to keep in sync.

Three notions stay distinct, because confusing them is the source of most painful planners.

Notion 1

Objective

A race targeted by a rider, with a priority and a desired role: leader, support or free role. It has an author (the staff or you) and a state: held, compromised or abandoned.

Notion 2

Assignment

Always the whole race. A stage race reserves its entire interval; after the start, only the survivors carry on, with no replacement.

Notion 3

Preparation

A form window derived from the objectives, never set race by race. You say where the rider must shine; the staff works out when he prepares.

Not to be confused

A race has a public level (major if every top-division team is invited) and, for your team, a priority A, B or C. The two are independent: a small race can be an A objective for a team with a rider built to win it.

A rider’s annual role in a race, his planned leader slot, pre-fills the race plan at the briefing. The briefing stays editable, and the race plan keeps its authority once the race is under way.

02

Opening a season in seven steps

When a career is created, then when each season opens, every team in the world is planned in the same order, by the same function, on its own estimates. Nothing is drawn at random: the generator is a pure function of the inputs frozen at generation time (what the team knows, the calendar, the past and the protected decisions).

Opening a seasonfor each team, in this order
1PrioritiesA, B or C for each race on the team’s calendar.
2HierarchyLeaders, lieutenants, domestiques, young riders, and their terrains.
3ObjectivesA planned leader per A race, two more objectives per leader.
4IntentionsDevelopment or performance, for each rider.
5Race-day targetsThe team’s capacity shared out among its riders.
6AssignmentsThe generator fills every race (section 07).
7For your teamA forfeit declared if a race can’t be covered, objectives “to watch”, a report.

Intentions are set by the staff: development under 24 (except the planned leader of an A race), performance otherwise. You can change them; upkeep is never assigned automatically.

When a race’s entrants follow the official invitation rule, a team is entered only if the race fits within its capacity for the day and for the season. A forfeit at generation is therefore the exception: it mostly concerns modified content packs that don’t allow a race to be covered, and it is always announced by a message.

03

Priorities A, B and C

A race’s priority, for a team, blends two things: how much the race matters to everyone, and how well suited the team is to it.

interest = 60 × share of top-division teams invited + 40 × squad affinity
affinity = the team’s estimated strength on the race (average of its best estimated aptitudes),
scaled between 0 and 1 among the team’s races

Races are then ranked by decreasing interest, and caps do the rest. At most three A races, which together cover at most a quarter of the invited race days (the first A is admitted even if it is long). The other major races are B, then B is topped up by interest as long as A and B together stay under 65 % of the days. The rest is C.

Caps on invited race daysIllustrative diagram
Aat most 25 %
Bup to 65 % with A
Cthe rest

The proportions show the caps, not a real team. Affinity is relative to the team’s other races: a sprinter squad doesn’t get the same A list as a climbing one.

The share of top-division teams is read from the season’s entrants, known before the programmes are generated, whether they come from a fixed list or from the invitation rule. Priorities are season-level decisions: the monthly revision never revisits them.

04

The hierarchy: five tiers, five terrains

The generator doesn’t pick “the seven best”: it starts from a hierarchy. Each rider has a tier per season, and leaders and lieutenants also get a terrain that says which races they count for.

The five tiersone per rider and per season
TierWhat the generator draws from it
Grand tour leaderLeads the grand tours, and only if the team’s calendar contains one. The most apt at the general classification.
LeaderLeads the races of his terrain: classics, week-long stage races, sprints. At most two performance objectives.
LieutenantProtected support to the leader of his terrain on that leader’s objectives. Fallback leader in the C races of that terrain.
DomestiqueCarries the volume: fills most of the places.
Young riderUnder 24, neither leader nor lieutenant. Has a minimum number of race days (section 08).

The terrain is one of five: flat and sprint, hills, cobbles, mountains, or general classification. Aptitude at a terrain is the average of the rider’s estimated aptitude over the courses of that type the team is going to race. For the general classification, it is the average over the stages of the stage races, weighted by each stage’s terrain (flat 1, hilly 2, cobbles 2, mountain 2), because a flat stage finishes in a bunch and gives little more than time bonuses.

When each season opens, the staff proposes the hierarchy, with the same rule for every team:

  • Leaders: at most three, and at least one, i.e. one per block of six riders. They are chosen one at a time, each on the most important terrain that still has the fewest, so as to cover the squad’s specialities rather than take the three best of an average.
  • Lieutenants: at least one per leader, the most apt remaining on his terrain. A lieutenant automatically takes his leader’s speciality, which you can then change.
  • Young riders: any rider under 24 who is neither leader nor lieutenant.
  • Domestiques: the others.

The ranges are advice (for example two to four leaders for eighteen riders), never blocks. They come out as named warnings: too many or too few leaders, a leader without a lieutenant, a terrain with neither leader nor lieutenant, a grand tour without a grand tour leader.

05

Objectives, key races and the preparation window

Each A race gets a planned leader: the leader of its terrain (the grand tour leader for a grand tour), failing that the lieutenant of that terrain, failing that a leader among the most apt of the squad on the race. If nobody fits, the race has no planned leader and the staff will choose at the briefing: a team of sprinters may well have nobody for a mountain stage. Then each leader fills up to two objectives among the B races of his terrain, and the terrain’s lieutenants support their leader’s objectives. Two objectives of the same rider never overlap.

The preparation window of an A objectivereserved at generation
4 dtaper
7 dspecific
7 dintensity
A objectivefirst day

4 + 7 + 7 = 18 days: these are the days of the staff’s training plan, and the condition of the form “reference band” that a rider with no race in those days reaches.

For each rider of an A objective, these eighteen days are reserved: the generator doesn’t line him up inside the window (it costs 1,000 points in the filling score, which amounts to a ban). Then the preparation is assessed: the rider’s form is projected day by day under the candidate programme, and the objective is declared prepared if the form factor on its first day reaches the reference band, 1.030. Otherwise the compromise is named: “A objective not prepared”.

Key races

When you set an objective, the race becomes a key race. It moves to priority A with you as author: it is protected and counts toward the staff’s caps. The rider gets his preparation window and his leader or support slot there, and the staff removes its own objectives from any rider whose key races you have set: they become his complete list.

Setting a B or C priority on a race that carries key races removes them: they were a peak, now there is no peak. Removing the last key race of a race gives its priority back to the staff. Around your choices, the staff recomputes its own priorities (a staff A race may drop back to B when the caps are reached), redoes the objectives of races that gain or lose a leader, then moves the riders whose key races have changed: they leave their other upcoming races where they were neither imposed nor on an objective, and the staff fills those places while respecting their targets and windows. In “I plan everything” it merely removes its objectives from the riders you have set.

06

Race-day targets

A team can’t race everyone everywhere: its capacity is the number of places to fill, i.e. the sum over the season, for each race, of the number of riders its rules grant multiplied by its days. A rider’s target is his share of that capacity, pro rata to a weight that depends on his tier and on the team’s division.

Race-day target weightsonly the ratios matter
TierTopProContinental
Grand tour leader7585—
Leader90105110
Lieutenant100100100
Domestique100100100
Young rider8085100

The “upkeep” intention multiplies any rider’s weight by 0.85. Targets are rounded to the largest remainders, so they add up to exactly the capacity.

The weights come from real benchmarks. According to public statistics, a top-division rider raced 57 days on average in 2023; grand tour leaders sat between 44 and 58 days, i.e. 0.7 to 0.8 times a domestique, and the annual records (77 to 92 days) belonged to domestiques. Leaders are kept fresh for their objectives, domestiques carry the volume. For the lower divisions, the weights are estimates: a pro team lives off its leaders’ points, and they race a little more; in continental teams, leaders have to show themselves and young riders aren’t spared.

An example with Elvane, a fictional team shipped with the game: 371 rider-days to share among 18 riders (3 leaders, 4 lieutenants, 6 domestiques, 5 young riders). That gives 20 days to the leaders, 22 to the lieutenants and domestiques (one of the twenty-two rises to 23 by largest remainder) and 18 to the young riders.

Holding a target isn’t following it to the letter

A race is indivisible: no one promises to hit a target to the day. The generator therefore applies a pressure to the score of each place. Up to the tolerance it is mild and depends on the priority: nothing on an A race, where the strongest team starts, about a point per day on a B and two on a C. Beyond the target plus a tolerance (ten percent of the target, three days at least), each extra day takes 40 points off the score, whatever the priority.

That last rule is recent, and it fixes a measured defect. Without it, leaders raced far too much: on the real calendar, top-division grand tour leaders averaged 65.7 days against a target of 48, with cases up to 26 days over. The cause was simple. The pressure was zero on A races and one point per day on B races, while a leader has twenty to twenty-five more points of aptitude than a domestique: no slope that shallow could tell them apart. After the fix, no tier average exceeds its target plus tolerance (thirty-one overruns before, zero after, over five seeds).

Overload, concretely

Targets limit the number of days, not how they chain together. The generator therefore also projects each rider’s form day after day. Every rider carries a recovery debt: it climbs when he strings together demanding days without a real easy day, and falls slowly. Beyond a threshold it eats into his form: that is the accumulated fatigue, capped at 8 %. A high chronic load alternated with recovery doesn’t push it up; intensity with no break at all takes it to the cap. A rider whose projection shows more than 14 days in a row at 2 % accumulated fatigue or more is taken off a movable race in favour of a replacement who isn’t overloaded.

07

The generator: one score, five steps

The generator fills every place of every entered race. It has no global solver: it is five readable steps, always in the same order, with no draw.

The generator’s five stepsthe same for every team
  1. What is already decided. Races that have started or finished, presences, absences and leaders you imposed, training camps under way.
  2. Objectives, A then B. By decreasing interest, the leader before his supports, with each rider’s preparation window reserved.
  3. Young riders’ exposure. Places reserved so that each young rider reaches his minimum number of days (section 08).
  4. Filling. Race by race, starting with the one that has the fewest available candidates; for each place, the rider with the best score.
  5. Repair. A bounded pass of replacements and swaps that reduces overload or exposure deficit without uncovering a place or compromising an A objective.
score = estimated aptitude − target pressure − 1,000 if the rider is in a reserved window
race order: fewest available candidates, then priority A, B, C, longest first, date, identifier
tie between two riders: the rider’s identifier

Starting with the race that has the fewest candidates is the classic heuristic for placement problems: handle the most constrained first, so you don’t discover at the end that a race can no longer be filled. The repair pass is limited to three moves per rider and sixty per team, and a move is kept only if it reduces its problem without creating a new one.

The result carries an explicit outcome:

complete

Everything is covered

Every place is filled, every objective holds, no young rider is under his minimum, no lasting overload.

with compromises

Named causes

Objective not covered, A objective not prepared, young rider under his minimum, overload of more than 14 days: every compromise is stated, never hidden.

unresolved

A place can’t be filled

In a revision, the previous programme is kept. At first generation, the race is declared a forfeit with a message.

Why not a global solver

A solver would sometimes find solutions that take three coordinated moves, and a more even spread. We lose those. In exchange we keep a complete season, the same rules for everyone, persistent decisions, explanations and grouped corrections. The finer solver will be taken up if played seasons show what it would bring.

What the result looks likeIllustrative diagram
Rider
C race
A classic
B race
A tour
C race
Leader (hills)
prep
L
S
—
—
Leader (general)
—
—
prep
L
S ≈
Lieutenant
—
S
S ≈
S
—
Domestique
S ≈
S
S
S
—
Young rider
Y ≈
—
Y ≈
—
Y ≈

L leader · S starter · Y a young rider’s exposure place (staff annotation) · ≈ filled in by the staff · prep reserved preparation window, the rider doesn’t race.

A team table reads this programme as riders × races. Marks are always doubled by a letter or a label: never a colour alone.

08

Getting young riders racing

A young rider who doesn’t race gains no experience. Each team therefore guarantees every rider under 24 a minimum number of days: the smaller of ten and half the average capacity per rider (team capacity divided by squad size). A team that races a lot asks for ten; a small team asks for fewer, because it has fewer places to give.

  • The minimum is programmed from February and counts every participation, B and C races included.
  • Several young riders can receive a place on the same day. We start with the races that have the fewest.
  • Exposure places are reserved first on C races, then B. On an A race, a young rider only takes a domestique place, and only if he has the level: his estimated aptitude is no more than 8 points below that of the domestique he replaces. He is never a leader through the exposure rule alone, and the planned leader and his protected supports are never moved for him.
  • A young rider without that level isn’t lined up in an A race: his minimum is completed in B and C races.
  • You can override, and the deficit stays displayed.
A deliberate decision

Racing feeds a young rider’s experience like anyone else’s, but the programme adds no learning bonus on top: exposure gives him opportunities, not faster progression. When the effect was measured, neither intention nor exposure told two young riders apart on the power test. The programme has them race because that is a team’s job, not to buy progression.

09

Three ways to play the programme

Some players want to delegate everything, others to set everything, most something in between. Your team’s “Programme” setting therefore has three values, which you can change at any time. Opposing teams always play the first.

The three ways to playyour team’s setting
SettingHierarchy and key racesProgramme
The staff plans everythingProposed and revised by the staff.Generated and revised by the staff; your exceptions stay protected.
I set the hierarchy and key racesYours. The staff never changes them.Generated and revised by the staff from them.
I plan everythingYours.Yours. The staff changes nothing: it warns, and proposes on request.

In all three cases, the programme stays editable cell by cell.

Changing the setting doesn’t rewrite the programme. It is a game decision, not a presentation one: it is journaled and goes through a command, like any other. When a season opens, the setting determines what carries over. With “The staff plans everything”, the staff re-proposes the hierarchy, carrying over your protected tiers. With “I set the hierarchy”, yours is carried over as is; a rider who has turned 24 leaves the young tier, with a message. With “I plan everything”, the programme opens empty and the staff’s complete proposal waits, pending, for you to apply it, edit it or discard it.

The last resort

A race must always be able to run, even if you have done nothing: that is the game’s second pillar. On the eve of the first day of one of your races whose selection is incomplete, time advance stops. The staff then completes the race with the generator, keeping the starters already set, in the staff’s name, with an important message and a journal entry. If nothing can complete it, the race is declared a forfeit.

10

One revision a month, by repair

A programme generated in January is wrong by May: a rider is injured, another is in better form than expected, a dossier has moved. Every month the staff therefore revises the part of the programme it is allowed to touch, in the same way for every team.

When the staff reviseseight times a season
Feb 28First revisionThe last day of the month, as long as a race still starts 15 days later or after.
Mar 31 to Aug 31One a monthAfter your races and the day’s background races, before the move to the next day.
Sep 30Last revisionEight in all. None in the off-season.

Dates from the reference pack’s calendar: the rule is “the last day of the month, from the season’s opening to the last race”.

Why the last day of the month and not the first? A revision placed on the 1st, after the change of day, would make a one-day advance consume two days, lose the important messages of the 1st, and make the order between the revision and a race on the 1st depend on the path taken (watched or delegated). That is the game’s sixth pillar: how you move through time must never change the simulation.

What the revision may not touch

Call J the day after the revision. Frozen: past races, races that have started or finished; those whose first day falls before J + 14 (the race on the fifteenth day stays revisable); all your decisions; the riders of an objective whose preparation has begun, who stay in their race; and the season-level decisions (hierarchy, priorities, objectives, intentions, targets), which the revision never revisits. Nor does the revision read the riders’ progression, only the staff’s dossiers: the fourth pillar applies here too.

Repair, don’t regenerate

The first idea would have been to regenerate the free zone every month. Measured, that changed 7.45 % of the places for no cause at all: a programme that moves for nothing is a programme nobody trusts. So the revision repairs. The zone’s starters are taken back with their roles; a starter who can no longer race leaves and his place is redone; the bounded repairs (young riders, projected overload) do the rest. With no named problem, the revision changes no assignment.

Every move has a cause written in the journal: “unavailable”, “vacant place”, “overload”, “exposure”, or “level”, a pass that swaps a starter when a rider’s dossier has opened an aptitude and score gap that is new since the previous revision. A change with no cause is a defect.

What the staff may propose to you

When the best repair would go through one of your decisions, the staff doesn’t undo it: it proposes it. The list of proposals is closed:

  • a rider you imposed is in projected overload of more than 14 days, and only a race where he is imposed would relieve him: removal from that race, with his replacement;
  • an imposed rider is racing inside the preparation window of one of his A objectives: removal from that race.

A proposal is never applied without you, even when it expires (it expires when the race starts or its premise disappears). You accept it, or you refuse it, and the refusal is remembered: the proposal doesn’t come back this season. Its key is the season, the nature of the problem, the imposed rider and the race, but not the replacement: a refused proposal doesn’t return just because the best replacement has changed. It comes back only if you hand that race or rider back to the staff, if the rider abandons, or if he receives a new objective. An accepted or refused proposal is one more decision, protected like the others.

In “I plan everything”, the revision changes nothing and proposes nothing: it only raises warnings.

A rider gets injured

An injury can’t wait for the end of the month. When a team has a newly injured rider (moderate or severe), he is removed from all his upcoming races that touch his unavailability, 14-day freeze included and even if he was imposed there: it is a fact, not a decision. The generator, in revision mode, then fills the places. In “I plan everything”, the injured rider leaves and nothing comes in: it is the last resort that completes the race on the eve of the start. A simple abandon, on the other hand, makes nobody unavailable.

What you read the following month

Each revision leaves a report in the inbox: every change by the staff with its “why”, the pending proposals with “Accept the swap” and “Refuse”, those that have expired, the season’s refusals and the diagnostics of the moment (overloads, young riders under their minimum, A objectives and their projected preparation). With no proposal, nothing is mandatory: closing the report is enough.

11

What the staff really knows

The generator never reads a rider’s exact attributes: otherwise your staff would be omniscient and the fourth pillar would be a lie. Each team keeps a dossier on each of its riders, that is, estimates. The estimated aptitude for a race is computed on those estimates, with the same calculation the game uses.

  • The start. The content’s ratings, with a persistent bias specific to each team, each rider and each attribute, drawn once and for all (about 3 points on the four qualities measured by tests, 5 on the others). It depends only on the seed and the identifiers: it isn’t even stored in the save.
  • Then, your tests. The four measured qualities (flat, hills, mountain, sprint) follow the power tests the team has filed. With each new test, the dossier moves three eighths of the way toward what the test indicates, from an anchor set at the first test of the effort. A test never fixes a level: a missed window changes nothing, a partial test only updates its own efforts.
  • Nothing else. The dossier reads only the seed, the content and the team’s observations, never an effective rating, a hidden ceiling, the progression or another team’s observations.
Symmetry

The same rules for everyone

Same generator, same targets, same exposure policy, same revision calendar. No rule reads an opposing team’s “Programme” setting, which always plays “The staff plans everything”.

Information

Public only

Of opposing teams you see only what is public: invitations, published starters, past results. None of their programmes.

Determinism

No draw

Ties are settled by identifier. Same inputs, same programme, on any machine.

Concurrency

The career revision

Every mutation increments a counter. A proposal computed on a stale revision is cleanly refused, including after a race, a test or an instruction.

12

Measuring a planner

“The programme is good” isn’t proven by one example. The planning bench plays complete seasons over several seeds and compares two paired arms: G, the world where every team plays the planner; and F(X), the same world except one team X that is put back on the old frozen selection (its best riders everywhere, no objectives, peaks on every race). The ratio of X’s season points in G and in F says what the planner costs, or earns. Eight teams serve as the yardstick: four from the top division, four from the pro division.

What the bench checksthreshold · latest measure (October 2026)
CriterionThresholdMeasure
Peaks: A objectives whose preparation reaches the bandat least 90 %95.6 %
Load: periods of more than 14 days in overloadnone without a warning0
Quality: aptitude gap between an A race’s starters and the seven bestat most 1 point0.62 point
Targets: tier average beyond target plus tolerance (probe on the real calendar, 5 seeds)none0 (31 before)
G season points relative to F85 % (revised on October 6)75.3 %

The last line needs an explanation, because it is the only one that doesn’t pass. It doesn’t say the programme lost points. Here are the cumulative season points of the eight teams before the target fix (section 06) and after:

Season points, sum of the eight teams’ averages16 seeds
ArmPointsTotal
G, before the fix
2,600
F, before the fix
2,917
G, after
2,668
F, after
3,543

G doesn’t drop: it gains 3 %. It is F that rises by 21 %: the other teams now hold their targets and rest their leaders, so the frozen team, which lines up its own everywhere, faces weaker fields.

The ratio therefore measures what the discipline of targets costs against a team that has none, not a drop in the programme. Faced with two conflicting criteria, we made the call: targets take precedence over relative points. The way to bring the ratio back up isn’t a shallower slope, it is a criterion that no longer compares against a team without targets.

On cost, planning is not a bottleneck. When the planner arrived, generating one team’s programme took 2 to 4 ms, all teams’ programmes at career creation 140 to 200 ms, and revising the 36 teams 35 ms on average; the programme views compute in under ten milliseconds.

13

What isn’t right yet

A planner’s numbers are compromises, not truths. Here is what we know we don’t yet do well.

  • The ratio to relative points is 75.3 %, not 85 %. We chose to let targets take precedence. The drop comes from the F yardstick, not from the programme (section 12), but the criterion remains to be rewritten so it no longer compares a team with a version of itself outside the rules.
  • A few individual riders still exceed their target. Tier averages hold, but some top-division lieutenants (from zero to four out of seventy-two, depending on the seed) still go over theirs, by up to twenty-seven days. The generator fills every place that has a candidate: pressure only chooses among them. These cases haven’t been analysed rider by rider yet.
  • One A objective can keep a leader out of another. If an A race falls within the eighteen days before a leader’s objective, he doesn’t race it: that is the price of the reserved window, and the main source of the residual aptitude gaps in an A race.
  • No global solver. Three coordinated moves are out of reach of the repair pass. We prefer a readable season to an optimal one.
  • Some weights are estimates. Real benchmarks support the grand tour leaders and the top-division domestiques; the weight of the other leaders and those of the lower divisions are estimates. The under-23 column is reserved for a content pack that would define that division.
  • You can’t see opposing programmes. That is deliberate (fourth pillar), but it makes reading an opposing calendar harder: you can only guess their leaders from their invitations and published starters.
Bordure · cycling management game · solo offline desktop client Model versions: career state 38 · dossiers 2 · injuries 2