UNPKG

igc-xc-score

Version:

igc-xc-score is a paragliding and hang-gliding XC scoring program in vanilla JS

185 lines (158 loc) 6.48 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: src/solver.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: src/solver.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>'use strict'; /** * igc-xc-score Solver * scoring library for paragliding flights * * @module igc-xc-score * @author Momtchil Momtchev &lt;momtchil@momtchev.com> */ import SortedSet from 'collections/sorted-set.js'; import { Solution } from './solution.js'; import { Range, Point } from './foundation.js'; import * as geom from './geom.js'; import * as Flight from './flight.js'; import scoringRules from '../scoring-rules.config.js'; /** * This the solver * @param {IGCFile} flight flight track data in the igc_parser format * @param {object[]} [scoringTypes=undefined] undefined for FFVL or one of the elements of scoringRules * @param {object=} config optional config parameters * @param {number=} config.maxcycle maximum execution time of the solver in ms, each sucessive call will return a better solution, default undefined for unlimited * @param {boolean=} config.noflight do not include the flight track data in the output GeoJSON, default false * @param {boolean=} config.invalid include invalid GPS fixes when evaluating the flight, default false * @param {boolean=} config.hp use high-precision distance calculation (Vincenty's), much slower for slightly higher precision, default false * @param {boolean=} config.trim automatically detect launch and landing and trim the flight track, default false */ export default function* solver(flight, _scoringTypes, _config) { let reset; const scoringTypes = _scoringTypes || scoringRules.FFVL; const config = _config || {}; Flight.analyze(flight, config); geom.init({ flight }); if (config.hp) Point.prototype.distanceEarth = Point.prototype.distanceEarthVincentys; else Point.prototype.distanceEarth = Point.prototype.distanceEarthFCC; let solutionRoots = []; for (let scoringType of scoringTypes) { for (let l of flight.ll) { const opt = { flight, launch: l.launch, landing: l.landing, scoring: scoringType, config }; let solutionRoot = new Solution([ new Range(l.launch, l.landing), new Range(l.launch, l.landing), new Range(l.launch, l.landing) ], opt); solutionRoot.do_bound(); solutionRoot.do_score(); solutionRoots.push(solutionRoot); } } let best = solutionRoots[0]; let solutionQueue = new SortedSet( solutionRoots, Solution.prototype.contentEquals, Solution.prototype.contentCompare ); let processed = 0; let tcum = 0; do { const tstart = Date.now(); while (solutionQueue.length > 0) { if (processed % 100 === 0) { if (config.env &amp;&amp; config.env.v8 !== 'undefined') { const mem = config.env.v8.getHeapStatistics(); if (mem.used_heap_size / mem.heap_size_limit > 0.98) { /* c8 ignore next 4 */ console.error(`Out of memory: ${mem.used_heap_size/1024}KiB used` + ` of ${mem.heap_size_limit/1024}KiB total`); break; } } } let current = solutionQueue.pop(); if (current.bound &lt;= best.score) { solutionQueue.clear(); break; } let children = current.do_branch(); for (let s of children) { s.do_bound(); if (s.bound &lt;= best.score) continue; s.do_score(); processed++; if (s.score >= best.score &amp;&amp; s.score > 0) { best = s; if (solutionQueue.findLeast() &amp;&amp; solutionQueue.findLeast().value.bound &lt;= best.score) { const garbageBest = solutionQueue.findGreatestLessThanOrEqual({ bound: best.score }); if (garbageBest !== undefined) { const cutoff = solutionQueue.indexOf(garbageBest.value); solutionQueue.splice(0, cutoff + 1).length; } } } else { delete s.scoreInfo; } solutionQueue.push(s); if (config.debug) best.last = s; } if (processed > config.maxloop || (Date.now() - tstart) > config.maxcycle) { break; } } best.processed = processed; const currentUpperBound = solutionQueue.findGreatest(); best.currentUpperBound = currentUpperBound ? currentUpperBound.value.bound : best.bound; tcum += Date.now() - tstart; best.time = tcum; if (solutionQueue.length == 0) best.optimal = true; else best.optimal = false; if (best.optimal) { reset = true; return best; } else reset = yield best; } while (!reset); } </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-igc-xc-score.html">igc-xc-score</a></li></ul><h3>Global</h3><ul><li><a href="global.html#name">name</a></li><li><a href="global.html#scoringRules">scoringRules</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.3</a> on Wed Sep 25 2024 13:24:38 GMT+0200 (Central European Summer Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>