We rebuilt our season table three times. Here is what we learned about fairness.
A form board that rewards recent scoring, tolerates irregular attendance and cannot be gamed by sitting out. The four decisions that took three attempts to get right.
Updated 10 July 2026 · 6 min read · Flagstick team
We run a society on the software we build, which means our season table gets tested by actual members with actual opinions every week. It took three redesigns to arrive at something that survived contact.
Each of the four decisions below is the fix for a specific failure we shipped. They are not the only reasonable answers, but none of them is decoration.
What a form board is for
An Order of Merit measures the whole season. It is cumulative, it rewards a good March in November, and — correctly — it is slow.
A form board measures how you are playing now. It exists so there is always a table a new member can climb, and so the season stays interesting for someone whose Order of Merit position was settled in May.
Both tables, side by side. Different questions, different answers.
Decision 1: scale rounds to an 18-hole equivalent
Raw Stableford is not comparable across round lengths. Our club plays a lot of 9 and 10 hole rounds, where playing to handicap is 18 to 20 points, not 36.
We shipped without scaling. The result: the entire club tied on the same score with “0 of 3 counting”, because the baseline sat above every real score.
The fix is round(points × 18 ÷ holes) — and the trap inside the fix is whose hole count you use. Use the round’s, never the player’s, or a member who walks in after two holes with 6 points scales to 54 and tops the board. Full detail in comparing Stableford across 9, 10 and 18 holes.
Decision 2: the baselines sit in the pool
This is the subtle one, and it is where the first two versions failed.
You need something to fill the gap for a member with fewer than M rounds. The obvious approach is to pad the empty slots with a baseline value B.
That is wrong, and here is why. Take B = 26 and M = 3.
| Rounds played | Padding empty slots | Baselines in the pool |
|---|---|---|
| One round of 22 | 22 + 26 + 26 = 74 | best 3 of {22, 26, 26, 26} = 78 |
| Two rounds: 22, 25 | 22 + 25 + 26 = 73 | best 3 of {22, 25, 26, 26, 26} = 77 |
Under padding, playing a second round of 25 — a perfectly respectable score — lowered the member’s total from 74 to 73. A member who understands the table will therefore sit out to protect their position.
Any table with that property is broken, no matter how sensible it looks on paper.
Putting the baselines into the pool and taking the best M means adding a round can only ever help or do nothing. That is the property you actually need, and it is worth some inelegance to get it.
The baseline is also not just an early-season crutch. It stays in the pool forever, which makes it a permanent floor: one blow-up round can never drag your form score below B. That is what makes it safe to have a bad day.
Decision 3: the window counts rounds played, not weeks
The natural definition of “recent” is calendar-based: your last six weeks.
It excludes the once-a-month member entirely. They can never hold M scores inside a six-week window, so they are permanently at the baseline and permanently bottom.
Counting your last W rounds, however long ago they were, includes everybody. The member who plays weekly has a window covering five weeks; the member who plays monthly has one covering five months. Both are measured on their own recent form, which is what the board claims to measure.
Decision 4: accept that playing can cost you a point
Once your window is full at W rounds, a new round evicts the oldest. If the evicted round was better than the new one, your form score can drop.
This is intended, and it is the honest cost of a decaying measure. In our data it happens on roughly 7% of rounds, and it is usually a point or two.
The temptation is to “fix” it by never evicting — keep the best W rounds ever. Do not. That freezes the board: after a strong month, a member’s form score becomes permanent and the table stops moving, which is the exact thing a form board exists to avoid.
The maths behind the rolling window goes through why every alternative is worse.
What you owe members is the explanation, in the UI, in one sentence: your last five rounds count, so a new round replaces your oldest.
Putting it together
W = form_window_rounds (default 5)
M = form_counting_rounds (default 3)
B = form_baseline_points (default 26)
pool = scaled points from your last W rounds, plus M copies of B
score = sum of the best M values in poolEvery parameter is per-club, because a club playing 30 rounds a season and one playing 8 want different windows.
Showing rank movement honestly
Arrows next to a position are the most-read part of any form board, and the naive implementation is to store yesterday’s rank in a snapshot table.
Recompute instead: run the same calculation as of the day before the last completed round, and compare. It costs a little more work per page load and it means correcting a score three weeks late fixes history rather than leaving a stale snapshot that disagrees with the live table sitting next to it.
How to test a table like this
Two properties, both cheap to assert and both of which caught real bugs for us:
- Brute force it. Write an independent implementation — a naive one, in a different language if you can — and compare on real data.
- Assert monotonicity. Within a fixed window, adding a round must never lower a member’s score. This single property is what the padding-versus-pool decision comes down to, and a test for it would have caught the bug before members did.
Frequently asked questions
- What is a golf form table?
- A form table ranks members on their recent scoring rather than on points accumulated across the season. It exists alongside an Order of Merit so there is always a table that reflects how members are playing now, and one that a new member can climb quickly rather than being permanently behind on accumulated points.
- How do you stop a league table punishing members who play irregularly?
- Define the window as a number of rounds played rather than a number of weeks, so a monthly player is measured over five months and a weekly player over five weeks. Add baseline scores into the pool of counting rounds so that members with few rounds are not stranded, and take the best M from that pool.
- Why should baseline scores go in the pool rather than fill empty slots?
- Because filling empty slots means a below-baseline round replaces a baseline and lowers your total, which gives members a reason to sit out and protect their position. Putting baselines in the pool and taking the best M means adding a round can only ever help or do nothing.
- Should a form table be based on your best rounds ever?
- No. Keeping your best rounds indefinitely freezes the board — once a member posts a strong set, their position stops moving regardless of how they play afterwards. A rolling window means positions keep changing, which is the reason a form table exists alongside a cumulative season table.