Flare Timing

The flare-timing implementation of GAP is a set of command line apps to be run in sequence. The workings of each step and the final scores are written to plain-text files. In these there’s enough detail and supporting evidence for everything to be checked by hand.

Scoring Steps

Let’s now walk through the process of scoring with flare-timing. Starting from an *.fsdb competition with related *.igc or *.kml track logs, scoring proceeds in steps [1];

  1. Extract the inputs with extract-input.
  2. Trace the route of the shortest path to fly a task with task-length.
  3. Find pairs of fixes crossing over zones with cross-zone.
  4. Interpolate between crossing fixes with tag-zone.
  5. Unpack track logs to a flat list of time with latitude and longitude with unpack-track . This data supplies the pilot tracks that can be downloaded and shown on the map and is used to find the scored track indices for stopped tasks.
  6. Peg out the time range of each track log that will be scored with peg-frame.
  7. Index fixes from the time of first crossing with align-time.
  8. Discard fixes that get further from goal and note leading area with discard-further.
  9. Mask a task over its tracklogs with mask-track.
  10. Group and count land outs with land-out.
  11. Score the competition with gap-point.

If hosting the web app then the following two steps are needed too:

  1. Extract the scores and some of the workings of FS with fs-score. These values and differences are shown as extra columns in tables side-by-side with flare-timing values. This is a quick way to spot discrepancies between the two GAP scoring implementations.
[1]In this list, any step can use the inputs or outputs from a previous step. For instance *.kml and *.igc track logs are needed as inputs for the cross-zone, align-time and unpack-track steps. The app of each step logs the inputs they’re using.

Extracting Inputs

We can extract the inputs for scoring from the competition’s *.fsdb. FS keeps both inputs and outputs in this file. It is XML without a schema. We’re only interested in a subset of the input data, just enough to do the scoring [1]. Other data useful to running a competition but not required for scoring we ignore.

Competition
id, name, location, date range and UTC offset, discipline, Earth model and geometry math, stopped task score back time and turnpoint tolerance, scaling for arrival and leading weights.
Nominal
launch, goal, time, distance and minimal distance.
Task
name and kind of task, zones, speed section, start gates and pilots, if and when stopped, scaling for arrival and leading weights and any penalties.
Zone
name, latitude, longitude, altitude, open and close times, radius, shape.
Pilot
name and track log file name normally but can be marked as absent or did not fly or flew having no track log sometimes being awarded distance or time manually by the scorer.

Something to be aware of when parsing XML of *.fsdb is that attributes may be missing and in that case we’ll have to infer the defaults used by FS. This is done by looking at the source code of FS as there is no schema for the XML that could also be used to set default values.

<Fs>
  <FsCompetition id="7592" name="2012 Hang Gliding Pre-World Forbes" location="Forbes, Australia"
      from="2012-01-05" to="2012-01-14" utc_offset="11">
    <!-- Nominals are set once for a competition but beware, they are repeated per task. -->
    <FsScoreFormula min_dist="5" nom_dist="80" nom_time="2" nom_goal="0.2" />
    <FsParticipants>
      <FsParticipant id="23" name="Gerolf Heinrichs" />
      <FsParticipant id="106" name="Adam Parer" />
    </FsParticipants>
      <!-- Flags on how to score are also set for the competition but pick them up from the task. -->
      <FsTask name="Day 8" tracklog_folder="Tracklogs\day 8">
        <FsScoreFormula use_distance_points="1" use_time_points="1" use_departure_points="0" use_leading_points="1" use_arrival_position_points="1" use_arrival_time_points="0" />
        <FsTaskDefinition ss="2" es="5" goal="LINE" groundstart="0">
          <!-- Not shown here but each FsTurnpoint has open and close attributes. -->
          <FsTurnpoint id="FORBES" lat="-33.36137" lon="147.93207" radius="100" />
          <FsTurnpoint id="FORBES" lat="-33.36137" lon="147.93207" radius="10000" />
          <FsTurnpoint id="MARSDE" lat="-33.75343" lon="147.52865" radius="5000" />
          <FsTurnpoint id="YARRAB" lat="-33.12908" lon="147.57323" radius="400" />
          <FsTurnpoint id="DAY8GO" lat="-33.361" lon="147.9315" radius="400" />
          <!-- This was an elapsed time task so no start gates. -->
        </FsTaskDefinition>
        <FsTaskState stop_time="2012-01-14T17:22:00+11:00" />
        <FsParticipants>
        <!-- See a description of FsParticipant below. -->
        </FsParticipants>
      </FsTask>
    </FsTasks>
  </FsCompetition>
</Fs>

Pilot Groups

When parsing the *.fsdb file there are various groups of pilots.

  • ABS: An FsParticipant without child elements is an absent pilot.

    <FsParticipant id="106" />
    
  • DNF: With empty FsFlightData this pilot did not fly.

    <FsParticipant id="80">
      <FsFlightData />
    </FsParticipant>
    
  • DF: A pilot with a tracklog who did fly.

    <FsParticipant id="23">
      <FsFlightData tracklog_filename="Gerolf_Heinrichs.20120114-100859.6405.23.kml" />
    </FsParticipant>
    
  • DF: A pilot without tracklog who did fly and will be awarded minimum distance.

    <FsParticipant id="91">
      <FsFlightData tracklog_filename="" />
    </FsParticipant>
    
  • DF: A pilot without tracklog who did fly and was awarded a distance by the scorer. Distance calculations can vary depending on the Earth model and algorithm used. For this reason we also need to grab the task distance too. When it comes time to score this pilot we’ll award them a distance relative to the task distance and not the exact distances saved in the *.fsdb calculated by FS.

    <FsParticipants>
      <FsParticipant id="85">
        <FsFlightData distance="95.030" tracklog_filename="" />
      </FsParticipant>
    </FsParticipants>
    <FsTaskScoreParams task_distance="158.847" />
    
[1]As flare-timing is a work in progress, some further inputs will be needed as different kinds of task are tested, such as those with stopped tasks and those with penalties

Tracing an Optimal Route

To find the best route flare-timing constructs a graph and finds the shortest path connecting the nodes. It puts nodes on turnpoint cylinder arc boundaries and uses the competition specific math for working out distances on the Earth as the cost of connecting nodes in the network. It would be expensive to construct and evaluate a large network with the accuracy required so it is done iteratively. At each iteration the arc of the circle bounding a zone is shortened and the density of nodes is increased. For goal line zones the nodes are selected in pretty much the same way except that points on the arc are projected down onto the line.

This optimal path found on the Earth model for the competition is the edge to edge optimal route. Routes are shown with waypoints, segment distances [1] and total distance.

taskRoutes:
  edgeToEdge:
    distance: 159.373683
    legs:
    - 10.078208
    - 42.525217
    - 0
    - 64.949832
    - 41.820427
    legsSum:
    - 10.078208
    - 52.603424
    - 52.603424
    - 117.553256
    - 159.373683
    waypoints:
    - lat: -33.36047067
      lng: 147.93206999
    - lat: -33.43411056
      lng: 147.86878018
    - lat: -33.7159199
      lng: 147.55846831
    - lat: -33.7159199
      lng: 147.55846831
    - lat: -33.13199024
      lng: 147.57575486
    - lat: -33.35857718
      lng: 147.93468357

The naive way to measure task length would be to just connect the centers of each control zone. This is the point to point distance.

taskRoutes:
  pointToPoint:
    distance: 169.10714
    legs:
    - 57.427511
    - 69.547668
    - 42.131961
    legsSum:
    - 57.427511
    - 126.975179
    - 169.10714
    waypoints:
    - lat: -33.36137
      lng: 147.93207
    - lat: -33.75343
      lng: 147.52864998
    - lat: -33.12908
      lng: 147.57322998
    - lat: -33.36099999
      lng: 147.93149998

Knowing that FS uses a plane to work out the shortest route in two dimensions on the the Universal Transverse Mercator projection, we can also do that with our graph algorithm. We end up with waypoints, optimal on the plane but possibly sub-optimal on the sphere or ellipsoid model of Earth.

taskRoutes:
  projection:
    spherical:
      distance: 159.373683
      legs:
      - 10.078208
      - 42.525217
      - 0
      - 64.949832
      - 41.820427
      legsSum:
      - 10.078208
      - 52.603424
      - 52.603424
      - 117.553256
      - 159.373683
      waypoints:
      - lat: -33.36047067
        lng: 147.93206999
      - lat: -33.43411056
        lng: 147.86878018
      - lat: -33.7159199
        lng: 147.55846831
      - lat: -33.7159199
        lng: 147.55846831
      - lat: -33.13199024
        lng: 147.57575486
      - lat: -33.35857718
        lng: 147.93468357
taskRoutes:
  projection:
    planar:
      distance: 159.144781
      legs:
      - 10.065441
      - 42.4942
      - 0
      - 64.761082
      - 41.820427
      legsSum:
      - 10.065441
      - 52.559642
      - 52.559642
      - 117.320723
      - 159.14115
      mappedPoints:
      - easting: 586715.834
        northing: 6308362.198
      - easting: 580759.282
        northing: 6300248.47
      - easting: 551744.701
        northing: 6269201.551
      - easting: 551744.701
        northing: 6269201.551
      - easting: 553704.761
        northing: 6333932.964
      - easting: 586960.882
        northing: 6308569.955
      mappedZones:
      - latZone: H
        lngZone: 55
[1]A zero leg distance indicates that the turnpoint was touched at one point only, the optimal route does not traverse the interior of the cylinder. The entry and exit waypoints are both shown but can be the same.

Crossing Zones and Sectioning Tracks

For each pilot track, we need to work out which zones have been crossed with cross-zone and then select from these crossings the tagging of each zone with tag-zone. Taking into account the timing restriction of the task we can section the times and fixes selecting the subset of these that will be scored with peg-frame.

Finding Zone Crossings

Before we can determine if any zones have been crossed we’ll have to decide how to tell which parts of a track log are flown and which are walked or driven in the retrieve car, possibly even back to goal. [1]

To work out when a pilot is flying, select the longest run of fixes that are not the same allowing for some stickiness when the GPS loses signal. For example we might consider within ± 1m altitude or within ± 1/10,000th of a degree of latitude or longitude to be in the same location and not likely recorded during flight.

flying:
  - - - '23'
      - Gerolf Heinrichs
    - loggedFixes: 4786
      flyingFixes:
      - 293
      - 4775
      loggedSeconds: 19140
      flyingSeconds:
      - 1172
      - 19100
      loggedTimes:
      - 2012-01-14T02:00:05Z
      - 2012-01-14T07:19:05Z
      flyingTimes:
      - 2012-01-14T02:19:37Z
      - 2012-01-14T07:18:25Z

Next we need to find and nominate every crossing of each control zone and from among those work out which pair to select as the zone crossing. The same control zone may be crossed multiple times and we need a sequence of crossings ordered in time that fits the task [2].

crossing:
  - - - '23'
      - Gerolf Heinrichs
    - zonesCrossSelected:
      - crossingPair: ...
      - crossingPair: ...
      - crossingPair: ...
      - crossingPair: ...
      - crossingPair:
        - fix: 4714
          time: 2012-01-14T07:14:21Z
          lat: -33.360479
          lng: 147.931166
          alt: 377
        - fix: 4715
          time: 2012-01-14T07:14:25Z
          lat: -33.361015
          lng: 147.931573
          alt: 372
        inZone:
        - false
        - true
      zonesCrossNominees: ...

Interpolating Zone Taggings

Between the pair of fixes straddling a control zone, we need to interpolate the point at which the pilot is most likely to have crossed and the time of this tagging of the turnpoint.

tagging:
  - - - '23'
      - Gerolf Heinrichs
    - zonesTag:
      - inter: ...
      - inter: ...
      - inter: ...
      - inter: ...
      - inter:
          fixFrac: 4714.903706113713
          time: 2012-01-14T07:14:24.614824454852Z
          lat: -33.36096338
          lng: 147.93153381
          alt: 372.48
        cross:
          crossingPair:
          - fix: 4714
            time: 2012-01-14T07:14:21Z
            lat: -33.360479
            lng: 147.931166
            alt: 377
          - fix: 4715
            time: 2012-01-14T07:14:25Z
            lat: -33.361015
            lng: 147.931573
            alt: 372
          inZone:
          - false
          - true

Sorting the list of tagging times, we can show the first and last times, the count of taggings and the pilots.

timing:
- zonesSum:
  - 74
  - 81
  - 73
  - 54
  - 27
  zonesFirst:
  - 2012-01-14T02:00:38.517193949596Z
  - 2012-01-14T02:43:11.03560045651Z
  - 2012-01-14T04:26:05.006295836437Z
  - 2012-01-14T06:21:02.137866989328Z
  - 2012-01-14T07:14:24.614824454852Z
  zonesLast:
  - 2012-01-14T03:10:04.202693584608Z
  - 2012-01-14T04:19:09.263939298134Z
  - 2012-01-14T07:16:54.579375206841Z
  - 2012-01-14T08:06:40.357924724524Z
  - 2012-01-14T08:12:57.60359403562Z
  zonesRankTime:
  - - 2012-01-14T02:00:38.517193949596Z
    - ...
  - - 2012-01-14T02:43:11.03560045651Z
    - ...
  - - 2012-01-14T04:26:05.006295836437Z
    - ...
  - - 2012-01-14T06:21:02.137866989328Z
    - ...
  - - 2012-01-14T07:14:24.614824454852Z
    - 2012-01-14T07:31:07.089658199088Z
    - 2012-01-14T07:35:18.31771989944Z
    - ...
  zonesRankPilot:
  - - - '51'
      - Rob In 't Groen
    - ...
  - - - '88'
      - Martin Sielaf
    - ...
  - - - '66'
      - Jonas Lobitz
    - ...
  - - - '23'
      - Gerolf Heinrichs
    - ...
  - - - '23'
      - Gerolf Heinrichs
    - - '100'
      - Attila Bertok
    - - '66'
      - Jonas Lobitz
    - - ...
  lastLanding: 2012-01-14T08:41:04Z

Sectioning the Scoring Window

With the scored section of the track log in hand we can select from the zone taggings those that will be scored and update the task timings [3].

stopWindow:
- lastStarters: []
  windowTimes:
  - 2018-05-24T10:30:00Z
  - 2018-05-24T12:18:00Z
  windowSeconds: 6480
- lastStarters: []
  windowTimes:
  - 2018-05-26T11:00:00Z
  - 2018-05-26T12:05:00Z
  windowSeconds: 3900
- null
stopFlying:
      ...
  - - - '37'
      - Igor Eržen
    - scoredFixes:
      - 40
      - 1323
      scoredSeconds:
      - 40
      - 1323
      scoredTimes:
      - 2018-05-24T11:19:48Z
      - 2018-05-24T11:41:11
      ...
  - - - '37'
      - Igor Eržen
    - scoredFixes:
      - 47
      - 4507
      scoredSeconds:
      - 47
      - 4507
      scoredTimes:
      - 2018-05-26T10:48:26Z
      - 2018-05-26T12:02:46
      ...
  - - - '37'
      - Igor Eržen
    - scoredFixes:
      - 45
      - 6955
      scoredSeconds:
      - 45
      - 6955
      scoredTimes:
      - 2018-05-27T10:35:29Z
      - 2018-05-27T12:30:39Z
      ...
timing: ...
tagging: ...
[1]Some pilots’ track logs will have initial values way off from the location of the device. I suspect that the GPS logger is remembering the position it had when last turned off, most likely at the end of yesterday’s flight, somewhere near where the pilot landed that day. Until the GPS receiver gets a satellite fix and can compute the current position the stale, last known, position gets logged. This means that a pilot may turn on their instrument inside the start circle but their tracklog will start outside of it.
[2]On a triangle course early fixes may cross goal.
[3]The competition shown in most examples had no stopped tasks so this snippet is from the workings for scoring the 2018 XC Dalmatian Paragliding Open. In this competition the first two of three tasks were stopped.

Track Log Tables

The next steps all work to produce *.csv files that share a common set of headers so that they can be compared easily. These headers are:

fixIdx,time,lat,lng,alt,tickLead,tickRace,zoneIdx,legIdx,togo,area

The steps for processing track logs proceeds as follows:

  1. Unpack track logs with unpack-track.
  2. Index fixes from the time of first crossing with align-time.
  3. Discard fixes that get further from goal and note leading area with discard-further.
  4. Discard fixes after first applying any distance for altitude bonus with peg-then-discard.
  5. Discard fixes before applying any distance for altitude bonus discard-then-peg.

Unpacking Tracks

The *.igc file format has a header record for the date with fix records offset in seconds from this.

HFDTE0301181
     ^^^^^^^
     on 2018-01-03
...
B0405473321383S14756040EA0024800227
 ^^^^^^
 at 04:05:47

The *.kml format sometimes used in competitions is similar with a timestamp for the first point and then seconds of offset from that for each subsequent fix.

<Placemark>
  <Metadata src="GpsDump" v="4.66" type="track">
    <FsInfo time_of_first_point="2012-01-14T02:12:55Z"
            civl_pilot_id="21437" comp_pilot_id="40"
            instrument="6030 SN06451 SW3.30"
            downloaded="2012-01-14T08:22:21Z"
            hash="61168B84FE0DAC55F3D65EFBA888B08F72834DDF">
      <SecondsFromTimeOfFirstPoint>
0 2 4 ...
      </SecondsFromTimeOfFirstPoint>
      <PressureAltitude>
239 240 240 ..
      </PressureAltitude>
    </FsInfo>
  </Metadata>
  <name>Tracklog</name>
  <LineString>
    <altitudeMode>absolute</altitudeMode>
    <coordinates>
147.932050,-33.361600,237 147.932050,-33.361600,238 147.932050,-33.361600,238 ...
    </coordinates>
  </LineString>
</Placemark>

The unpack-track step sets values for these fields:

fixIdx,time,lat,lng,alt

Aligning Tracks by Elapsed Time

We align the tracks in time elapsed from the first start and work out the distance flown for each fix. All fields are set except area so by this stage we know which leg of the course a fix is associated with, the legIdx, and which fix it is within a leg, the zoneIdx. The tickLead and tickRace are aligning the track logs over all competitors flying a task:

fixIdx,time,lat,lng,alt,tickLead,tickRace,zoneIdx,legIdx,togo

Discarding Fixes further from Goal

We discard any fixes that get further from goal so that togo always decreases and work out the leading area for each increment of distance. This is the track log data used for time and leading points.

fixIdx,time,lat,lng,alt,tickLead,tickRace,zoneIdx,legIdx,togo,area

When no pilot makes it through the speed section no time points are awarded. The last row holds the minimum togo value. When subtracted from the task length this gives a pilot’s distance flown or reach. The maximum reach, the task best distance, is compared to the competition’s nominal distance to determine the time validity for tasks where no pilot makes it through the speed section.

Peg and then Discard

When circling in thermals altitude gains are often uneven. Sharing a thermal with another pilot we’ll see them go up and down relative to us around the turn. The GAP rules say that an altitude bonus distance is calculated for each fix in a pilots track log. From this it would be right to apply the bonus before discarding fixes.

fixIdx,time,lat,lng,alt,tickLead,tickRace,zoneIdx,legIdx,togo,area

Discard and then Peg

What if the altitude bonus was applied after discarding fixes further from goal? We could potentially end up with negative slivers of leading area. In any case altitude bonus distance is ignored for the purpose of calculating leading area.

fixIdx,time,lat,lng,alt,tickLead,tickRace,zoneIdx,legIdx,togo,area
                                                              ^^^^
                                                              sometimes negative

Masking Task over Track

Taking what we now know about the tracks and the task, we have times, distances and fractions we’ll need later for the points. So far we have leading, arrival, speed and reach [1] fractions but we still need to look at where pilots landed to have the effort [2] fractions.

pilotsAtEss:
...
- 29
raceTime:
...
- openTask: 2012-01-14T01:00:00Z
  closeTask: 2012-01-14T09:00:00Z
  firstStart: 2012-01-14T02:43:11.03560045651Z
  firstLead: 2012-01-14T02:43:11.03560045651Z
  lastArrival: 2012-01-14T08:12:57.60359403562Z
  leadAllDown: 21472.964
  leadArrival: 19786.568
  leadClose: 22608.964
  openClose: 28800
  tickClose: 22608.964
ssBestTime:
...
- 3.719213 h
gsBestTime:
...
- 3.719213 h
taskDistance:
...
- 158.864751 km
taskSpeedDistance:
...
- 148.964751 km
bestDistance:
...
- 158.864751 km
sumDistance:
...
- 9486.622084 km
leadAreaToCoef:
...
- 0.00000002503574 km^-2 s^-1
leadCoefMin:
...
- 4.12428993

We have the lead and arrival fractions:

leadRank:
...
- - - - '23'
      - Gerolf Heinrichs
    - area: 164736078.4532 km^2 s
      coef: 4.12428993
      frac: 1
  - - - '66'
      - Jonas Lobitz
    - area: 166917443.8758 km^2 s
      coef: 4.17890204
      frac: 0.91024137
  - - - '51'
      - Rob In 't Groen
    - area: 170139661.7053 km^2 s
      coef: 4.25957265
      frac: 0.83567191
 ...
arrivalRank:
...
- - - - '23'
      - Gerolf Heinrichs
    - rank: '1'
      frac: 1
  - - - '100'
      - Attila Bertok
    - rank: '2'
      frac: 0.92666251
  - - - '66'
      - Jonas Lobitz
    - rank: '3'
      frac: 0.85799451
  ...

If the task is stopped we’ll need some statistics to work out the stopped task validity:

flownMean:
...
- 117.935977 km
flownStdDev:
...
- 49.749145 km
reachMean:
...
- 117.935977 km
reachStdDev:
...
- 49.749145 km

We have the reach and speed fractions:

reachRank:
...
- - - - '23'
      - Gerolf Heinrichs
    - frac: 1
      reach: 158.864751 km
  - - - '100'
      - Attila Bertok
    - frac: 1
      reach: 158.864751 km
  - - - '66'
      - Jonas Lobitz
    - frac: 1
      reach: 158.864751 km
  ...
ssSpeed: ...
gsSpeed:
- - - - '23'
      - Gerolf Heinrichs
    - time: 3.719213 h
      frac: 1
  - - - '83'
      - Peter Dall
    - time: 3.924142 h
      frac: 0.77565394
  - - - '41'
      - Curt Warren
    - time: 3.947778 h
      frac: 0.75871917
  ...

For those landing out, how close or nigh were they to goal, what was their reach? Pilots that arrived at goal have a reach equal to the task distance and are not included in this list of pilots that are nigh.

nigh:
...
- - - '40'
      - Phil de Joux
    - togo:
        distance: 112.781482 km
        flipSum:
        - 112.781482 km
        - 106.020325 km
        - 41.776873 km
        legs:
        - 6.761157 km
        - 64.243452 km
        - 41.776873 km
        legsSum:
        - 6.761157 km
        - 71.004609 km
        - 112.781482 km
        waypoints:
        - lat: -33.651233
          lng: 147.560767
        - lat: -33.70932748
          lng: 147.53919553
        - lat: -33.13234684
          lng: 147.57502845
        - lat: -33.36226617
          lng: 147.93033075
      made: 46.083751 km
  - - - '53'
      - Hadewych van Kempen
    - togo:
        distance: 123.188199 km
        flipSum:
        - 123.188199 km
        - 106.093143 km
        - 41.776873 km
        legs:
        - 17.095056 km
        - 64.316270 km
        - 41.776873 km
        legsSum:
        - 17.095056 km
        - 81.411326 km
        - 123.188199 km
        waypoints:
        - lat: -33.577367
          lng: 147.6364
        - lat: -33.71015129
          lng: 147.54332275
        - lat: -33.13234684
          lng: 147.57502845
        - lat: -33.36226617
          lng: 147.93033075
      made: 35.676751 km
...

Where did pilots land along the course?

land:
- - - - '41'
      - Curt Warren
    - togo: 0.000000 km
      made: 158.864751 km
  - - - '95'
      - Anton Struganov
    - togo: 0.000000 km
      made: 158.864751 km
  - - - '30'
      - Fredy Bircher
    - togo: 0.827092 km
      made: 158.037659 km
  ...
  - - - '40'
      - Phil de Joux
    - togo: 112.823874 km
      made: 46.040877 km
  - - - '53'
      - Hadewych van Kempen
    - togo: 123.477146 km
      made: 35.387605 km
  ...
[1]Reach is the distance made.
[2]Effort is the distance difficulty.

Assessing Difficulty

We consider only pilots landing out in 100m chunks of the task. How many came down in a chunk and how many are downward bound is shown. For each chunk with a landing, we have its relative difficulty. Taking the sum of these under a moving window we have difficulty fractions to award to pilots.

minDistance: 5.000 km
bestDistance:
...
- 158.865 km
landout:
...
- 63
lookahead:
...
- 76
sumOfDifficulty:
...
- 266
difficulty:
...
- - chunk: 0
    startChunk: 5.0 km
    endChunk: 5.0 km
    endAhead: 12.6 km
    down: 3
    downs:
    - 5.000 km
    - 5.000 km
    - 5.000 km
    downers:
    - - '32'
      - Kathryn O'Riordan
    - - '64'
      - Gustavo Carvalho
    - - '28'
      - Evgeniya Laritskaya
    downward: 3
    rel: 5.6391e-3
    frac: 5.6391e-3
    ...
  - chunk: 304
    startChunk: 35.3 km
    endChunk: 35.4 km
    endAhead: 43.0 km
    down: 1
    downs:
    - 35.388 km
    downers:
    - - '53'
      - Hadewych van Kempen
    downward: 1
    rel: 1.8797e-3
    frac: 4.887218e-2
  - chunk: 411
    startChunk: 46.0 km
    endChunk: 46.1 km
    endAhead: 53.7 km
    down: 1
    downs:
    - 46.041 km
    downers:
    - - '40'
      - Phil de Joux
    downward: 5
    rel: 9.3985e-3
    frac: 5.827068e-2
    ...

Collating Scores

To calculate validities, we need nominal values, the fraction of pilots flying, the best distance and the best time and the sum of the distance flown. From the ratio of pilots making goal we can work out the weights and then with the validities we can work out the available points.

validityWorking:
- time:
    bestDistance: 159.3 km
    nominalTime: 2.0 h
    bestTime: 3.716666 h
    nominalDistance: 80.0 km
  launch:
    nominalLaunch: 0.95999999
    flying: 84
    present: 91
  distance:
    sum: 9427.0 km
    flying: 84
    area: 52.9374
    nominalGoal: 0.2
    nominalDistance: 80.0 km
    minimumDistance: 5.0 km
    bestDistance: 159.3 km
validity:
- time: 1
  launch: 0.99468309
  distance: 1
  task: 0.99468309
allocation:
- goalRatio: 0.34523809
  weight:
    distance: 0.50519562
    leading: 8.659076e-2
    arrival: 6.185054e-2
    time: 0.34636306
  points:
    reach: 251.2
    effort: 251.2
    distance: 502.5
    leading: 86.1
    arrival: 61.5
    time: 344.5
  taskPoints: 994.0

With all the information now at hand, we can tally points for the total task score.

score:
 - - Phil de Joux
    - total: 85.0
      breakdown:
        reach: 72.9
        effort: 12.1
        distance: 85.1
        leading: 0
        arrival: 0
        time: 0
      velocity:
        ss: 2012-01-14T03:33:34Z
        es: null
        distance: 46.2 km
        elapsed: null
        velocity: null
 ...
  - - Gerolf Heinrichs
    - total: 994.0
      breakdown:
        reach: 251.2
        effort: 251.2
        distance: 502.5
        leading: 86.1
        arrival: 61.5
        time: 344.5
      velocity:
        ss: 2012-01-14T03:31:13Z
        es: 2012-01-14T07:14:13Z
        distance: 159.3 km
        elapsed: 3.716666 h
        velocity: 42.8 km / h
Scarf Analytics