Wiki under construction. Many concepts here are from alpha 0.2 and may still change. The wiki will be finalised for version 1.0 — for now it's here to help closed testers and, later, early-access players find their way around. For the most up-to-date and accurate info, join the Discord — that's where changes are announced first and where you can ask directly.

Join the Discord for the latest info

Calendar

The season schedule — 20 Grands Prix, the world circuit pool, circuit contracts and the GP-15 calendar review.

Work in progress. First draft is here, but content may evolve and screenshots are still being added. Spotted something wrong? Tell us on Discord.
On this page

The Calendar app is the season schedule: 20 Grands Prix, the mid-season break weekends between them, and a detail panel for whichever round you select. Behind it sits the world circuit pool — a set of ~50 venues the series draws its calendar from — and a series contract on every round, reviewed at the GP-15 break. This page covers both the screen and the machinery that changes it from one season to the next.


How to open it

  • Sidebar / desk icon “Calendar” — available from any career phase.
  • The Hub’s next-GP widget and the race Debrief both link straight to a circuit profile, which is the same data one level deeper.
  • Esc closes the app. Up / Down move the selection (break rows are skipped).

The round list (left)

23 rows: the 20 rounds plus the three break weekends. Each round row shows the flag of the host country, the round number, the name, the character, the lap length and the lap count.

Row stateAppearance
SelectedDark blue background, white text
Current GPPale blue background, amber in the status column
CompletedGrey text, green
Announced, upcomingNormal beige, alternating rows
Not yet announcedGrey text, name reads TBA

Clicking behaviour is two-stage on purpose. A click on a row that is not selected only moves the selection. A click on the row that is already selected opens its circuit profile. A click directly on the circuit name opens the profile immediately, whatever the selection. The View Circuit button does the same for the selected round. Unannounced rounds have no profile and stay inert.

Announcement

Rounds are confirmed two per pre-season turn (announce_tracks). Each confirmation pushes a news item and a PFS Commission mail carrying the location, length, turn count, lap count and character, plus a headline deal length and — when one exists — the title sponsor’s own agreement. That headline figure in the mail is flavour text; the contract term the GP-15 review actually judges is the round’s own 3–6 season deal (see below).

Title sponsors

A signed sponsor with budget rating ≥ 6 and prominence ≥ 4 can buy the naming rights to a Grand Prix. The assignment prefers a GP whose location or name contains the sponsor’s country of origin; failing that it takes a 50 % chance at a random unsponsored round. The deal runs 5 seasons and the round is then displayed as “{Sponsor} {Grand Prix name}” everywhere. Title backing is negotiated per event — it does not follow a venue that is replaced.


The break rows

Break weekends sit after GP 5, GP 10 and GP 15 (BREAK_GPS). They are amber rows with a - round number, and each has its own label:

AfterRow labelWhat actually happens
GP 5SEASON BREAK — Regulation BreakThe whole next-season regulation package is announced (REGULATION_GPS = [5])
GP 10SEASON BREAK — Driver Contract RenewalsThe mid-season signing window opens for MID_SEASON_TURNS = 3 turns
GP 15SEASON BREAKThe circuit contract review runs (CIRCUIT_REVIEW_GP = 15)

All three breaks also grant bonus Work Units. The GP-15 break is the only one whose headline event is invisible on the row itself — you find out through the inbox.


The track panel (right)

For the selected round:

  • Name (with the title-sponsor prefix if any) and location.
  • Character, colour-coded: High-Speed red, Technical blue, Street olive, Balanced green.
  • Length (km), Turns, Laps, Race distance = length × laps.
  • Status: Completed / Next Race / Upcoming.
  • Three derived characteristics, read straight off the character:
CharacterDownforceTire wearOvertaking
High-SpeedLowLowEasier
TechnicalHighHighDifficult
StreetHighMediumVery Difficult
BalancedMediumMediumModerate

Street circuits exist in the data model but are not drawn by the current generator — a 20-round calendar is 5 High-Speed, 5 Technical and 10 Balanced, shuffled.

Layout preview

The mini-map is generated lazily the first time you look at a round (20 circuit generations at career creation would stall the new-career screen), then cached by circuit_seed, not by round number. That matters: a round can change venue between seasons, and a cache keyed on its position would keep drawing the departed track.

Geometry per character:

CharacterTurnsLength
High-Speed8–115 500–7 000 m
Technical13–154 000–5 000 m
Balanced10–144 500–6 500 m
Street11–144 000–5 500 m

Lap count is one formula everywhere: ceil(300 000 m × race_distance_factor / length). At the default factor of 0.65 a 5 km track runs 39 laps.


The Last Grand Prix panel

Below the progress bar: the P1 / P2 / P3 codes of the previous round and your own team’s best classified finish (Your team: P4, or DNF in red). Results are looked up by round number, not by index into the driver’s finish log — a stand-in who started one race must not have his single result read as round 1.


The circuit pool

The calendar is a subset of the world, not the world itself. CareerSave::circuit_pool holds circuit_pool_size venues (default 50, slider 20–60 in Settings → Career → Balance), hard-capped by what the city database can supply.

How the pool is drawn:

  • Each draw picks a country weighted by GDP², so wealthy nations dominate without shutting the rest out.
  • A top-15 country can host up to 3 GPs (its 1st/2nd/3rd biggest city); the 2nd city’s weight is ×0.30 and the 3rd’s ×0.10.
  • A next-15 country hosts at most 1.
  • A country with several venues gets city-based names (“{City} Grand Prix”); a country with one gets “Grand Prix of {Country}”.
  • circuit_seed is forced unique — no two venues share a layout.

Every venue also rolls facilities, fixed for its life:

RatingRangeMeaning
Infrastructure3–5 ★Grandstands, paddock, access, hospitality
Capacity1–5 ★Crowd size class
Safety1–5 ★Rolled and stored; not yet wired to anything

Capacity stars map to a real total crowd: 5★ = 120–150 k (Silverstone-class), 4★ = 85–120 k, 3★ = 60–85 k, 2★ = 40–60 k, 1★ = 25–40 k. The seated share follows infrastructure, not capacity: 5★ facilities seat 88 % of the crowd, 3★ seat 55 %, 1★ seat 30 %. A huge venue with modest facilities is a huge venue with grass banks.

Drawing the calendar from the pool

The 20 rounds are a weighted sample without replacement, biased by facilities: 5★ ×2.0, 4★ ×1.5, 3★ ×1.0, 2★ ×0.7, 1★ ×0.5. The bias is deliberately gentle — over many draws 5★ venues take roughly 55–85 % of the places, so the field keeps its variety. Each round is signed for 3–6 seasons from the current one, staggered so renewals do not all land in the same year.


The GP-15 renewal review

At the GP-15 break the series looks one season ahead and decides which venues it will not renew. A verdict is announced a full year before it takes effect, and the outgoing venue still races its final season — a contract is honoured to its end.

Who is judged

A round is a candidate only if all of these hold:

  1. It has a contract (contract_seasons > 0) — a pre-0.5.1 save with no contract is skipped until the load-time migration gives it one.
  2. No successor has already been chosen for it.
  3. Its last contracted season is next season.
  4. Its circuit record holds at least 2 races. One race is an accident, not a record.

The score

The review computes the calendar-wide average media rating and average retirements per race across every round that has actually raced, then for each candidate:

media_short = (calendar_media_avg − venue_media_avg) / circuit_media_drop_margin   [default 0.30 ★]
dnf_short   = (venue_dnf_avg − calendar_dnf_avg)     / circuit_dnf_drop_margin     [default 0.80 DNF]
shortfall   = media_short + dnf_short
drop if shortfall >= circuit_drop_threshold                                        [default 1.2]

The sum is signed. Beating the calendar on one axis earns a negative term there, so a dull-but-clean venue and a chaotic-but-thrilling one both buy themselves back to safety. What cannot be saved is a venue poor on both counts, or catastrophic on one — a 1.5★ venue is dropped on the media axis alone even with unremarkable attrition. At the default settings the calendar loses roughly one venue per season; 2.0 makes it rare, 0.5 restless.

The original spec was a hard “fails BOTH margins” test. It never fired: over 8 measured seasons only 9 % of reviewed venues were on the wrong side of both averages at once, because media rating and retirements are near-independent. The combined score with its own threshold replaced it.

Where the media rating comes from

The rating is captured at each race’s debrief and stored per race in the circuit record — the review reads history, it never recomputes. The formula (tv_rating_stars) scores three things:

  • Fight for the win, weight 0.42 — winner’s margin over P2; under 1 s is a photo finish, 25 s is a walkover.
  • Racing behind it, weight 0.38 — overtakes per car, maxing out at 10/car.
  • Drama, weight 0.20 — safety cars, driver mistakes, and attrition on a bell curve: retirements add spectacle up to 22 % of the field, fall away by 60 %, and are penalised outright past 40 %. A grid that destroys itself is a farce, not a classic.

The whole score is divided by Media Severity (Settings → Career → Balance, 0.5–2.0, default 1.0) before the star bands are applied: ≥0.78 = 5★, ≥0.58 = 4★, ≥0.42 = 3★, ≥0.24 = 2★, ≥0.10 = 1★. A competent race is a 3–4★ race by design.

Picking the replacement

Candidates are pool venues that hold no round and are not already promised to another expiring round. Each is scored on its own average media rating; a venue that has never raced scores calendar_average + 0.25, so the calendar keeps rotating in new places. The list is sorted descending and the successor is drawn at random from the top 4 — good, but not deterministic.

The successor’s contract length (3–6 seasons) is rolled at review time and persisted, because the announcement mail quotes it a season in advance and the rollover must apply the same figure.

The announcement mail

From the PFS Commission, category Calendar. It carries:

  • Both figures that decided it, each next to the calendar average it was judged against.
  • The calendar year of the outgoing venue’s last race (not the internal season index).
  • The incoming venue: name, location, length, turns, character — and its drawn layout, rendered from a self-contained @circ turns distance seed marker rather than a round lookup, because the round still belongs to the outgoing venue until the rollover.
  • The explicit note that a dropped venue is not gone for good.

What happens at the rollover

apply_circuit_replacements runs once per season change, and handles two cases for every round whose contract has now run out:

A successor was named. The round keeps its number and its place in the season; the venue behind it changes completely — name, location, turns, length, character, and circuit_seed. Swapping the seed is exactly what makes the departed track keep its own history, lap record and statistics instead of handing them to the newcomer. Laps are recomputed through the shared laps_for_distance; the cached outline is cleared (a stale one would draw the old track under the new name); the title sponsor is dropped; announced resets to false so the round is confirmed again next pre-season.

No successor. The series re-signs the venue for a fresh 3–6 seasons from the current one. Without this its expiry date would stay in the past forever and it would never come up for review again — the calendar would freeze after one round of decisions.

The pass is idempotent: an interrupted rollover cannot rotate venues twice.

Then recompute_circuit_prestige refreshes every pool venue, wholesale rather than incrementally:

prestige (0-100) = 100 × (0.66 × media_avg/5  +  0.34 × min(seasons_hosted, 12)/12)

A venue that has never raced stays at 0 and displays as ”—”: unraced is not the same as bad.


Advanced

  • circuit_seed is the identity of everything. Race history, statistics, the lap record and the circuit profile are all keyed on it. It survives a venue leaving the calendar and coming back years later — which is why a returning track still shows its old races.
  • Read the World Data → Circuits tab alongside this app. It lists the whole pool with each venue’s status (Round N · Ny left or In pool), seasons hosted, average media rating and prestige. That tells you which of your rounds is drifting toward non-renewal before the GP-15 mail.
  • A venue you love can be saved. The score is calendar-relative: if the rest of the calendar puts on worse races, a mediocre venue’s media_short shrinks. There is no absolute bar.
  • Facilities bias which venues get calendar places, not which get dropped. The review never looks at stars; it looks at what happened on track.
  • The five review dials are live sliders (Settings → Career → Balance): Media Severity, Circuit Pool, Circuit Drop: Media ★, Circuit Drop: DNFs, Circuit Drop: Threshold. They read the runtime config.db in the user data directory, not the project copy.
  • Custom (mod-pack) circuits race through the same choke point, build_round_circuit, which resolves a hand-drawn centreline when the round pins one and the procedural seed otherwise. A drawn track’s identity is an FNV hash of its name and geometry, so the same drawn track always keys the same history.
  • A pre-0.5.1 career is migrated at load, not at a season boundary: its 20 calendar venues become the first pool entries verbatim (same seeds), the pool is topped up around them, and contracts are staggered from the current season.

Common mistakes

  • Assuming the calendar is fixed for the career. It was, before 0.5.1. It is not now — plan multi-season car development knowing a round can change character entirely.
  • Reading the GP-15 mail as an immediate change. The venue named still races its entire final season. The swap happens at the following rollover.
  • Ignoring the DNF axis. A venue you race well at can be dropped for being an attrition trap even when its media rating is fine, and vice versa. Both terms are in the same sum.
  • Expecting the announcement mail’s deal length to be the contract the review reads. The mail’s figure is presentation; the round carries its own 3–6 season term.
  • Treating prestige as a live number in season 1. It is recomputed at the rollover; the World Data tab works around this by computing it from the live record, but the stored field on a fresh career is 0 everywhere.
  • Clicking a row expecting the profile. The first click selects; the second (or a click on the name) opens.

See also