FSDB competition database
FS 2018+ · Airscore We-Fly

Interactive specification

One file, a whole competition.

FSDB is the XML database FS and Airscore write: every task of a comp, its turnpoints, its start gates and — in a scored file — every pilot's result. This page covers the half that defines the flying, and the part that trips up every importer: working out which turnpoint is the start, the end of the speed section, and the goal.

XML, UTF-8 Many tasks per file 1-based turnpoint indices ISO datetimes with offset
01 Overview

What an FSDB holds

FSDB — "FS database" — is the native file of FS (the long-standing hang-gliding and paragliding competition scoring suite) and of Airscore, its open-source successor. Unlike every other task format, one .fsdb is not one task: it is an entire competition — its identity, its dates, all of its tasks, and in a scored file the full pilot list with every result.

That makes it the format a comp organiser hands you at the end of the week, and the reason an FSDB importer returns a list. A five-task comp yields five tasks, each needing its own name and date.

Two halves. FsTaskDefinition describes the flying — geometry, gates, deadlines. FsParticipants / FsTaskScoreParams / FsParticipant carry results. A file that has only been defined and not yet flown contains the first half alone, and is completely valid. Never require the scoring elements.

Versions in the wild

The root element carries a version attribute (3.x for modern FS). The task-definition shape described here has been stable since FS 2018 and is what Airscore reads and writes. Older 2000s-era files exist with different attribute spellings; they are rare enough that the pragmatic move is to reject them loudly rather than guess.

02 Document structure

The element tree

the path to a task
Fs [version]
└─ FsCompetition [name, from, to, location]
   ├─ FsCompetitionNotes
   ├─ FsTasks
   │  └─ FsTask [id, name]                          ← repeats, one per task
   │     ├─ FsTaskState [task_state, cancel_reason]
   │     ├─ FsTaskScoreParams [task_distance, …]      // scoring, optional
   │     └─ FsTaskDefinition [ss, es, goal, groundstart]
   │        ├─ FsTurnpoint [id, lat, lon, altitude, radius, open, close]
   │        └─ FsStartGate [open]                   // 0..n
   └─ FsParticipants                                  // pilots + results, optional

Everything that matters is an attribute. FSDB has almost no element text content — if you are reading textContent anywhere, you are on the wrong track.

Force-array the repeaters. FsTask, FsTurnpoint and FsStartGate repeat. Most XML-to-object libraries collapse a single occurrence into an object rather than a one-element array — a one-task comp then crashes an importer that worked on a five-task one. Declare those three names as always-arrays.
03 FsTaskDefinition

The four attributes that define the race

AttributeTypeMeaning
ssintegerStart of speed section — the 1-based index of the turnpoint that is the SSS. Absent or 0 means the task has no speed section.
esintegerEnd of speed section — 1-based index of the ESS.
goalstringCYLINDER or LINE — the shape of the final turnpoint's zone.
groundstart0 / 1Whether the clock runs from a ground start rather than a gate.
qnh_settingnumberQNH used for altitude checks, hPa. Advisory.
ss and es are indices, not names. They point into the FsTurnpoint list, counting from 1. This is the single most common FSDB import bug: read them as zero-based and every task starts one turnpoint too early.

There is no attribute naming the takeoff, and none naming the goal. Both are positional — see §04.

04 Role derivation

Which turnpoint is which

A turnpoint's role is derived from its position and the two index attributes. The rules, in the order that resolves conflicts correctly:

  • Index 1 is the takeoff.
  • Index ss is the SSS, when ss is present and greater than zero.
  • Index es is the ESS.
  • The last index is the goal — and it wins over everything above.
  • Everything else is a plain turnpoint.

The precedence in rule 4 is not decoration. In a race that ends at the goal line, es commonly points at the last turnpoint — the ESS and the goal are the same cylinder. Applying the rules in any other order leaves you with a task that has an ESS and no goal.

Try it · turnpoint count, ss, es → roles

A turnpoint's attributes

AttributeUnitMeaning
idstringWaypoint name — usually "CODE Name" (B02 Aujour). Not a numeric id.
lat / londegreesSigned decimal WGS84. Legacy files may use sexagesimal "DD MM SS.ss" — see §08.
altitudemetresTerrain elevation at the point.
radiusmetresCylinder radius.
open / closeISO datetimeThe turnpoint's own window. Present on some points, absent on others.
05 Gates & timing

Start gates, deadlines and the flying day

FSDB is the only task format that carries full datetimes with a UTC offset, not bare times of day:

a start gate and a turnpoint window
<FsTurnpoint id="B02 Aujour" lat="44.28500" lon="5.74000"
  altitude="1834" radius="2000"
  open="2022-07-06T12:30:00+00:00" close="2022-07-06T19:00:00+00:00"/>
<FsStartGate open="2022-07-06T12:30:00+02:00"/>

That offset is a gift: it makes the flying date recoverable, and it lets every gate convert to a true UTC HH:MM:SSZ — the same canonical form XCTrack and Airtribune use. An FSDB task and its Airtribune twin therefore reduce to the same times, and deduplicate to one library entry.

Convert, never truncate. 12:30:00+02:00 is 10:30:00Z. Slicing the time substring out of the string keeps the wall-clock digits and silently shifts the task by the offset — and because the result still looks like a plausible gate, nothing downstream complains.

Race, elapsed time, or open distance

File saysTask isGates
ss present, ≥ 1 FsStartGateRace to goalEach FsStartGate open is a gate.
ss present, no FsStartGateElapsed timeThe clock starts per pilot; fall back to the SSS turnpoint's open.
no ssOpen distance / freeNo speed section at all.

Start direction

FSDB does not record whether the start cylinder is entered or exited. The FS convention recovers it from geometry: when the takeoff and the SSS share a position, the start is an EXIT (you launch inside the cylinder and leave it); otherwise it is an ENTER. That is what Airscore's own importer does, and it is right often enough to be the sane default — but it is an inference, not data.

The task deadline comes from the close attribute of the ESS turnpoint.

06 Element explorer

Every element and attribute

Search by element, attribute or meaning, or narrow by category.

07 File inspector

Paste an FSDB, read the tasks out

Every FsTask is listed with its turnpoints, the roles derived from ss/es, and its gates converted to UTC. Parsed with the browser's own XML parser — nothing is uploaded.

FSDB source · editable
Tasks live
08 Parsing gotchas

Where FSDB imports go wrong

  • ss and es count from 1. The one bug that produces a task which looks almost right.
  • Goal beats ESS. Apply the last-index rule after the es rule, or a task whose ESS is the final cylinder ends up with no goal.
  • Datetimes carry an offset. Convert to UTC; never slice the time out of the string.
  • Coordinates may be sexagesimal. Older files write lat="44 16 40.8" — degrees, minutes, seconds, space-separated. Sniff for whitespace before calling parseFloat, which would happily return 44.
  • Negative sexagesimal is sign-on-degrees. "-5 30 0" is −5.5°, not −5 + 0.5. Take the magnitude of all three components and apply the sign of the first.
  • One task can be malformed without the file being malformed. Skip an unreadable FsTask and keep the rest — a cancelled or half-defined task is normal in a real comp file.
  • Scoring elements are optional. A defined-but-not-yet-flown comp has no FsParticipants. Do not treat that as an error.
  • Bound the file. A scored FSDB with a few hundred pilots runs to megabytes of results you do not need. Cap the input size and the task count. We-Fly allows 4 MB and 60 tasks.
09 In We-Fly

What We-Fly reads

We-Fly imports .fsdb in the competition-task library. One upload can create many tasks; each is named "<competition> — <task>" and dated from the first turnpoint window, so a whole comp week lands as a set of dated, linkable tasks.

Behaviour
DirectionImport only. We-Fly exports tasks as .xctsk, never as FSDB.
Size limit4 MB per file, 60 tasks per file.
IgnoredAll scoring elements — pilots, results, formulas.
DedupBecause gates convert to true UTC, an FSDB task matches the same task imported from Airtribune or XCTrack and is stored once.

How the four task formats map onto one model — and what each loses — is in the competition-task formats guide.

10 Sources

What this reconciles