Flight figures
This page covers the numbers on the flight detail pages (summary, Performance, Flight, Info, Phases, the declared task and optimisation pages) and on the map’s readings line. It builds on Flight analysis, which specifies the analysis itself. This page does not repeat these sections:
| Topic | Where |
|---|---|
| Take-off, release, landing, engine runs, gliding block, height-gain range | Flight analysis §5.1 |
| Per-fix bearing, vario, ground speed | Flight analysis §3.6 |
| Pressure correction, and GPS altitude standing in for a missing baro | Flight analysis §4.2 |
| Thermals, legs (glides) | Flight analysis §5.3–5.5 |
Leg, Optimization, TaskAttempt fields | Flight analysis §2.4, §2.7, §2.8 |
The flight’s derived statistics (duration, averageGlideRatio, …) | Flight analysis §2.1 (“Derived (lazy) statistics”) |
| Distance optimisations | Flight analysis §6 |
| Task scoring | Flight analysis §7.5 |
| Per-fix average speed, average task speed, distance travelled, best 1 h / 2 h | Flight analysis §7.6 |
| Terrain elevation | Flight analysis §8.1 |
Unit conversion, UnitFormatter, time formats, printf rounding | Flight analysis §9 |
| Barogram series, scale and readout | Map, barogram and airspace §4 |
| Thermals page figures | Thermals |
Android ports every figure on this page from iOS. Where a figure differs, its section says so.
1. Conventions
Section titled “1. Conventions”1.1 Units and rounding
Section titled “1.1 Units and rounding”Every figure is computed in SI units: metres, seconds and m/s. Only the formatter converts it to the pilot’s
unit. The output is "{number} {unit}". The number of decimals depends on the unit, not on the figure.
| Unit setting | Decimals | Example |
|---|---|---|
| Altitude: m, ft | 0 | 1240 m |
| Speed and wind: km/h, mph, kt | 0 | 98 km/h |
| Vertical speed: m/s | 2 | 2.49 m/s |
| Vertical speed: kt, ft/min | 0 | 5 kt |
| Distance: km, mi, nm | 2 (0 in the “rounded” variant) | 342.18 km |
Percentage (percentageValue) | 2, format "%0.2f %%" | 34.00 % |
Glide ratio (ldString) | integer, format "%i:1" | 42:1 |
Rounding follows C printf on the exact binary value (flight analysis §9.3). Android reproduces it with
CFormat. Numbers are not grouped, and the decimal separator is always ”.”.
1.2 Time formats
Section titled “1.2 Time formats”| Format | Rule | Used for |
|---|---|---|
timeValue | HH:mm:ss. A negative value gets +86400 and a value above 86400 gets −86400, once. Uses Float arithmetic | Durations and times of day alike |
shortTimeValue | 3h05m, 3h when the minutes are 0, 05m when the hours are 0. Seconds are dropped, and 0 gives 0h | iOS inspector’s slim column |
veryShortTimeValue | Only the non-zero parts: 1h 5m 30s, 45s. 0 gives an empty string | Thermal phase caption |
Durations go through timeValue, so a duration over 24 h wraps. 90 000 s shows as 01:00:00.
1.3 Missing values
Section titled “1.3 Missing values”The detail pages hide what they cannot fill. They never show a placeholder.
- A label/value item (
DetailInfoItem) fails to build when its value isnilor empty. A paired row disappears when both of its items are missing. A section with no rows disappears. - A metric tile (
DetailMetric) fails to build on anilor empty string, so the tile is dropped and the grid closes up. - A summary row whose page has nothing to show is dropped. See §2.2.
The map’s readings line works the other way round. Each reading shows -- when it has no value (§8).
Some figures default to 0 rather than nil, so they show as 0. The sections below call these out.
1.4 Which altitude
Section titled “1.4 Which altitude”All the figures on this page read Fix.pressureAltitude. It is never the raw B-record value:
- When the whole log has a pressure altitude of 0, it is replaced by the GPS altitude (flight analysis §4.2,
convertPressureToGPS). - Otherwise, when terrain elevation is available, it is calibrated so the first fix sits on the terrain, with the drift spread linearly to the last fix.
So a “height” on this page is the corrected baro altitude, or the GPS altitude for a log without a baro. The
pilot’s barogram choice of pressure or GPS altitude (graphDataUnit, map-barogram §4.2) changes only the
barogram. It changes nothing on this page.
Height above ground (AGL) = pressureAltitude − elevation, in metres. Fix.elevation defaults to 0, so a
flight without terrain data shows its AGL equal to its MSL height, still labelled “AGL”. Only the map snapshot
strip checks isElevationAvailable (§8.3).
Source: vulture-ios/Packages/Preferences/Sources/Preferences/Units/Formatter/UnitFormatter.swift,
.../Units/Extensions/Double+Formatter.swift, Int+Formatter.swift,
vulture-ios/Packages/Flights/Sources/Flights/Extensions/Int+Time.swift,
vulture-ios/Packages/DesignSystem/Sources/DesignSystem/Extensions/Double+Percentage.swift,
vulture-ios/Packages/FlightScreens/Sources/FlightScreens/FlightDetail/Rows/DetailInfoItem.swift,
.../FlightDetail/Models/DetailMetricGrid.swift (DetailMetric.init?(label:formattedValue:tint:));
vulture-android/core/units/src/main/kotlin/be/fousa/vulture/core/units/UnitFormatter.kt, TimeFormats.kt,
NumberFormats.kt.
2. Summary page
Section titled “2. Summary page”2.1 The four headline figures
Section titled “2.1 The four headline figures”These tiles also appear in the logbook list’s long-press preview, and the stored flight’s columns hold the same values.
| Tile | Value | Shown when |
|---|---|---|
| Distance | judgedDistance, formatted with distanceString | not nil |
| Duration | judgedDuration, formatted with timeValue | not nil |
Average speed (flight.info.label.cruise.speed) | judgedAverageSpeed, formatted with speedString | not nil |
| Height gain | altitudeGained, formatted with altitudeString | > 0 |
judgedDistance = bestTaskAttempt.distance if bestTaskAttempt != nil and its distance > 0 else freeDistanceOptimization.distance if > 0 else nil (a winch hop)
judgedAverageSpeed = (follows the same branch as the distance) task branch: bestTaskAttempt.averageSpeed if > 0, else nil free branch: freeDistanceOptimization.averageSpeed if > 0, else nil
judgedDuration = duration ?? glidingBlockDuration (seconds)altitudeGained = highestAltitudeFix.pressureAltitude − lowestAltitudeFix.pressureAltitude (m, 0 if either is nil)- The task branch is taken for an unfinished task attempt too, as long as it covered some distance. The distance and speed are then those of the path through the turnpoints it reached (flight analysis §2.8).
- If the task branch is taken but its speed is not above 0, the speed tile is dropped. The free speed is not used in its place.
durationis landing minus take-off, inrawTime(flight analysis §2.1). The fallback to the gliding block applies only when there is no take-off or no landing fix.altitudeGainedis the height gain of the gliding range with the biggest climb above its own running minimum (flight analysis §5.1processAltitudeGained). It is not the flight’s maximum minus its minimum.
iOS only, the slim figures. The inspector’s narrow column shows the same four tiles shortened. Distance uses
roundedDistanceString (0 decimals, so 2500.9 m shows 3 km) and duration uses shortTimeValue. Speed and
height gain are the same as in the tiles. Android has no slim column.
2.2 Analysis rows
Section titled “2.2 Analysis rows”The rows appear in this order. A row is dropped when its condition fails.
| Row | Shown when | Caption | Headline | Headline detail |
|---|---|---|---|---|
| Declared task | task and bestTaskAttempt both exist | turnpoint count (plural string) | “Completed” / “Unfinished” (isCompleted) | task.distance when > 0 |
| Performance | some distance optimisation has a distance > 0 | name of the best one | its distance | its averageSpeed when > 0 |
| Thermals | thermals.count > 0 | thermal count | averageThermalVario (vertical speed) | thermalPercentage (percentageValue) |
| Phases | phases is not empty | number of cruise phases | phases.count (plain integer) | — |
| Flight | always | flightDuration (timeValue), or none | — | — |
| Airspace | the crossing scan reported > 0 crossings | crossing count | — | — |
| Info | always | pilot name (logbook first, then IGC; blank counts as missing) | — | — |
The “best” optimisation is the largest distance among free, three turnpoints, triangle, out-and-return and out,
taken in that order. On a tie, the first one in that order wins (Swift max(by:); Android keeps the same rule).
thermalPercentage = totalThermallingTime / duration × 100. Without a take-off or landing (duration == nil)
the detail line is missing. averageThermalVario is time-weighted: Σ altitudeGained / Σ duration over all
thermals, and nil when the total duration is 0. Both are covered in more depth in Thermals.
Source: vulture-ios/Packages/FlightScreens/Sources/FlightScreens/FlightDetail/Models/DetailFlightFigures.swift,
.../FlightDetail/Summary/DetailSummaryViewModel.swift;
vulture-android/domain/flightdetail/src/main/kotlin/be/fousa/vulture/domain/flightdetail/DetailFlightFigures.kt,
DetailSummary.kt. Same as iOS.
3. Performance page
Section titled “3. Performance page”3.1 Achievements
Section titled “3.1 Achievements”| Row | Value | Missing when |
|---|---|---|
Gliding duration (flight.info.label.glide.duration) | glidingBlockDuration (timeValue) | no gliding block (row half hidden) |
| Height gain | altitudeGained (altitudeString) | never: shows 0 m when there is no gain, unlike the summary tile |
| Best 1 h speed | best1hSpeedOptimization as an optimisation row (§3.2) | nil |
| Best 2 h speed | best2hSpeedOptimization as an optimisation row | nil |
Maximum distance out (flight.label.optimization.maxout) | maximumDistanceOutOptimization.distance (distanceString); a tap centres the map on its last fix | nil |
glidingBlockDuration = endGlidingBlockFix.rawTime − startGlidingBlockFix.rawTime. The gliding block is the
longest engine-free stretch (flight analysis §5.1). The total gliding duration is this one block. It is not
the sum of the cruise legs, which is the cruise duration in §4.2.
The best 1 h and 2 h windows come from the speed enricher (flight analysis §7.6). Their rows show the window’s distance and its average speed.
3.2 Optimisation rows
Section titled “3.2 Optimisation rows”The five distance optimisations follow, in the order free, three turnpoints, triangle, out-and-return, out. A missing one is left out. Each row shows these values:
| Value | Rule |
|---|---|
| Distance | optimization.distance (distanceString). When it is nil or 0, the declared task’s distance, else "" |
| Speed | (optimization.averageSpeed ?? 0).speedString. It is always a string, so an optimisation with speed 0 shows 0 km/h |
| Detour | totalDetourDistance when > 0 (§6.3) |
Optimization.averageSpeed = (km / (Δt / 3600)) / 3.6 m/s (flight analysis §2.7).
Source: vulture-ios/Packages/FlightScreens/Sources/FlightScreens/FlightDetail/Tabs/DetailTabPerformanceViewModel.swift,
.../FlightDetail/Rows/DetailItemRow.swift (.optimization);
vulture-android/domain/flightdetail/src/main/kotlin/be/fousa/vulture/domain/flightdetail/PerformanceTab.kt.
Same as iOS.
4. Flight page
Section titled “4. Flight page”4.1 Flight
Section titled “4.1 Flight”| Row | Formula | Format | Missing when |
|---|---|---|---|
Time (flight.info.label.time.duration) | duration = landing.rawTime − takeoff.rawTime | timeValue | no take-off or landing fix |
| Flight duration | landing.rawTime − (release ?? takeoff).rawTime − (engineRunTime ?? 0) | timeValue | no landing, or neither release nor take-off |
| Take-off type | winch / tow / self-launch | localised label | unknown |
| Take-off performance | see below | verticalSpeedString | see below |
| Average wind | mean of wind[*].speed (m/s) | windSpeedString | never: shows 0 km/h when no wind was estimated |
| Water | logbook waterBalast in litres | localised measurement (shortWaterValue) | the flight is not in the logbook; 0 litres is shown |
Take-off performance is the average climb from take-off to release, in m/s:
if release.pressureAltitude == 0: gain = release.gpsAltitude − takeoff.gpsAltitude (nil if either GPS altitude is nil, e.g. a 2D fix)else: gain = release.pressureAltitude − takeoff.pressureAltitudedt = release.time − takeoff.time (local time, not rawTime)takeoffPerformance = dt > 0 ? gain / dt : nilThe figure is nil without a release or take-off fix. A tow climb therefore shows the average tow climb rate,
and a winch launch the winch climb rate.
4.2 Cruise
Section titled “4.2 Cruise”| Row | Formula | Format | Missing when |
|---|---|---|---|
| Cruise duration | totalCruisingTime = Σ leg.duration | timeValue | no legs (legs == nil); an empty leg list gives 00:00:00 |
| Cruise speed | (Σ leg.distance / 1000) / (Σ leg.duration / 3600) / 3.6 m/s | speedString | either sum is not above 0 |
| Glide ratio (average L/D) | Int(Σ leg.distance / Σ leg.altitudeDifference) × −1 | ldString, e.g. 42:1 | no distance, or a total altitude difference of 0 |
leg.distanceis the leg’s 5-turnpoint optimised distance, not its path length (flight analysis §2.4).leg.altitudeDifference = end.pressureAltitude − start.pressureAltitude, which is negative on a descending glide. The negation makes the ratio positive. The division is truncated toward zero before the negation.- If the glides gained height overall, the ratio is negative and shows as e.g.
-35:1. Nothing clamps it. - A flight without thermals and without engine runs has no legs at all (flight analysis §5.5), so every cruise row is missing.
Cruise versus thermal split. The app never sums the two as a pair. Thermalling time is
totalThermallingTime (Σ thermal durations, shown as a share of duration on the summary’s Thermals row). Cruise
time is totalCruisingTime (Σ leg durations). The two do not add up to the flight time. Engine runs and the legs dropped for being no longer than
minimumLegDuration count as neither (flight analysis §5.5).
4.3 Engine
Section titled “4.3 Engine”This section shows only when engineRegistrationType is not empty, meaning some fix has ENL or MOP enabled.
| Row | Value | Missing when |
|---|---|---|
| Engine type | "ENL", "MOP" or "ENL + MOP" | — |
| Engine runs | "#" + engineRuns.count (countValue) | count is 0 |
| Engine duration | engineRunTime = Σ run.duration (timeValue) | the sum is 0 |
4.4 Flap usage
Section titled “4.4 Flap usage”This section shows only when the log has more than one flap label. It is one bar per label, and each bar’s value is the number of fixes recorded at that flap position. That is a count of fixes, not of seconds, so it is only proportional to time at a constant logging interval.
Source: vulture-ios/Packages/FlightScreens/Sources/FlightScreens/FlightDetail/Tabs/DetailTabFlightViewModel.swift,
vulture-ios/Packages/Flights/Sources/Flights/Models/Flight.swift (takeoffPerformance, totalCruisingTime,
averageCruisingSpeed, averageGlideRatio, engineRunTime, averageWindSpeed);
vulture-android/domain/flightdetail/src/main/kotlin/be/fousa/vulture/domain/flightdetail/FlightTab.kt,
vulture-android/domain/flight/src/main/kotlin/be/fousa/vulture/domain/flight/model/FlightStatistics.kt,
Flight.kt (takeoffPerformance).
Platform differences.
- Water: Android uses plural resources (
FIXED(B27)). The value is the same. - Glide ratio: both platforms format with
ldStringtoday. The Android commentFIXED(B26)says that iOS showed the bare integer, but the current iOS code uses.ldStringtoo. - Average wind: iOS averages the values of a dictionary, which has no order. The floating-point sum can therefore differ in the last bit between runs. That never changes the 0-decimal display.
5. Info page
Section titled “5. Info page”These are identity strings, not calculations. The logbook value wins over the IGC header value when the logbook
value is not nil. On the Info and Flight pages a blank logbook value still wins and hides the row. Only the
summary’s caption and title treat a blank value as missing (nonEmpty). The logger, FLARM, GPS and sensor rows
come straight from the IGC header.
Source: vulture-ios/Packages/FlightScreens/Sources/FlightScreens/FlightDetail/Tabs/DetailTabInfoViewModel.swift.
6. Declared task and optimisation detail
Section titled “6. Declared task and optimisation detail”The summary’s Declared task row and each tappable optimisation row open the same screen, built from a
DetailOptimizationItem. For the declared task, the item wraps bestTaskAttempt together with the task.
6.1 Metric tiles
Section titled “6.1 Metric tiles”| Tile | Value | Shown when |
|---|---|---|
| Distance | as in §3.2 | always (an empty string drops it) |
| Speed | averageSpeed.speedString | always, including 0 km/h |
| Start height | TaskAttempt.startAltitude = pressure altitude of the first credited fix | a task attempt with ≥ 2 credited fixes and a positive duration |
| Start speed | startGroundSpeed = ground speed of the first credited fix | same |
| Finish height | finishAltitude = pressure altitude of the fix credited for the finish | the attempt is completed |
| Relative finish height | finishAltitude − finishZone.minimumAltitude | completed and the finish zone has a minimum (Elev) |
| AAT duration | (finish.rawTime − start.rawTime) − minimumAATDuration | completed and the task has a minimum AAT time |
| Detour | totalDetourDistance | > 0 |
A free optimisation is an Optimization, not a TaskAttempt, so it has no start, finish, relative or AAT
values. Its screen shows only distance, speed and detour.
Signed tiles. The relative finish height and the AAT duration both show a sign and a colour:
text = (d >= 0 ? "+" : "-") + format(|d|) // altitudeString or timeValuetint = d >= 0 ? success (green) : brand (orange)A difference of exactly 0 shows +0 m in green. The TaskAttempt doc comments say the differences are nil
“when it was respected”, but the code sets them whenever both inputs exist.
Pressure-altitude fallback. finishAltitude is computed as finishFix?.pressureAltitude ?? finishFix?.gpsAltitude, and startAltitude the same way. pressureAltitude is never nil, so the GPS fallback
never applies. A log with no baro already carries GPS values in pressureAltitude (§1.4).
6.2 Legs
Section titled “6.2 Legs”There is one row per pair of consecutive credited fixes. A pair whose duration or distance is 0 is skipped, as happens when two turnpoints are credited at one fix. For a declared task, each waypoint the attempt never reached is then added as a failed leg.
| Value | Formula |
|---|---|
| Time | the leg’s end fix time (timeValue) |
| Distance | haversine(previousFix, fix), 6371 km sphere (distanceString) |
| Speed | (distance / 1000) / (duration / 3600) / 3.6, duration = fix.rawTime − previousFix.rawTime |
| Thermal vario | Σ altitudeGained / Σ duration over the thermals that lie entirely within the leg’s time span; nil without any |
| Thermal share | Σ thermal duration / leg duration × 100 (percentageValue); nil when 0 |
| Detour | §6.3 |
| Status | success, fail or unknown (shown as the leg number), from the best task attempt |
The leg distances use the 6371 km haversine, but the headline distance uses the 6378.137 km optimisation path (flight analysis §13 item 5). So the legs do not add up exactly to the headline distance.
The leg item also computes the cruise speed and glide ratio over the flight’s legs inside the leg. When those
glides lose no height, it falls back to Int(distance / (first.pressureAltitude − last.pressureAltitude)) over
the leg’s own fixes. The leg row does not show these values. Compare and the Debrief read them; see
Compare, ranking and statistics.
An unflown leg shows the declared distance: waypoint.distance, else the haversine from the previous
waypoint. Instead of measured values it shows the declared bearing: waypoint.bearing, else the bearing from the
previous waypoint, formatted "%i°". Every measured value is empty.
6.3 Detour
Section titled “6.3 Detour”The detour is the extra distance flown over a leg compared to its straight line, not counting the circling.
flown = 0; i = 1while i < legFixes.count: if legFixes[i].thermal != nil: last = last index j in legFixes where legFixes[j].thermal === legFixes[i].thermal flown += haversine(legFixes[i−1], legFixes[last]); i = last + 1 // a thermal counts as entry → exit else: flown += haversine(legFixes[i−1], legFixes[i]); i += 1detour = flown − legDistancelegDetour = detour > 100 m ? detour : niltotalDetourDistance = Σ legDetour over the legs that have one, or nil when none haslegFixes is flight.fixes[indexes[k−1] ... indexes[k]]. fix.thermal is also set for rejected thermal
candidates (flight analysis §13 item 9), so their circling is collapsed too. The 100 m threshold applies per leg,
before the sum.
| Constant | Value |
|---|---|
| Minimum leg detour | 100 m (strictly greater) |
| Earth radius | 6371 km |
Source: vulture-ios/Packages/FlightScreens/Sources/FlightScreens/Models/DetailOptimizationItem.swift,
DetailOptimizationItem+Legs.swift, OptimizedLeg.swift,
vulture-ios/Modules/App/Sources/Map/OptimizationDetail/OptimizationDetailViewModel.swift,
OptimizationDetailView.swift (OptimizationLegRow),
vulture-ios/Packages/Flights/Sources/Flights/Models/TaskAttempt.swift (finalize(for:));
vulture-android/domain/flightdetail/src/main/kotlin/be/fousa/vulture/domain/flightdetail/DetailOptimizationItem.kt,
OptimizationDetail.kt. Same as iOS. Android numbers the legs by their position in the list, 1…n
(FIXED(B31)–FIXED(B33)).
6.4 Task page (task map)
Section titled “6.4 Task page (task map)”The task popup opened from the task map shows the task’s own figures. Each tile is dropped when its value is missing.
| Tile | Value |
|---|---|
| Distance | task.distance: the sum of the waypoint leg distances, recomputed whenever the waypoints change |
| Minimum height | the finish zone’s minimumAltitude (altitudeString) |
| Minimum time | task.minimumAATDuration (timeValue) |
When the popup is opened from a flight, it also shows the attempt status and the task optimisation row (§3.2).
Source: vulture-ios/Packages/FlightScreens/Sources/FlightScreens/FlightDetail/Tabs/DetailTabTaskViewModel.swift;
vulture-android/feature/taskmap/src/main/kotlin/be/fousa/vulture/feature/taskmap/TaskDetailModel.kt.
7. Phases page
Section titled “7. Phases page”The timeline is flight.phases: thermals, cruise legs, engine runs and event fixes, sorted as in flight
analysis §2.6. The page’s filter shows all of them, or only one kind.
| Phase | Time | Caption | Value | Value detail |
|---|---|---|---|---|
| Event | fix.time | take-off and landing: "{pressureAltitude} MSL"; every other event: "{pressureAltitude − elevation} AGL" | — | — |
| Thermal | entryTime | duration.veryShortTimeValue | thermal.vario (vertical speed); greyed when < 0 | altitudeGained, with + when > 0 (+620 m, -10 m, 0 m) |
| Cruise | leg.startFix.time | leg.averageSpeed (speedString) | leg.distance (distanceString) | "{averageGlideRatio}:1", missing when nil |
| Engine run | startFix.time | duration.timeValue | — | — |
- The “MSL” and “AGL” suffixes are hard-coded English on both platforms.
- The event caption for the high and low points of the height gain uses AGL, which equals MSL without terrain data (§1.4).
leg.averageSpeed = (distance/1000)/(duration/3600)/3.6, with no guard. A leg’s duration is always aboveminimumLegDuration, so the division is safe.- The leg glide ratio follows the same rule as the flight’s (§4.2): it is truncated, then negated, and
nilwhen the distance is 0 or the altitude change is 0.
The summary’s Phases row counts every phase. Its caption counts the cruise phases (§2.2).
Source: vulture-ios/Packages/FlightScreens/Sources/FlightScreens/FlightDetail/Tabs/DetailTabPhasesViewModel.swift,
.../FlightDetail/Rows/DetailItemRow.swift (eventRow, thermalRow, cruiseRow, engineRow,
Fix.altitudeString, Thermal.altitudeGainedString);
vulture-android/domain/flightdetail/src/main/kotlin/be/fousa/vulture/domain/flightdetail/PhasesTab.kt. Same as
iOS.
8. Map readings
Section titled “8. Map readings”8.1 Readings line
Section titled “8.1 Readings line”The panel’s readings line shows the selected flight at the replay position (currentFix). The readings come in
order of importance. The line shows as many as fit at full type size and drops the rest from the end.
| # | Reading | Value | Unit label | -- when |
|---|---|---|---|---|
| 1 | Altitude | fix.pressureAltitude | altitude unit | no fix |
| 2 | Vario | fix.vario (smoothed, flight analysis §3.6) | vertical-speed unit | no fix |
| 3 | Ground speed | fix.groundspeed | speed unit | no fix |
| 4 | Height above ground | fix.pressureAltitude − fix.elevation | altitude unit + AGL | no fix |
| 5 | Distance | fix.distanceTraveled × 1000 (the field is in km) | distance unit | no fix |
| 6 | Average or task speed | task: fix.averageTaskSpeed; else fix.averageSpeed | speed unit + task or avg | no fix, or the speed ≤ 0 |
| 7 | Track | ((bearing % 360) + 360) % 360 + ° | — | no fix, or the fix has no bearing (the first fix) |
The values use the formatters of §1.1 with the unit hidden. The unit is drawn separately in a smaller, fainter
style. The “task” label and the task speed apply when the flight has a bestTaskAttempt, finished or not.
What the distance and speed readings mean comes from the speed enricher (flight analysis §7.6):
- Average or task speed is a rolling average over the last 60 minutes of distance along the optimised
path. It is not an average since the start:
sum60 / (max(1, t − t₆₀) / 3600) / 3.6. The free pass fillsaverageSpeedalong the free-distance optimisation. The task pass fillsaverageTaskSpeedalong the best task attempt’s credited fixes. - Distance is the distance travelled along the optimised path:
distance of the earlier legs + leg length − distance still to the next turnpoint. The task pass runs after the free pass and overwritesdistanceTraveledwithin the task’s fix range. Within that range the reading is therefore the task distance, even when the speed reading is the free one. - A fix outside the optimised range keeps its default of 0. This includes fixes before the first turnpoint and
the last turnpoint’s own fix and everything after it, unless the other pass covered them. Such a fix shows
0.00 kmand an average speed of--.
| Constant | Value |
|---|---|
| Average window | 3600 s |
| Empty-reading text | -- |
| Column width templates | 88888 altitude, -88.8 vario, 888 speed, 88888 AGL, 888.88 distance, 888 average, 888° track |
The templates only size the columns, so a changing value does not move its neighbours. They have no effect on the values.
8.2 Barogram readout
Section titled “8.2 Barogram readout”The scrubber bubble on the barogram formats its own values. See map-barogram §4.4. It is also the only place where the pressure or GPS altitude choice applies.
8.3 Shareable map snapshot strip
Section titled “8.3 Shareable map snapshot strip”When a replay position is selected, the snapshot strip shows these values:
| Value | Format |
|---|---|
| Time | fix.time.timeValue, after the date |
| Speed | fix.groundspeed.speedString |
| Vario | vertical speed with 1 decimal (numberOfFractionDigits = 1) |
| MSL | fix.pressureAltitude.altitudeString |
| AGL | pressureAltitude − elevation, only when isElevationAvailable |
Without a selected fix the strip shows only the identifier and the date.
Source: vulture-ios/Modules/App/Sources/Map/Flight/Flight/FlightViewModel.swift (PanelFlightItem
conformance, snapshotContent()), .../Panel/Flights/Cells/PanelFlightReadoutView.swift,
PanelFlightItem.swift, vulture-ios/Packages/Flights/Sources/Flights/Enricher/FlightSpeedEnricher.swift;
vulture-android/feature/flightmap/src/main/kotlin/be/fousa/vulture/feature/flightmap/model/FlightMapPresentation.kt
(panelFlightItems, averageSpeedString, trackString), .../model/SnapshotContent.kt,
.../panel/FlightStrip.kt. Same as iOS.
9. Figures the flight detail does not show
Section titled “9. Figures the flight detail does not show”- Handicapped speed. Neither the flight detail nor the readings line divides by a handicap. The handicap, which comes from the competition a flight was opened from, is used only by the race ranking during a replay. See Compare, ranking and statistics.
- Maximum and minimum heights. The detail pages have no maximum or minimum height figure. The highest and
lowest points of the height gain appear as events on the Phases page (§7). The flight’s
min/maxPressureAltitudeset the barogram scale and the altitude colour ramp (map-barogram §3.2, §4.4), andmaximumPressureAltitudepre-filters the airspace scan (map-barogram §5.7).
