{"id":32159834,"url":"https://github.com/glideangle/flare-timing","last_synced_at":"2026-02-22T11:03:02.564Z","repository":{"id":38986877,"uuid":"102285202","full_name":"GlideAngle/flare-timing","owner":"GlideAngle","description":"Scoring for free flight competitions.","archived":false,"fork":false,"pushed_at":"2024-03-07T16:23:07.000Z","size":11842,"stargazers_count":12,"open_issues_count":145,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-14T06:56:41.763Z","etag":null,"topics":["ghcjs","gps","haskell-application","haversines","igc","kml","reflex-frp","servant","shortest-path","utm","vincenty","wgs84"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GlideAngle.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"philderbeast"}},"created_at":"2017-09-03T18:24:05.000Z","updated_at":"2024-12-27T00:06:56.000Z","dependencies_parsed_at":"2024-11-13T13:53:10.266Z","dependency_job_id":null,"html_url":"https://github.com/GlideAngle/flare-timing","commit_stats":{"total_commits":5218,"total_committers":3,"mean_commits":"1739.3333333333333","dds":0.06075124568800305,"last_synced_commit":"90cc11b39a16e0ef0a859a4815cef6c8c560c32e"},"previous_names":["blockscope/flare-timing"],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/GlideAngle/flare-timing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlideAngle%2Fflare-timing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlideAngle%2Fflare-timing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlideAngle%2Fflare-timing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlideAngle%2Fflare-timing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GlideAngle","download_url":"https://codeload.github.com/GlideAngle/flare-timing/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlideAngle%2Fflare-timing/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29710317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-22T10:34:24.778Z","status":"ssl_error","status_checked_at":"2026-02-22T10:32:23.200Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ghcjs","gps","haskell-application","haversines","igc","kml","reflex-frp","servant","shortest-path","utm","vincenty","wgs84"],"created_at":"2025-10-21T13:22:50.363Z","updated_at":"2026-02-22T11:03:02.546Z","avatar_url":"https://github.com/GlideAngle.png","language":"Haskell","funding_links":["https://github.com/sponsors/philderbeast"],"categories":[],"sub_categories":[],"readme":"# Flare Timing\n\n![stack](https://github.com/BlockScope/flare-timing/workflows/stack/badge.svg)\n![cabal](https://github.com/BlockScope/flare-timing/workflows/cabal/badge.svg)\n![pier](https://github.com/BlockScope/flare-timing/workflows/pier/badge.svg)\n[![docs](https://readthedocs.org/projects/flare-timing/badge/?version=latest)](https://flare-timing.readthedocs.io/en/latest/?badge=latest)\n\n\u003e [!IMPORTANT]\n\u003e This project depends on `uom-plugin-0.3.0.0` that was constrained to use\n\u003e `ghc \u003c= 8.2`. A new version, `uom-plugin-0.4.0.0`, has been released that\n\u003e works with `ghc \u003e= 9` so this project could now be upgraded.\n\n**Flare Timing** is a reference implementation of [GAP](lang-haskell/GAP.md)\nscoring for cross country hang gliding and paragliding racing.\n\nIts command line console apps, one for each step in scoring, write down their\nworkings along with their outputs. With these workings we can trace how\na pilot's score has been calculated. There's no visual competition editor. The\none file that defines a competition can be generated from an FS database, the\n`*.fsdb` file. It includes a web app that can be hosted locally for visual\nchecks and comparisons with expected or official results. It is possible to\npublish the data alongside this web app standalone as done at [flaretiming, the\nweb site](https://flaretiming.com).\n\n## Installation\n\nDownload the source, build and install the command line apps with\n[stack](https://docs.haskellstack.org) or with ghc and cabal that can be\ninstalled with [ghcup](https://www.haskell.org/ghcup/):\n\n```\n\u003e git clone https://github.com/BlockScope/flare-timing.git --recursive\n\u003e cd flare-timing/lang-haskell\n\n# with stack\n\u003e stack install\n\n# with cabal supplying options --installdir and --overwrite-policy\n\u003e cabal v2-install all:exes\n```\n\nThere's more in the [building](lang-haskell/BUILDING.md) guide. There's a guide for\n[testing](lang-haskell/TESTING.md) too.\n\n## Usage\n\nLet's get the inputs and outputs from FS, do the scoring and host the comp\nlocally.\n\nStart by preparing the FS comp file, the `*.fsdb`. This will often contain\nsensitive personal information such as birthdays, phone numbers and notes that\nwe'll want to avoid publishing. We'll also want some output data for making\ncomparisons between flare-timing and FS.\n\n1. Clean out the sensitive pilot personal stuff we don't need with\n[`fs-clean`](lang-haskell/flare-timing/prod-apps/fs-clean).  \n2. Trim away data we don't need with\n[`fs-trim`](lang-haskell/flare-timing/prod-apps/fs-trim).  \n3. Grab the optimal route around the tasks found by FS with\n[`fs-route`](lang-haskell/flare-timing/prod-apps/fs-route).  \n4. Grab the arrival times and positions from FS with\n[`fs-arrival`](lang-haskell/flare-timing/prod-apps/fs-arrival).  \n5. Grab the landouts from FS with\n[`fs-effort`](lang-haskell/flare-timing/prod-apps/fs-effort).  \n6. Grab the scores from FS with\n[`fs-score`](lang-haskell/flare-timing/prod-apps/fs-score).  \n\nThat's the `*.fsdb` file done with. From here on, flare-timing deals with the\ntrimmed XML, the `*.trim-fsdb.xml`. If we have the track logs we can score the\ntasks:\n\n1. Extract the inputs with\n[`ft-extract-input`](lang-haskell/flare-timing/prod-apps/extract-input).  \n2. Trace the shortest path to fly a task with\n[`ft-task-length`](lang-haskell/flare-timing/prod-apps/task-length).  \n3. Find flying times with\n[`ft-fly-time`](lang-haskell/flare-timing/prod-apps/fly-time).  \n4. Find pairs of fixes crossing over zones with\n[`ft-cross-zone`](lang-haskell/flare-timing/prod-apps/cross-zone).  \n5. Interpolate between crossing fixes for the time and place where a track tags\na zone with [`ft-tag-zone`](lang-haskell/flare-timing/prod-apps/tag-zone).  \n6. Unpack the `*.igc` or `*.kml` tracklogs with\n[`ft-unpack-track`](lang-haskell/flare-timing/prod-apps/unpack-track).  \n7. Peg the timing window to a reference frame with\n[`ft-peg-frame`](lang-haskell/flare-timing/prod-apps/peg-frame).  \n8. Index fixes from the time of first crossing with\n[`ft-align-time`](lang-haskell/flare-timing/prod-apps/align-time).  \n9. Discard fixes that get further from goal and note leading area with\n[`ft-discard-further`](lang-haskell/flare-timing/prod-apps/discard-further).  \n10. Draw out leading areas \n[`ft-lead-area`](lang-haskell/flare-timing/prod-apps/lead-area).  \n11. Mask a task over its tracklogs with the following, run in any order:\n    * [`ft-mask-arrival`](lang-haskell/flare-timing/prod-apps/mask-arrival).  \n    * [`ft-mask-bonus`](lang-haskell/flare-timing/prod-apps/mask-bonus).  \n    * [`ft-mask-effort`](lang-haskell/flare-timing/prod-apps/mask-effort).  \n    * [`ft-mask-lead`](lang-haskell/flare-timing/prod-apps/mask-lead).  \n    * [`ft-mask-reach`](lang-haskell/flare-timing/prod-apps/mask-reach).  \n12. Group and count land outs with\n[`ft-land-out`](lang-haskell/flare-timing/prod-apps/land-out).  \n13. Group and count far outs with\n[`ft-far-out`](lang-haskell/flare-timing/prod-apps/far-out).  \n14. Score the competition with [`ft-gap-point`](lang-haskell/flare-timing/prod-apps/gap-point).  \n\nTo get the backend server for hosting the comp data running locally:\n\nStart the server with\n[`ft-comp-serve`](lang-haskell/app-serve).  \n\nTo host the frontend web app for the comp locally:\n\n1. Change directory:\n    `\u003e cd lang-haskell`\n2. Open a try-reflex shell with:\n    `\u003e reflex-platform/try-reflex`\n3. Build the frontend and start its webpack dev server with:\n    `\u003e ../stack-shake-build.sh view-start-ghcjs`\n4. Open a browser at the hosted URL, usually http://localhost:9000/app.html.\n\nDocumentation is available online at\n[flare-timing.readthedocs.io](http://flare-timing.readthedocs.io/) and there's\na [worked example](lang-haskell/EXAMPLE.md) too.\n\n## What's Included\n\nThe GAP rules have changed over the years. Here are the features that\nflare-timing includes or not.\n\n* Scoring Method\n    - [x] GAP\n        - [ ] GAP2000\n        - [ ] GAP2002\n        - [ ] OzGAP2005\n        - [ ] GAP2007\n        - [ ] GAP2008\n        - [x] GAP2011 tested with:    \n            Forbes [2012](http://2012-forbes.flaretiming.com)\n            , Forbes [2014](http://2014-forbes.flaretiming.com)\n            , Forbes [2015](http://2015-forbes.flaretiming.com)            \n        - [x] GAP2013 tested with:    \n            Forbes [2017](http://2017-forbes.flaretiming.com)\n        - [ ] GAP2014\n        - [x] GAP2015 tested with:    \n            Big Spring [2016](http://2016-big-spring.flaretiming.com)\n            , Green Swamp [2016](http://2016-greenswamp.flaretiming.com)\n            , Green Swamp Sport [2016](http://2016-greenswamp-sport.flaretiming.com)\n            , Forbes [2016](http://2016-forbes.flaretiming.com)\n            , Quest [2016](http://2016-quest.flaretiming.com)\n        - [x] GAP2016 tested with:    \n            Dalmatian [2018](http://2018-dalmatian.flaretiming.com)\n            , Dalby [2017](http://2017-dalby.flaretiming.com)\n            , Forbes [2018](http://2018-forbes.flaretiming.com)\n            , Forbes [2019](http://2018-forbes.flaretiming.com)\n        - [x] GAP2018 tested with:    \n            Dalmatian [2019](http://2019-dalmatian.flaretiming.com)\n            , Italy [2019](http://2019-italy.flaretiming.com)\n        - [ ] GAP2020\n    - [ ] PWC (GAP variant)\n        - [ ] PWC2007\n        - [ ] PWC2008\n        - [ ] PWC2009\n        - [ ] PWC2011\n        - [ ] PWC2012\n        - [ ] PWC2013\n        - [ ] PWC2014\n        - [ ] PWC2015\n        - [ ] PWC2016\n        - [ ] PWC2017\n        - [ ] PWC2019\n    - [ ] Linear distance\n    - [ ] Time-based scoring (TBS)\n* Earth Model\n    - [x] FAI sphere\n    - [x] WGS84 ellipsoid\n* Distance Method\n    - [x] Pythagorus on a UTM plane\n    - [x] Haversines on the sphere\n    - [x] Vincenty on the ellipsoid\n    - [x] Andoyer on the ellipsoid\n* Type of Task\n    - [x] Race\n    - [x] Elapsed time\n    - [ ] Open distance (can be declared but not yet scored)\n* Shape of Zone\n    - [x] Cylinder\n    - [ ] Inverted cone (can be defined but treated as a cylinder)\n* Shape of Goal\n    - [x] Circle\n    - [x] Line\n* Final Glide Decelerator\n    - [ ] Conical end of speed section (CESS)\n    - [ ] Arrival altitude time bonus (AATB)\n* Source of Altitude\n    - [x] GPS\n    - [ ] Pressure (QNH)\n* Validities\n    - [x] Task (day quality)\n    - [x] Launch\n    - [x] Distance\n    - [x] Time\n    - [x] Stop\n* Points\n    - [x] Linear distance (reach)\n    - [x] Distance difficulty (effort)\n    - [x] Arrival position\n    - [x] Arrival time\n    - [x] Time (speed)\n    - [x] Leading\n    - [ ] Departure\n* Leading Area as a Function of Time and Distance Tweaks\n    - [x] Use distance; a = t * d\n    - [x] Use distance squared; a = t * d^2\n    - [ ] Use PWCA weighting; a = w(t, d)\n* Parameter Tweaks\n    - [ ] Day quality override\n    - [ ] 1000 points for winner if no pilot made goal\n    - [ ] 1000 points for winner before day quality applied\n    - [x] Double leading points weight\n    - [ ] Proportional leading points weight if no pilot made goal\n    - [x] Adjustable stopped task bonus glide ratio (fixed at 4:1 for PG and 5:1 for HG)\n* Special Cases\n    - [x] End of the speed section but not goal\n    - [x] Early start\n    - [x] Stopped tasks\n* Stopped Tasks\n    - [x] Stopped task time as announcement minus score back\n    - [ ] Requirements checking, goal or duration\n    - [x] Score time window\n    - [ ] Time points for pilots at or after the end of the speed section\n    - [x] Distance points with altitude bonus\n* Penalties\n    - [x] Absolute\n    - [x] Fractional\n    - [x] Jump-the-gun factor\n    - [x] Jump-the-gun maximum\n    - [x] Made ESS but not goal\n* Task Ranking\n    - [x] Overall\n    - [ ] Female\n    - [ ] Country\n* Competition Ranking\n    - [ ] Overall\n    - [ ] Female\n    - [ ] Country\n    - [ ] Ties\n    - [ ] Fixed Total Validity\n\n## License\n\n```\nCopyright © Phil de Joux 2017-2020\nCopyright © Block Scope Limited 2017-2020\n```\n\nThis software is subject to the terms of the Mozilla Public License, v2.0. If\na copy of the MPL was not distributed with this file, you can obtain one at\nhttp://mozilla.org/MPL/2.0/.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglideangle%2Fflare-timing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglideangle%2Fflare-timing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglideangle%2Fflare-timing/lists"}