Code Monkey home page Code Monkey logo

flare-timing's Introduction

Flare Timing

stack cabal pier docs

Important

This project depends on uom-plugin-0.3.0.0 that was constrained to use ghc <= 8.2. A new version, uom-plugin-0.4.0.0, has been released that works with ghc >= 9 so this project could now be upgraded.

Flare Timing is a reference implementation of GAP scoring for cross country hang gliding and paragliding racing.

Its command line console apps, one for each step in scoring, write down their workings along with their outputs. With these workings we can trace how a pilot's score has been calculated. There's no visual competition editor. The one file that defines a competition can be generated from an FS database, the *.fsdb file. It includes a web app that can be hosted locally for visual checks and comparisons with expected or official results. It is possible to publish the data alongside this web app standalone as done at flaretiming, the web site.

Installation

Download the source, build and install the command line apps with stack or with ghc and cabal that can be installed with ghcup:

> git clone https://github.com/BlockScope/flare-timing.git --recursive
> cd flare-timing/lang-haskell

# with stack
> stack install

# with cabal supplying options --installdir and --overwrite-policy
> cabal v2-install all:exes

There's more in the building guide. There's a guide for testing too.

Usage

Let's get the inputs and outputs from FS, do the scoring and host the comp locally.

Start by preparing the FS comp file, the *.fsdb. This will often contain sensitive personal information such as birthdays, phone numbers and notes that we'll want to avoid publishing. We'll also want some output data for making comparisons between flare-timing and FS.

  1. Clean out the sensitive pilot personal stuff we don't need with fs-clean.
  2. Trim away data we don't need with fs-trim.
  3. Grab the optimal route around the tasks found by FS with fs-route.
  4. Grab the arrival times and positions from FS with fs-arrival.
  5. Grab the landouts from FS with fs-effort.
  6. Grab the scores from FS with fs-score.

That's the *.fsdb file done with. From here on, flare-timing deals with the trimmed XML, the *.trim-fsdb.xml. If we have the track logs we can score the tasks:

  1. Extract the inputs with ft-extract-input.
  2. Trace the shortest path to fly a task with ft-task-length.
  3. Find flying times with ft-fly-time.
  4. Find pairs of fixes crossing over zones with ft-cross-zone.
  5. Interpolate between crossing fixes for the time and place where a track tags a zone with ft-tag-zone.
  6. Unpack the *.igc or *.kml tracklogs with ft-unpack-track.
  7. Peg the timing window to a reference frame with ft-peg-frame.
  8. Index fixes from the time of first crossing with ft-align-time.
  9. Discard fixes that get further from goal and note leading area with ft-discard-further.
  10. Draw out leading areas ft-lead-area.
  11. Mask a task over its tracklogs with the following, run in any order:
  12. Group and count land outs with ft-land-out.
  13. Group and count far outs with ft-far-out.
  14. Score the competition with ft-gap-point.

To get the backend server for hosting the comp data running locally:

Start the server with ft-comp-serve.

To host the frontend web app for the comp locally:

  1. Change directory: > cd lang-haskell
  2. Open a try-reflex shell with: > reflex-platform/try-reflex
  3. Build the frontend and start its webpack dev server with: > ../stack-shake-build.sh view-start-ghcjs
  4. Open a browser at the hosted URL, usually http://localhost:9000/app.html.

Documentation is available online at flare-timing.readthedocs.io and there's a worked example too.

What's Included

The GAP rules have changed over the years. Here are the features that flare-timing includes or not.

  • Scoring Method
    • GAP
      • GAP2000
      • GAP2002
      • OzGAP2005
      • GAP2007
      • GAP2008
      • GAP2011 tested with:
        Forbes 2012 , Forbes 2014 , Forbes 2015
      • GAP2013 tested with:
        Forbes 2017
      • GAP2014
      • GAP2015 tested with:
        Big Spring 2016 , Green Swamp 2016 , Green Swamp Sport 2016 , Forbes 2016 , Quest 2016
      • GAP2016 tested with:
        Dalmatian 2018 , Dalby 2017 , Forbes 2018 , Forbes 2019
      • GAP2018 tested with:
        Dalmatian 2019 , Italy 2019
      • GAP2020
    • PWC (GAP variant)
      • PWC2007
      • PWC2008
      • PWC2009
      • PWC2011
      • PWC2012
      • PWC2013
      • PWC2014
      • PWC2015
      • PWC2016
      • PWC2017
      • PWC2019
    • Linear distance
    • Time-based scoring (TBS)
  • Earth Model
    • FAI sphere
    • WGS84 ellipsoid
  • Distance Method
    • Pythagorus on a UTM plane
    • Haversines on the sphere
    • Vincenty on the ellipsoid
    • Andoyer on the ellipsoid
  • Type of Task
    • Race
    • Elapsed time
    • Open distance (can be declared but not yet scored)
  • Shape of Zone
    • Cylinder
    • Inverted cone (can be defined but treated as a cylinder)
  • Shape of Goal
    • Circle
    • Line
  • Final Glide Decelerator
    • Conical end of speed section (CESS)
    • Arrival altitude time bonus (AATB)
  • Source of Altitude
    • GPS
    • Pressure (QNH)
  • Validities
    • Task (day quality)
    • Launch
    • Distance
    • Time
    • Stop
  • Points
    • Linear distance (reach)
    • Distance difficulty (effort)
    • Arrival position
    • Arrival time
    • Time (speed)
    • Leading
    • Departure
  • Leading Area as a Function of Time and Distance Tweaks
    • Use distance; a = t * d
    • Use distance squared; a = t * d^2
    • Use PWCA weighting; a = w(t, d)
  • Parameter Tweaks
    • Day quality override
    • 1000 points for winner if no pilot made goal
    • 1000 points for winner before day quality applied
    • Double leading points weight
    • Proportional leading points weight if no pilot made goal
    • Adjustable stopped task bonus glide ratio (fixed at 4:1 for PG and 5:1 for HG)
  • Special Cases
    • End of the speed section but not goal
    • Early start
    • Stopped tasks
  • Stopped Tasks
    • Stopped task time as announcement minus score back
    • Requirements checking, goal or duration
    • Score time window
    • Time points for pilots at or after the end of the speed section
    • Distance points with altitude bonus
  • Penalties
    • Absolute
    • Fractional
    • Jump-the-gun factor
    • Jump-the-gun maximum
    • Made ESS but not goal
  • Task Ranking
    • Overall
    • Female
    • Country
  • Competition Ranking
    • Overall
    • Female
    • Country
    • Ties
    • Fixed Total Validity

License

Copyright © Phil de Joux 2017-2020
Copyright © Block Scope Limited 2017-2020

This software is subject to the terms of the Mozilla Public License, v2.0. If a copy of the MPL was not distributed with this file, you can obtain one at http://mozilla.org/MPL/2.0/.

flare-timing's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

tierninho mfkiwl

flare-timing's Issues

parseTimeOrError: no parse of "2012-01-12T02:09:58"

$ __shake-build/mask-track "--file=/data/Australia Forbes 2012.comp-input.yaml" --task=6

mask-track: parseTimeOrError: no parse of "2012-01-12T02:09:58"
CallStack (from HasCallStack):
  error, called at libraries/time/lib/Data/Time/Format/Parse.hs:116:12 in time-1.6.0.1:Data.Time.Format.Parse

Read stopped task inputs

There's scoring logic in flight-gap for stopped tasks but these are not wired up. We'll need to read when the tasked was stopped from the *.fsdb as an input and then feed this into the scoring.

Function showSci is rounding but toSci and encode are not

With package detour-via-sci showSci is rounding but toSci and encode are not.

>>> let x = 0.1122334455667788
>>> showSci (DecimalPlaces 8) x
"0.11223345"
>>> let x = 1122334455667788 % 10000000000000000
>>> toSci (DecimalPlaces 8) x
0.11223344
>>> encode (Lat x)
"0.11223344"
>>> Csv.encode [("A", Lat x)]
"A,0.11223344\r\n"

Ratio has zero denominator testing flight-earth

earth> stack ghci flight-earth:earth
:main --pattern=outside
...
          From origin (0°,-180°) bearing r = 0.0
            No points > [u| 0.0 mm |] outside a [u| 4.0e-2 km |] cylinder
              when searching within [u| 1.0e-3 m |]:    FAIL
              Exception: Ratio has zero denominator
...
          From origin (0°,-180°) bearing r = 120.0
            No points > [u| 0.0 mm |] outside a [u| 4.0e-2 km |] cylinder
              when searching within [u| 1.0e-3 m |]:    FAIL
              Exception: Ratio has zero denominator
...
          From origin (0°,0°) bearing r = 0.0
            No points > [u| 0.0 mm |] outside a [u| 4.0e-2 km |] cylinder
              when searching within [u| 1.0e-3 m |]:    FAIL
              Exception: Ratio has zero denominator

No instance for KnownUnit printing stopped in fsdb parser

> stack install
...
/.../flare-timing/flare-timing/test-apps/fsdb-parser/FsdbMain.hs:95:35: error:
    • No instance for (Data.UnitsOfMeasure.Singleton.KnownUnit
                         (Data.UnitsOfMeasure.Internal.Unpack
                            (Data.UnitsOfMeasure.Internal.Base "s")))
        arising from a use of ‘print’
    • In the expression: print stopped'
      In a case alternative: Right [Just stopped'] -> print stopped'
      In a stmt of a 'do' block:
        case stopped of
          Left msg -> print msg
          Right [Just stopped'] -> print stopped'
          Right _ -> putStr "Expected only one score back time."
   |
95 |          Right [Just stopped'] -> print stopped'
   |                                   ^^^^^^^^^^^^^^
Failed, one module loaded.

Failing 3 out of 215 tests for flight-gap:score

> stack test flight-gap:score
...
        No penalties = sum of distance, leading, time & arrival points:                        FAIL
          /Users/pdejoux/dev/src/blockscope/flare-timing/gap/test-suite-score/Points.hs:39:
          expected: TaskPoints (4 % 1)
           but got: TaskPoints (5 % 1)
...
        Somewhat early start HG = full points minus jump the gun penalty:                      FAIL
          /Users/pdejoux/dev/src/blockscope/flare-timing/gap/test-suite-score/Points.hs:78:
          expected: TaskPoints (39 % 1)
           but got: TaskPoints (49 % 1)
...
      Can score a stopped task, Pg:                                                            FAIL
        *** Failed! Falsifiable (after 100 tests):
        StopCanScoreTest (FromLastStart [7839s,9739s,6332s,6070s,8438s,6497s,692s,8282s,5040s,7785s,93s,361s,3414s,6040s,1883s,9166s,3781s,4228s,5835s,5860s,691s,640s,5775s,2809s,2637s,7648s,3007s,7290s,2282s,2149s,528s,498s,5310s,1305s,897s,9907s,7578s,9434s,8171s,4590s,2463s,6988s,1928s,5105s,5558s,2749s,971s,5041s,9057s,380s,4954s,2358s,1906s,6417s,9251s,2243s,8682s,4858s,2386s,8955s,866s,3938s,3752s,1547s,4489s,533s,6352s,3321s,3386s,6410s,6714s,3551s,7783s,663s,762s,7432s,3596s,318s,2407s,2162s,7792s,6132s,6940s,9405s,881s,5415s,2264s,5266s,2734s,8319s,9003s,4696s,1782s,3486s] (TaskStopTime (615402169662642 % 143444252249)))
        Use --quickcheck-replay=974869 to reproduce.
...
3 out of 215 tests failed (449.51s)

Merge the earth-* packages.

Please merge the earth-flat, earth-sphere and earth-ellipsoid packages into one package, including tests.

Expecting "A", expecting xml reading what looks like *.igc

> ../../bin/cross-zone --file=forbes2018.comp-input.yaml
Reading competition from 'forbes2018.comp-input.yaml'

error: ""ABRA02486\r\nHFDTE301217\r\nHFFXA100\r\nHFPLTPILOT:..."" (line 1, column 1):
unexpected "A"
expecting xml declaration, comment, processing instruction, "<!DOCTYPE" or "<"

error: ""AXCGAventura  3.0|C17B-20520095\r\nHFDTE301217\r..."" (line 1, column 1):
unexpected "A"
expecting xml declaration, comment, processing instruction, "<!DOCTYPE" or "<"

Pickup the uom-plugin from hackage, not from git.

Remove the following from stack.yaml now that uom-plugin-0.3.0.0 is up on hackage;

- location:
    git: https://github.com/blockscope/uom-plugin.git
    commit: c170a2df329fe8e40d13aea0b4299758d5079bda
  subdirs:
  - uom-plugin
  extra-dep: true

MakeTravisYml file name does not match module name

When building on windows;

> stack install
...
    Configuring haskell-ci-0...
    Preprocessing library for haskell-ci-0..
    Building library for haskell-ci-0..

    ←[;1msrc\MakeTravisYml.hs:1:1: ←[;1m←[31merror:←[0m←[0m←[;1m←[0m←[0m←[;1m
        File name does not match module name:
        Saw: `Main'
        Expected: `MakeTravisYml'←[0m←[0m

Build docs for packages depending on flight-units

The flight-units package builds but its documentation fails to build.

> stack haddock flight-units
...
haddock: internal error: renameType: HsSpliceTy
CallStack (from HasCallStack):
  error, called at utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs:267:30
in main:Haddock.Interface.Rename

Run cross-zone, mistakenly check *.cross-zone.yaml

> ../../bin/cross-zone "--file=2018 XC Dalmatian Paragliding Open"
The --dir argument is not a directory or the --file argument is not a file.
The file checked for was '2018 XC Dalmatian Paragliding Open.cross-zone.yaml'.

Read start gates

For instance, task 3 from greda 2018 has one start gate.

    <FsTaskDefinition ss="2" es="7" goal="CIRCLE" groundstart="0">
      <FsTurnpoint ... />
      <FsStartGate open="2018-05-27T13:00:00+02:00" />
    </FsTaskDefinition>

With cross-zone getting invalid byte sequence in *.igc

> ../../bin/cross-zone --file=forbes2016.comp-input.yaml
Reading competition from 'forbes2016.comp-input.yaml'
cross-zone: day 1/Gijs_Wanders.20160102-192026.[CIVLID].7.igc:
hGetContents: invalid argument (invalid byte sequence)

Error in $: key "dnf" not present when tag-zone gets comp-input

The command tag-zone expect a *.cross-zone.yaml file as input but all other commands expect a *.comp-input.yaml file. If one of those is given instead there's this error;

> ../../bin/tag-zone --file=forbes2016.comp-input.yaml
Reading zone crossings from 'forbes2016.comp-input.yaml'
Error in $: key "dnf" not present
Tagging zones completed in 13.06 ms

The default stack-shake build fails stack-test-kml-parser

> ./stack-shake-build.sh
# dhall-format (for dhall-format-zone)
# hpack-dhall (for hpack-dhall-zone)
zone/flight-zone.cabal is up-to-date
...
# dhall-format (for dhall-format-aeson-via-sci)
# hpack-dhall (for hpack-dhall-aeson-via-sci)
aeson-via-sci/aeson-via-sci.cabal is up-to-date
Error when running Shake build system:
* stack-test-apps
* stack-test-kml-parser
Error, file does not exist and no rule available:
  stack-test-kml-parser
CallStack (from HasCallStack):
  error, called at src/Development/Shake/Internal/Rules/File.hs:180:58
in shake-0.16.4-KMeoCwUNS3d5jzYY220kU9:Development.Shake.Internal.Rules.File

Error: Multiple files use the same module name with stack ghci

Even though stack ghci in the root of this repo is not something I use, I thought I'd try it anyway and got this error;

Error: Multiple files use the same module name:
       * Driver found at the following paths
         * /.../build/app-cmd/Driver.hs (build-flare-timing:exe:build-flare-timing)
         * /.../flare-timing/prod-apps/align-time/Driver.hs (flare-timing:exe:align-time)
         * /.../flare-timing/prod-apps/cross-zone/Driver.hs (flare-timing:exe:cross-zone)
         * /.../flare-timing/prod-apps/discard-further/Driver.hs (flare-timing:exe:discard-further)
         * /.../flare-timing/prod-apps/extract-input/Driver.hs (flare-timing:exe:extract-input)
         * /.../flare-timing/prod-apps/gap-point/Driver.hs (flare-timing:exe:gap-point)
         * /.../flare-timing/prod-apps/land-out/Driver.hs (flare-timing:exe:land-out)
         * /.../flare-timing/prod-apps/mask-track/Driver.hs (flare-timing:exe:mask-track)
         * /.../flare-timing/prod-apps/tag-zone/Driver.hs (flare-timing:exe:tag-zone)
         * /.../flare-timing/prod-apps/task-length/Driver.hs (flare-timing:exe:task-length)
         * /.../flare-timing/test-apps/fsdb-parser/Driver.hs (flare-timing:exe:test-fsdb-parser)
         * /.../flare-timing/test-apps/igc-parser/Driver.hs (flare-timing:exe:test-igc-parser)
         * /.../flare-timing/test-apps/kml-parser/Driver.hs (flare-timing:exe:test-kml-parser)
       * Options found at the following paths
         * /.../flare-timing/prod-apps/align-time/Options.hs (flare-timing:exe:align-time)
         * /.../flare-timing/prod-apps/cross-zone/Options.hs (flare-timing:exe:cross-zone)
         * /.../flare-timing/prod-apps/discard-further/Options.hs (flare-timing:exe:discard-further)
         * /.../flare-timing/prod-apps/extract-input/Options.hs (flare-timing:exe:extract-input)
         * /.../flare-timing/prod-apps/gap-point/Options.hs (flare-timing:exe:gap-point)
         * /.../flare-timing/prod-apps/land-out/Options.hs (flare-timing:exe:land-out)
         * /.../flare-timing/prod-apps/mask-track/Options.hs (flare-timing:exe:mask-track)
         * /.../flare-timing/prod-apps/tag-zone/Options.hs (flare-timing:exe:tag-zone)
         * /.../flare-timing/prod-apps/task-length/Options.hs (flare-timing:exe:task-length)
         * /.../flare-timing/test-apps/fsdb-parser/Options.hs (flare-timing:exe:test-fsdb-parser)
         * /.../flare-timing/test-apps/igc-parser/Options.hs (flare-timing:exe:test-igc-parser)
         * /.../flare-timing/test-apps/kml-parser/Options.hs (flare-timing:exe:test-kml-parser)
* * * * * * * *

Not attempting to start ghci due to these duplicate modules.
Use --no-load to try to start it anyway, without loading any modules (but these are still likely to cause errors)
``

The cabal build could not resolve dependencies

The cabal build fails.

flare-timing> cabal new-build all
cabal: Could not resolve dependencies:
[__0] trying: aeson-via-sci-0.1.0 (user goal)
[__1] trying: template-haskell-2.13.0.0/installed-2.1... (dependency of
aeson-via-sci)
[__2] next goal: uom-plugin (user goal)
[__2] rejecting: uom-plugin-0.2.0.1 (conflict:
template-haskell==2.13.0.0/installed-2.1..., uom-plugin =>
template-haskell>=2.9 && <2.13)
[__2] rejecting: uom-plugin-0.2.0.0, uom-plugin-0.1.1.0, uom-plugin-0.1.0.0
(constraint from user target requires ==0.2.0.1)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: template-haskell, uom-plugin,
aeson-via-sci

Test suite flight-task:task fails to build

> stack ghci flight-task:task

/.../flare-timing/task/test-suite-task/EdgeToEdge.hs:33:1: error:
    Could not find module ‘Flight.Sphere.PointToPoint.Rational’
    Perhaps you meant
      Flight.Earth.Sphere.PointToPoint.Rational (from flight-earth-0.1.0)
      Flight.Earth.Flat.PointToPoint.Rational
    Use -v to see a list of the files searched for.
   |
33 | import qualified Flight.Sphere.PointToPoint.Rational as Rat
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

/.../flare-timing/task/test-suite-task/EdgeToEdge.hs:35:1: error:
    Could not find module ‘Flight.Sphere.Cylinder.Rational’
    Perhaps you meant
      Flight.Earth.Sphere.Cylinder.Rational (from flight-earth-0.1.0)
    Use -v to see a list of the files searched for.
   |
35 | import qualified Flight.Sphere.Cylinder.Rational as Rat (circumSample)
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/.../flare-timing/task/test-suite-task/EdgeToEdge.hs:37:56: error:
    Module ‘Flight.Task’ does not export ‘separatedZones’
   |
37 | import Flight.Task (Zs(..), AngleCut(..), CostSegment, separatedZones)
   |                                                        ^^^^^^^^^^^^^^
Failed, three modules loaded.

Use the participant identifier

Use the participant identifier from the *.fsdb. Test a competition with duplicate pilot names.

<FsParticipant id="1" name="..." />

Serialise time as HH:MM:SS.SS

In *.gap-point.yaml, elapsed time is serialised as fractional hours with the unit symbol. Could we instead serialise it as the more human readable HH:MM:SS.SS?

  velocity:
    ss: 2018-05-27T11:15:45Z
    gs: 2018-05-27T11:00:00Z
    es: 2018-05-27T12:23:54Z
    distance: 30.9 km
    ssElapsed: 1.135833 h
    gsElapsed: 1.398333 h

Read when the goal is a line

When the comp inputs are extracted from .fsdb, please read when the goal is a line.

<FsTaskDefinition ss="2" es="5" goal="LINE" groundstart="0">

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.