Home

PF: Performance Factor database for Australian yacht racing. Imports race results and certificates from SailSys, TopYacht, BWPS, ORC and AMS, optimises a back-calculated Performance Factor per boat, and exposes the data via a set of pages reached from the top navigation:

See Project Description for goals and architecture, and Processing Pipeline for the end-to-end pipeline.

Sharing a view

The Share button at the right of the top navigation copies a link to what you are looking at. On the Boats, Designs, Clubs, Series and Races pages the link keeps the search or filter, the sort column and direction, the filter tickboxes, the open row (with its race or series chart division), the ticked rows, the chart settings and the handicap calculator's allocated handicaps. On Compare Boats and Compare Designs it keeps the boats or designs compared, their chart controls and the calculator's handicaps. Other pages share their address as is.

For example: on Boats, sort by PP descending, click the top boat, then Share — the link opens Boats sorted the same way with that boat's details shown. Opening a link applies its settings once; the settings are then removed from the address bar, so later changes are not undone by a refresh. Links that carry allocated handicaps can be long.

Tasks

Controls data import and processing. Tasks are listed in the order they run during a scheduled run, which matters: analysis requires races to be imported first; reference-factors requires analysis; pf-optimise requires reference factors. Any task can also be run individually on demand. Scheduling is configured by day-of-week and time-of-day, and runs all "in schedule" tasks sequentially.

Task List

The task list shows all available import and processing tasks. Tasks are run in table order during a scheduled run, which is significant: later tasks depend on the output of earlier ones. The full dependency chain is:

sailsys / orc / ams / topyacht / bwps → analysis → reference-factors → build-indexes → pf-optimise

Any task can also be triggered individually. The status column updates in real time during a run. A "Stop schedule" button appears while a schedule is in progress.

Tasks › Task

The task name and run mode: api means the task fetches from an external network source (may be slow or fail if the source is unavailable); run means it computes from data already in the local store (always fast).

Tasks › Status

idle — the task is not running and is ready to start. running — currently executing; logs appear in the server console.

Tasks › Run

Click to run the task immediately, regardless of schedule.

Tasks › Last Run

Local time at which the task last started; — if it has never run.

Tasks › In Schedule

Tick to include this task in the automatic scheduled run. Tasks not ticked are skipped during scheduled runs but can still be triggered manually.

Tasks › On Start

Tick to run this task automatically each time the server starts. Useful for tasks like build-indexes which are fast and keep in-memory state fresh after a restart.

Task: Import SailSys Races

Fetches the SailSys events configured on each club (Clubs → Edit → SailSys events). Imports race metadata, divisions, finishers, elapsed times, and certificates inferred from the handicap used for scoring (handicapCreatedFrom). Supports a local file cache for bulk re-processing without network calls.

Unknown boats are resolved by fuzzy name matching (Jaro-Winkler similarity) or created as new records. The SailSys boat API is called on demand for design information.

Task: Import ORC Certificates

Downloads the ORC Australian certificate feed from data.orc.org. For each certificate, fetches the detail page to extract GPH and converts to TCF via 600/GPH. Detects non-spinnaker (NS), double-handed (DH), and club variants from the CertType and FamilyName fields. Creates or updates Boat, Design, and Certificate records. Idempotent: re-running does not duplicate records.

Task: Import AMS Certificates

Scrapes AMS certificate listings from raceyachts.org. Creates Certificate records with system="AMS". Includes non-spinnaker and two-handed variants.

Task: Import TopYacht Races

Scrapes race results from TopYacht club result pages listed in clubs.yaml. Parses group captions to detect handicap system and variant flags — for example, a caption of "Div 1 ORC NS WL results" sets system=ORC, nonSpinnaker=true, windwardLeeward=true. Multi-page results (same race, multiple handicap systems) are merged into a single Race record with multiple divisions. PHS handicap values are excluded; only elapsed times are kept from PHS divisions.

Task: Import BWPS Races

Imports BlueSail Worldwide Performance System race results from the Cruising Yacht Club of Australia. IRC-based races providing elapsed times and the AHC used for scoring.

Task: Analyse Certificates

Builds the ConversionGraph — a network of empirical linear fits between handicap systems, years, and variants. For each boat holding certificates in two different (system, year, variant) combinations, the pair of TCF values contributes one observation. Observations are grouped by pair type and a weighted linear regression is fitted. Edges with R² < 0.75 are discarded. The resulting graph enables conversion between any two connected nodes via shortest weighted path.

Task: Calculate Reference Factors

Traverses the ConversionGraph (DFS) from each boat's certificates toward the target IRC node, computing an IRC-equivalent Reference Factor. Three variants (spin, nonSpin, twoHanded) are computed independently. After certificate-based factors are assigned, the task iterates: design-level aggregation and race co-participation propagation extend coverage to boats without direct certificates, up to 20 iterations or until no new factors are produced.

Task: Build Indexes

Rebuilds the in-memory navigation indexes: boatId → race IDs, designId → boat IDs, seriesId → boat IDs. These indexes are volatile (lost on server restart) and must be rebuilt after any import that adds new boats or races. The task is fast (<1 second) and is typically ticked "on start".

Task: PF Optimise

Runs the Alternating Least Squares (ALS) optimisation to produce Performance Factors for all boats in the database. The optimisation solves jointly for:

A regularisation term (controlled by λ) pulls each boat's PF toward its Reference Factor, weighted by RF confidence. The outer loop recomputes entry weights from residuals (outlier down-weighting) and re-runs the inner ALS until weights stabilise. See Processing Pipeline steps 13–19 for the full mathematical description.

Task: Save Database

Flushes the data store to disk, rewrites admin.yaml, and prunes the user requests log.

Task: Clear ORC Cache

Deletes the cached ORC downloads (cache/orc), so the next ORC import fetches everything afresh.

Task: Clear SailSys Cache

Deletes the cached SailSys responses (cache/sailsys) — including cached errors, which otherwise keep a series from being fetched again.

Schedule & Configuration

Schedule Days

Days of the week on which the scheduled run executes. Multiple days can be selected. No days selected = schedule disabled. Saturday/Sunday night runs (e.g. 03:00 Sunday) are typical for low-traffic windows after weekend racing.

Schedule Time

Time of day (server local time) at which the scheduled run begins. All "in schedule" tasks run sequentially from this start time. A full run including network imports and optimisation typically takes 5–30 minutes depending on dataset size and network speed.

Target IRC Year

The IRC certificate year used as the target node in the ConversionGraph — all Reference Factors are expressed as IRC-equivalent TCF for this year. Leave blank to auto-detect from the most recently issued IRC certificates in the database. Set explicitly when fresh IRC data has not yet been imported but you want to lock to the current year, or when testing with historical data.

PF Parameters

These parameters control the ALS optimisation algorithm. Changes take effect on the next run of the pf-optimise task. The PF Run Quality panel on the Analysis page shows whether the current settings achieve convergence and what fit quality results.

Lambda (Regularisation)

The regularisation strength λ controls how strongly each boat's PF is pulled toward its Reference Factor. The per-boat pull is weighted by that boat's RF confidence weight, so well-certificated boats are anchored more tightly than those relying on propagated factors.

Convergence Threshold

Inner loop convergence criterion. The ALS inner loop stops when the maximum change in any log(PF) across a single iteration falls below this value. Default ~0.0001. Smaller = tighter solution but more iterations per outer cycle. Increase if inner convergence is very slow; decrease for maximum precision.

Max Inner Iterations

Maximum number of ALS iterations (alternating T₀ solve then PF solve) per outer reweighting cycle. Increase if the quality report shows "inner loop did not converge". Typical convergence occurs within 20–50 iterations for well-conditioned problems.

Max Outer Iterations

Maximum number of outlier reweighting cycles. Each outer cycle: recomputes entry weights from current residuals, then re-runs the inner ALS to convergence. Typically 3–5 outer iterations suffice. Increase if the quality report shows "outer loop did not converge".

Outlier K (IQR Multiplier)

Controls the aggressiveness of outlier down-weighting via a Cauchy weight function. An entry with residual magnitude greater than k × IQR is treated as an outlier and assigned reduced weight (but never excluded entirely). Default ~2.0. Lower = more aggressive suppression (useful for noisy datasets); higher = more permissive (useful when the fleet is homogeneous and outliers are genuine).

Asymmetry Factor

Extra penalty multiplier applied to entries where the boat finished faster than the model predicts (negative residuals). Reflects the asymmetry principle: it is essentially impossible for a boat to genuinely sail faster than its potential in a small fleet; an apparently outstanding result is more likely to reflect poor performance by the rest of the fleet or a favourable weather/tide gate.

Default ~1.5 means unexpectedly fast entries are down-weighted 1.5× harder than equivalently slow entries. Higher values are more conservative about crediting apparently outstanding performances.

Outer Damping Factor

Blend fraction for weight updates between outer reweighting cycles (0–1). The updated weight is a blend of the previous weight and the weight recomputed from current residuals: new_weight = damping × computed + (1 − damping) × old. Lower values damp oscillation at the cost of slower convergence. Default 0.5. Set to 1.0 for no damping (may oscillate on poorly-conditioned problems).

Age Half-life (years)

Older results count less when fitting a boat's PF and when propagating an RF from races. A result counts 0.5^(age / half-life), where its age is measured back from the boat's own most recent race in that variant — not from today — so a boat that has not raced for some years keeps its last results at full weight rather than fading to nothing.

With the default of 2 years, a result 2 years older than the boat's latest counts half, 4 years older a quarter, and 5 years older about 0.18. The PF is meant for setting a season's initial handicaps, so it deliberately reflects a boat's established capability rather than its latest form: after a long break, a boat's first few new results move its PF only gradually (about a season of new racing to outweigh a full old season). A boat that was materially changed is better split deliberately (an alias or design override with dates) than chased by a shorter half-life.

Only each boat's own PF update and its PF confidence are decayed — not the division par times (T₀), since each boat's decay depends on its own latest race. Decay also means fewer effective results per boat, so PFs carry slightly more noise. 0 turns age decay off.

Outer Convergence Threshold

Outer loop convergence criterion — maximum allowed change in any entry weight between consecutive outer cycles. Default 0.01. Increase (e.g. to 0.3) if the outer loop consistently fails to converge within the allowed iterations; this trades precision for tractability. Decrease for tighter convergence at the cost of more outer cycles.

Outer PF Convergence Threshold

The outer loop also stops when the largest change in any boat's log PF between cycles is below this. PFs are the optimiser's actual output, so converging on PF stability is at least as meaningful as converging on weight stability — in practice, with damping, the weight change rarely falls below its own threshold and this is what ends the run. Default 0.001; typical range 0.0001–0.05.

Log Outer Diagnostics

When enabled, each outer cycle logs the five results whose weights changed most and the five boats whose PFs moved most — useful for diagnosing a run that keeps cycling without settling. Off by default; turn it on for one run and off again.

Dubious Factor

A boat whose PF is above this begins a linear ramp of its results' weights towards zero, so very fast boats (which sit at the tail of the handicap range and distort the analysis) count for less. Default 1.5.

Max Factor

A boat whose PF is at or above this gets zero weight on its results, excluding it from the analysis entirely. Must be greater than the Dubious Factor; between the two, weights ramp linearly. Default 2.0.

Analysis

Visualises the empirical conversion network between handicap systems (IRC, ORC, AMS) across years and variants. Each edge represents a linear regression computed from boats holding certificates in both systems. Click an edge to see the scatter plot and a conversion lookup table. The PF Run Quality panel appears here after the optimiser has run.

Handicap Conversion Network

A graph visualising the empirical linear relationships between handicap systems (IRC, ORC, AMS) across years and variants. Each node represents one (system, year, variant) combination — for example "IRC spin 2024" or "ORC NS 2023". Each edge is a linear fit computed from boats that hold certificates in both endpoint systems.

Edge colour intensity reflects R² — darker edges have stronger fits with more predictive power. Hover over an edge to see the R², sample count, and conversion slope. Click an edge to load the scatter plot and conversion table for that pair.

The network is built by the analysis task. A minimum R² of 0.75 is required for an edge to be included. Year-to-year edges within the same system capture IRC certificate reissue inflation across seasons.

Analysis Scatter Plot

Scatter plot of paired handicap observations for the conversion selected in the dropdown (e.g. "IRC spin 2024 → ORC spin 2024"). Each point is one boat with certificates in both systems. The regression line shows the best-fit linear conversion; points beyond 2.5σ are excluded from the fit (but still plotted). The optional "Error band" checkbox shows a ±1σ envelope around the regression line.

A tight cluster near the regression line indicates a reliable conversion — these two systems track each other closely. A wide scatter indicates poor inter-system agreement and the resulting edge will have lower weight in the ConversionGraph.

Conversion Table

A lookup table applying the fitted linear conversion over a configurable range of input values. Set the Min, Max, and Step values, then click Update to regenerate. Useful for manually converting a known handicap from one system to another, or for sanity-checking that the fitted conversion is sensible at the extremes.

Conversion Table › x

Input value in the source handicap system (e.g. IRC TCF). Varies from Min to Max in steps of Step.

Conversion Table › Predicted y

Predicted output value in the target handicap system via the fitted linear conversion y = a·x + b.

Conversion Table › Weight

A proportional bar showing the effective density of training observations near this x value. Values near the centre of the training range have high weight; values at the extremes (extrapolations) have lower weight and should be treated with more caution.

PF Run Quality

Summary statistics from the most recent PF optimisation run, displayed on the Analysis page. These help assess whether the current configuration is appropriate and whether the results can be trusted. All statistics are from the last completed run of pf-optimise.

Convergence

Whether both the inner ALS loop and the outer reweighting loop converged within their allowed iteration limits. Non-convergence means the solution may be suboptimal:

Scale

The number of boats, race divisions, and individual race entries used in the optimisation. Larger numbers generally mean more reliable results. If the counts are much lower than expected, check that build-indexes has run after the most recent import.

Fit Quality

Median absolute residual and spread (IQR of residuals) across all race entries. Residuals are in log space; a median absolute residual of 0.02 means the typical entry's elapsed time differs from the model by about 2%. Lower values indicate a better fit. High spread suggests either highly variable race conditions or a dataset with many outlier races.

Outliers

The number of entries assigned reduced weight due to large residuals, and the number of race divisions with high internal spread (IQR/T₀ above threshold). These are down-weighted rather than excluded, so they still contribute to the optimisation but with less influence. A high outlier count may indicate noisy source data or an Outlier K setting that is too permissive.

Confidence

Median boat confidence score across all boats in the optimisation, reflecting the quantity and quality of race data per boat. A score near 1.0 means most boats have well-supported PF estimates; a low median score means many boats have few races or highly variable results. Individual boat confidence scores are shown in the PF Detail table.

Clubs

Sailing clubs from which data has been imported. The club ID is the club's website domain, chosen because it is stable and unique. Click the race count to filter the Races tab to that club's races.

Clubs › ID

Website domain (e.g. myc.com.au, cyca.com.au). Used as the stable identifier and as the prefix in race IDs.

Clubs › Short Name

Abbreviation used in result headers and source data (e.g. MYC, CYCA, RBYC).

Clubs › Full Name

The club's full official name.

Clubs › State

Australian state or territory: NSW, VIC, QLD, WA, SA, ACT, TAS, or NT.

Clubs › Boats

Number of boats in the database whose home club is this club. Click to filter the Boats tab to show only those boats.

Clubs › Series

Number of series run by this club. Click to show them in the Series table.

Clubs › Races

Total races imported from this club. Click to filter the Races tab.

Clubs › Excluded

Excluded clubs are hidden from analysis. Individual races from an excluded club can still be included if explicitly unexcluded.

Boats

The Boats top-level page has two modes selected from the nav dropdown: Browse lists all boats with sortable columns and a detail drawer per row; Compare plots back-calculated factor over time for one or more selected boats and offers a multi-boat handicap calculator.

Browse

Lists all boats in the database. Boats are identified by sail number and name; because neither is guaranteed unique, two source records for the same physical boat may appear as separate rows. Use the merge function (checkboxes → merge) to consolidate them.

The RF and PF columns are colour-coded: green indicates high confidence (weight close to 1.0), red indicates low confidence. A dash (—) means no value has been computed for this variant.

Boats › ID

A unique stable identifier constructed from the normalised sail number, boat name, and design ID. The format is sailnum-name-designid (e.g. AUS1234-raging-tp52). IDs are never derived from SailSys or TopYacht internal IDs, which are stored only in alias tables for ingestion purposes.

Boats › Sail Number

The sail number as recorded in the primary source. Country prefixes (e.g. AUS, GBR) are preserved. Sail numbers are not unique — different boats may share the same number, and the same boat may have its number recorded differently across sources.

Boats › Name

Boat name from the primary source. Aliases and name variations are reconciled during import using configurable fuzzy-matching; the canonical name shown here is whichever was first recorded or promoted by an admin merge.

Boats › Design

The design (class) ID linking this boat to a Design record. Derived from the ORC Class field where available, or from the SailSys make/model fields otherwise. Click to see the associated design record in the Designs tab.

Boats › Reference Factor (RF)

The IRC-equivalent handicap derived from this boat's measurement certificates (IRC, ORC, AMS) via the conversion network. Three variants are computed independently: spinnaker (spin), non-spinnaker (NS), and two-handed. The value shown in the table is the spin variant; the full breakdown is in the boat detail panel.

Weight reflects confidence: 1.0 = derived directly from a certificate in the target year; lower = inferred via multi-hop conversion, design-level aggregation, or race co-participation propagation. See the colour scale: green = weight close to 1.0, red = low weight.

Boats › PF

The Performance Factor — the back-calculated handicap from the ALS optimisation averaged over all recorded race entries for this boat. The weight reflects the quantity and quality of contributing races; a boat with few races or highly variable results will have low PF weight. Colour scale matches RF.

Boats › Overall (Performance Profile Score)

The normalised area of the performance profile pentagon — a single number in [0, 1] summarising how the boat compares to the active fleet across five dimensions over the last 12 months. A score of 1.0 would mean the boat ranks first in the fleet on every spoke simultaneously; 0.0 means last on every spoke. In practice most boats sit between 0.1 and 0.5. Click the boat row to see the full pentagon chart and per-spoke details. See Performance Profile for spoke definitions.

Only boats with at least 3 distinct races in the last 12 months receive a profile score. Boats with fewer races are excluded from the ranking pool entirely, so the score reflects only the regularly active fleet.

Boats › Club

The home club identifier (website domain). A boat may be associated with multiple clubs across different source systems; the value shown is the primary club from the most authoritative source.

Boats › Finishes

Total race finishes recorded in the database across all clubs and series. Click the number to switch to the Races tab filtered to show only races for this boat.

Boats › Excluded

Tick to exclude this boat from all analysis, charts, and PF calculations. Use for test entries, ghost boats, or data errors. Excluded boats are still visible in the data browser (greyed out) unless "Show excluded" is unticked.

Reference Factors Table

Click any boat row to expand the detail panel. Below the JSON record, two tables are shown: Reference Factors and PF Detail.

The Reference Factors table shows the IRC-equivalent Reference Factor for each handicap variant (Spin, Non-Spin, Two-Handed), alongside the confidence weight and the generation (number of propagation hops from a direct certificate). These are the anchor values fed into the PF optimiser.

Reference Factors › Variant

Spin (with spinnaker), Non-Spin, or Two-Handed. Each variant is computed independently because ORC, AMS, and IRC all issue separate certificates for different sailing configurations.

Reference Factors › Value

IRC-equivalent TCF (Time Correction Factor) for this variant, converted to the target IRC year via the empirical conversion network. A value of 1.000 represents the hypothetical reference boat.

Reference Factors › Weight

Confidence weight for this factor, between 0 and 1. The weight starts at 1.0 for a direct certificate in the target year and degrades through each source of uncertainty:

Source Weight
Direct certificate, target year 1.00 (base)
ORC club certificate × 0.90
Windward/leeward cert (ORC WL) × 0.80
Design-level aggregate (step 12) × 0.85 (max)
Race co-participation propagation × 0.70 (max)
Design combination (step 13) natural blend — high agreement → higher combined weight
Each year from target (certificate age) × 0.80 per year
Each ConversionGraph hop × edge weight (R²-derived)

The weight is treated as inversely proportional to variance in log space. See Error Bars for the full derivation.

PF Detail › Gen

Generation: how many propagation or combination steps removed from a direct certificate. Generation 0 = direct certificate (or one-hop graph conversion from a direct certificate). Generation 1+ = race co-participation propagation, design combination, or cross-variant derivation; each step increments the generation by 1. Higher generations carry more uncertainty and lower weights.

PF Detail Table

Shows the optimised Performance Factor for each variant alongside the corresponding Reference Factor, for easy comparison. The columns mirror the PF summary on the Boat Comparison page.

PF Detail › Variant

Spin, Non-Spin, or Two-Handed — matching the RF variant. PF is computed separately for each variant using only races run under that handicap configuration.

PF Detail › RF

The Reference Factor for this variant — the certificate-derived anchor value. See Reference Factors › Value.

PF Detail › PF

The Performance Factor — the back-calculated handicap from the ALS optimisation. A value close to RF means the boat's race history is consistent with its measurement certificate. A persistent gap may indicate the certificate is stale, the boat has been modified, or the fleet it races against has systematically drifted.

PF Detail › PF Weight

Confidence weight for the PF estimate, derived from the number and quality of contributing race entries. More races and more consistent results yield higher weight.

PF Detail › Delta

PF minus RF in the same units. Near zero = race history is consistent with the certificate. Positive delta = the boat races faster than its certificate predicts (PF > RF). Negative delta = it races slower (PF < RF). Large deltas on high-weight boats are worth investigating.

PF Detail › Races

Number of race division entries contributing to this PF estimate. More races generally means higher confidence, but consistency across races matters more than sheer count.

Performance Profile

A pentagon radar chart showing how this boat compares to the active fleet across five fleet-relative percentile scores, each computed from the last 12 months of race data. Each spoke ranges from 0 (worst in fleet) to 1 (best in fleet), where rank is relative to all boats with at least 3 distinct recent races. The overall score shown below the chart is the normalised polygon area of the pentagon (see Boats › Overall).

The five spokes, in pentagon order:

Spoke What it measures How it is scored
Frequency How much time the boat spends racing, and how broadly across the year Percentile rank of a duration-weighted race count multiplied by a small year-spread bonus. Each distinct race contributes (race duration / fleet-median duration)α, where α ≈ 0.26 (a race twice as long counts 1.2× more). The total is then multiplied by 0.85 + 0.15 × min(months_active, 12) / 12, so a boat racing in 1 month gets ≈ 0.86 and a boat racing every month gets 1.0. The bonus is deliberately small so duration-weighted race count remains the dominant contribution. Minimum 3 distinct races required to appear in the fleet ranking at all.
Consistency How tightly the residuals cluster around zero (with extra weight on fast surprises) Percentile rank of the asymmetrically weighted mean squared residual across recent race entries (lower = better). Every race counts equally regardless of outlier status, so a boat with large residuals is correctly penalised even if those races were down-weighted in the PF optimiser.

Asymmetric weighting: negative residuals (boat faster than its PF predicted) are weighted 1.5× more than positive residuals (slower) of the same magnitude. A fast surprise suggests untapped potential and a genuinely inconsistent boat, whereas slow days are more often explained by gear, tactics or a single bad start.

Discards: similar to series scoring, a configurable number of most-divergent results are excluded before computing the mean. One additional result is dropped for every N distinct races sailed (default N = 11), so a boat with 11 recent races gets 1 discard, 22 races gets 2, and so on. This rewards boats with a long track record by forgiving occasional bad days.
Diversity How broadly and how often the boat races against varied opposition Percentile rank of a variant-weighted Σ(√encounters) score. For each distinct (opponent, variant) pair encountered in recent races, the contribution is variant_weight × √(encounters), with variant weights Non-spin = 0.8, Spin = 1.0, Two-handed = 1.2 (configurable). The square root damps repeats so distinct opposition still dominates, but a boat that frequently races a diverse field scores higher than one with the same breadth of opposition met only once or twice. The same opponent met in two different variants counts as two pairs.
Chaotic Whether a boat's errors come in disorderly races (the rest of the fleet also strayed from its handicaps — excusable) or orderly ones (the rest of the fleet finished close to its handicaps — its own) — the pattern of its errors, independent of their size Percentile rank of the orderly-race share of error: the boat's mean squared residual with each race weighted by 1 / (spread of the other boats in its division), divided by its plain mean squared residual (lower = better), shrunk towards the fleet median for small samples. Independent of Consistency, so a consistent boat's one blunder in an orderly race counts heavily. Boats with fewer than 5 races in divisions of 4+ boats score 0. See Performance Profile.
Stability Whether the boat's trend is level or declining Percentile rank of an asymmetric slope penalty from a weighted linear regression of residuals against race date. A level trend (slope ≈ 0) incurs no penalty and ranks best. An improving trend (negative slope — boat getting faster relative to the fleet) incurs half the penalty of an equivalent declining trend. A declining trend (positive slope — boat getting slower) is penalised most heavily, since it suggests the current PF may already be stale.

The polygon area formula normalises the area so that a perfect pentagon (all spokes = 1) gives an overall score of 1.0 and a degenerate case (any spoke = 0) collapses the adjacent triangles, reducing the score.

Per-Race Residuals Chart

Scatter plot of per-race residuals in log space over time. The residual for one race entry is:

residual = log(elapsed × PF) − log(T₀)

A positive value means the boat finished slower than the fitted model predicted; negative means faster. Points near zero indicate races where the boat performed close to its PF. Colour intensity reflects the entry weight used in the optimiser — faint points are outliers that were down-weighted and contribute little to the PF estimate. A systematic trend (residuals growing more positive over time) may indicate the boat is slowing relative to the fleet.

Compare

Select one or more boats and plot their back-calculated per-race factors over time on a single chart. Useful for comparing how two or more boats have performed relative to each other historically, or for checking whether a boat's factor is trending.

A handicap calculator is provided that uses the RF and PF for all the compared boats to scale a handicap allocated to one boat to the others.

Back-Calculated Factor Comparison Chart

Scatter plot showing the back-calculated factor for each selected boat over time. Each point is one race result — the handicap that boat would have needed to be equal-corrected-time with a 1.000 reference boat in that specific race. Hover over a point for race details (date, club, division, elapsed time).

The Trend selector adds one trend line per boat to help identify patterns:

Both trend lines follow the chart's divisor when a PF, RF or allocated-set column is ticked in the handicap calculator. Hover over a trend line to highlight that boat's points.

Optimise — available when an allocated-set column is ticked as the divisor and at least two boats have a trend line. Each boat's line level is its average over the period shown (the midpoint of the linear trend, or the mean of the average). Dividing by the allocated handicaps makes each level scale as 1/handicap, so the button adjusts that set — by the smallest relative change to the handicaps — until every boat's line has the same level, then redraws. The note beside the button says how many handicaps changed and by how much at most. A linear trend can only be scaled, not tilted, so lines with different slopes will still cross. There is no undo other than Clear all or reloading your handicap file, so download the set first if you want to keep it.

The Variant selector controls which handicap configuration's data is shown. The "All available" checkbox toggles whether the boat selector shows all boats or only boats that have raced with every boat currently in the comparison.

Handicap Calculator

Enter a handicap for one boat or design; the others are automatically scaled by PF (or RF) ratio. On the Boat Comparison page, the suggested handicap for boat B given a known handicap for boat A is:

handicap_B = handicap_A × PF_B / PF_A

On the Design Comparison page, two suggestions are shown:

Each allocated-handicap column has − / + buttons that scale all its handicaps by 1%, keeping the ratios between them. With two or more columns, Equalise scales each column the same way so its average equals the ticked column's (the first column's, if none is ticked) — averaged over the boats shown that have a value in both — so sets from different sources can be compared on the same level.

Loading Handicaps from a File

Load handicaps from file fills the calculator's input column from a JSON file. The file is a JSON array of objects, one per boat (or design). Each object needs at least one way to identify the boat, and usually a handicap:

Field Required Meaning
handicap optional The allocated handicap as a TCF (time-correction factor), roughly 0.1–2.0. A row without one (or null) still matches its boat but applies no value.
boatId preferred The canonical boat id. Files exported from this app carry it, so they reload exactly.
sailno — Sail number (e.g. "AUS1234"); prefixes and leading zeros are normalised on match.
name — Boat name.
division optional Division/class name; used only to break ties between same-sail-number boats.
variant optional "spin", "nonSpin", or "twoHanded". See On Import.

Rows are matched to the boats in the table in this order of confidence, each boat used at most once: boatId → sailno + name → sailno + division → sailno alone → name alone.

Files produced by Download handicaps as JSON contain {boatId, sailno, name, handicap, variant} for each entered boat and round-trip cleanly. A minimal hand-written file only needs a handicap plus a sail number or name:

[
  {
    "boatId": "aus1234-x7",
    "sailno": "AUS1234",
    "name": "Windfall",
    "handicap": 1.083,
    "variant": "spin"
  },
  {
    "sailno": "SM77",
    "name": "Blue Streak",
    "handicap": 0.975
  },
  {
    "name": "Second Wind",
    "handicap": 1.012,
    "variant": "nonSpin"
  }
]

Loading boats, not just handicaps (Compare Boats only). If the Compare Boats table is empty when you load a file, its boats are added to the comparison, then any handicaps are applied. A row with a boatId adds that boat; a row with only a sailno and/or name is looked up — sail number and name, then sail number alone, then name alone, each of which must match exactly one boat. Rows that match no boat (or more than one) are listed as "not found" in the status line. So a file without handicaps is a quick way to load a set of boats. Once the table has boats, a file only matches into them, as on the race and series pages, which never add boats from a file.

variant accepts the usual spellings — nonspin, NS, Non-Spinnaker, 2H, double handed and so on — as well as spin, nonSpin and twoHanded.

[
  { "boatId": "aus1234-x7" },
  { "boatId": "sm77-bluestreak" }
]

After a load, the status line reports how many entries were read, how many boats matched, and how many handicaps were applied — so a file whose boats aren't in the current table, or that carries no handicap values, is easy to spot.

On Import (variant handling)

Controls what happens when a loaded row's variant (Spin / Non-Spin / Two-Handed) differs from the variant currently selected for that boat in the table. It has no effect on rows that carry no variant, or whose variant already matches.

Source Variant

Lets you override the variant of every loaded row before the On Import rule is applied.

Designs

The Designs top-level page has two modes selected from the nav dropdown: Browse lists all designs with their design-level reference factor; Compare scatter-plots two design classes against each other across shared race divisions.

Browse

Groups boats by design class. The design-level RF is a weighted aggregate of individual boat RFs, with a 0.85 design-level discount applied to reflect the additional uncertainty of inferring performance from class-level rather than individual boat certificates. Design-level factors are used as fallback anchors for boats in the same class that lack individual certificates.

Designs › ID

Normalised design name used as the primary key (e.g. j24, farr40). Derived from the ORC Class field where available. Normalisation strips spaces, punctuation, and case differences.

Designs › Canonical Name

The design name used in all reports and charts — typically the ORC class name or the most common name found across source systems.

Designs › Reference Factor (RF)

Design-level IRC-equivalent RF aggregated across all certificated boats of this class. See Boats › RF for weight interpretation. A design RF is only as reliable as the certificate data available for boats of this class.

Designs › RF Spin / RF No-Spin / RF 2-Handed

The design RF for each variant, on the target-year IRC scale. Colour shows confidence: green high, red low. — means no boat of the design has a factor for that variant.

Designs › Ignored

The design is a nonsense one (e.g. "yacht" or "d1") and is treated as if there was no design.

Designs › Custom

The design includes a "custom" or "modified" in the name, so no attempt is made to assign a design RF.

Designs › Boats

Number of boats of this design in the database. Click to filter the Boats tab to show only boats of this class.

Designs › Excluded

Excluded designs are hidden from analysis and charts. All boats of an excluded design are effectively excluded as well, unless individually overridden.

Compare

Select two design classes and compare their corrected elapsed times across shared race divisions. Each shared division provides a direct A-vs-B comparison under identical conditions. A best-fit line close to the RF-ratio reference line indicates good agreement between the theoretical conversion (from certificates) and the empirical result.

A handicap calculator (see Handicap Calculator) provides both RF-ratio and best-fit-based handicap conversion from one design to the other.

Design Comparison Chart

Scatter plot comparing the corrected elapsed times of two design classes across shared race divisions — divisions where at least one boat from each class competed on the same day and course. Blue = Design A, amber = Design B.

The x-axis is the boat's PF (or RF if PF is not yet available); the y-axis is corrected elapsed time in minutes. Two reference lines are shown:

A good comparison for handicap cross-referencing shows two tight clusters that overlap in the corrected-time dimension, with a best-fit line close to the RF projection. Divergence may indicate one design systematically out- or under-performs its certificate in the conditions typical of the shared races.

Series

Individual race series imported from SailSys, TopYacht, and BWPS. A single series may have multiple races.

Series › Club

The club that ran the series. Click to filter the Series table by this club.

Series › Name

The series name, as given by the source.

Series › Type

Spin, NS, 2H, Mixed or unknown. The type overrides each entry's own variant:

Boats of a no-spinnaker design are always NS, whatever the series type. Italic means the type was guessed from the series name rather than set (Edit the series to set it). When filtering for Unknown, the bracket shows what the entries actually are.

Series › First / Last

Dates of the first and last races in the series.

Series › Races

Number of races in the series. Click to show them in the Races table.

Series Chart › Linear trend and Optimise

Linear trend adds a least-squares trend line for every race line shown, fading the race lines so the trends stand out. A line under the chart title gives each dataset's weighted average trend slope — each race weighted by its number of boats. A slope near 0 means corrected time does not drift with boat speed: the handicaps treat fast and slow boats alike.

Optimise — available when an allocated-set column is ticked (and the x-axis is not the allocated handicap itself). The weighted average slope is a linear function of the handicaps, so the button adjusts that set, by the smallest relative change to the handicaps, until it is 0, then redraws. Only boats in the races and divisions shown are changed. As with Optimise on Compare Boats, there is no undo other than Clear all or reloading your handicap file.

Races

Individual race results imported from SailSys, TopYacht, and BWPS. A single race may have multiple divisions (different handicap systems or fleet splits for the same start). Click a race row to see the full JSON record and the division chart.

Races › ID

Unique race identifier: clubDomain–date–nnnn (e.g. myc.com.au-2024-11-06-0001). The four-digit suffix distinguishes multiple races at the same club on the same date. IDs are never reused and are independent of source system internal IDs.

Races › Club

The club that ran this race. Click to filter the Races tab by this club.

Races › Date

Race date in ISO format (YYYY-MM-DD).

Races › Series

The series this race belongs to (e.g. Wednesday Night Racing, Autumn Series). Click to filter the Races tab to all races in this series — useful for browsing a season's results or navigating prev/next within a series.

Races › Race Name

The race name or number within its series as recorded in the source system (e.g. "Race 3", "November 6").

Races › Finishers

Total finishers across all divisions in this race.

Races › Excluded

Excluded races are not used in PF calculations. Individual races can be excluded where results are known to be unreliable (e.g. abandoned race, severe weather split affecting only part of the fleet).

Races › Same race imported more than once

The same physical race is often imported several times: scored in two series (club championship and pointscore, a female-helm subset of a twilight), under two clubs (a combined clubs series), or from both SailSys and TopYacht. Two races on the same day are treated as copies when they share at least two boats and at least 90% of those have identical elapsed times, to the second.

Each boat's result then counts once: in the copy where its division has the most finishers. In the other copies it is reference-only — it still helps set that division's reference time, so a boat that is only in the smaller copy is measured against the boats it raced, but it does not count again in the boat's PF, confidence, race count, performance profile or comparison charts. The race chart shows "Same race as …" with links to the other copies.

If the copies disagree on a boat's variant (spin / non-spinnaker / two-handed):

Race Division Chart

Shows the elapsed time and corrected times for each finisher in the selected division, plotted against their PF on the x-axis. Three lines are shown:

A flat corrected-time line confirms the factor was appropriate for this race. A sloping line indicates the faster or slower boats systematically out- or under-performed their factor — possibly due to conditions favouring one end of the fleet, or an outlier performance.

Error bars on the corrected lines (enable with the "Error bars" checkbox) show ±95% confidence intervals derived from the RF weight. See Error Bars for the math.

Invert axes (ticked by default, on both the race and series charts) reverses both axes, so faster boats are on the right and better (shorter) times are at the top. Untick it for the conventional orientation; the choice is remembered for the session and kept in share links.

Division Charts › X-axis

The race, series and Compare Boats division charts place each boat at 1/factor across the chart, so faster boats are on the left. The X-axis selector picks the factor:

Concepts

Speed Factor

A speed factor is the inverse of a time-correction factor: 1 / factor. Where the factor multiplies elapsed time to give corrected time (so a fast boat needs a smaller factor), the speed factor scales like a rate — higher = faster.

Charts in the app that plot results against a boat's handicap use the speed factor on the x-axis (1/PF, 1/RF, or 1/Allocated Handicap). Plotting against 1/factor rather than the factor itself has two benefits:

The corrected-time line is flat when the factor is right for the race; tilt indicates the faster or slower end of the fleet systematically out- or under-performed their handicap.

See Factor Design — Time vs Speed Correction Factors for the underlying definitions and arithmetic.