UNPKG

minotor

Version:

A lightweight client-side transit routing library.

162 lines (148 loc) 4.55 kB
import { Command } from 'commander'; import fs from 'fs'; import log from 'loglevel'; import { DateTime } from 'luxon'; import { chGtfsProfile, GtfsParser, GtfsProfile } from '../parser.js'; import { Router, StopsIndex, Timetable } from '../router.js'; import { loadQueriesFromJson, prettyPrintPerformanceResults, testRouterPerformance, } from './perf.js'; import { startRepl } from './repl.js'; const program = new Command(); export type GtfsVariant = string; export type Config = { [config: GtfsVariant]: GtfsProfile; }; const profiles: Config = { CH: chGtfsProfile, }; program .name('minotor') .description('CLI for minotor route planner.') .version('0.0.1'); program .command('parse-gtfs') .description('Parse a GTFS feed and output a timetable and stops file.') .argument('<gtfsPath>', 'Path to GTFS data') .option( '-d, --date <date>', 'Date of the day to parse in yyyy-MM-dd format', DateTime.now().toFormat('yyyy-MM-dd'), ) .option( '-t, --timetableOutputPath <path>', 'Path to output timetable file', '/tmp/timetable', ) .option( '-s, --stopsOutputPath <path>', 'Path to output stops file', '/tmp/stops', ) .option('-p, --profileName <name>', 'Profile name for GTFS config', 'CH') .option('-v, --verbose', 'Verbose mode', false) .action( async ( gtfsPath: string, options: { date: string; timetableOutputPath: string; stopsOutputPath: string; profileName: string; verbose: boolean; }, ) => { if (options.verbose) { log.setDefaultLevel(log.levels.INFO); } else { log.setDefaultLevel(log.levels.ERROR); } const parser = new GtfsParser(gtfsPath, profiles[options.profileName]); const stopsIndex = await parser.parseStops(); fs.writeFileSync(options.stopsOutputPath, stopsIndex.serialize()); const timetable = await parser.parseTimetable(new Date(options.date)); fs.writeFileSync(options.timetableOutputPath, timetable.serialize()); }, ); program .command('parse-stops') .description('Parse a GTFS feed and output a stops file.') .argument('<gtfsPath>', 'Path to GTFS data') .option('-s, --outputPath <path>', 'Path to output stops file', '/tmp/stops') .option('-p, --profileName <name>', 'Profile name for GTFS config', 'CH') .option('-v, --verbose', 'Verbose mode', false) .action( async ( gtfsPath: string, options: { stopsOutputPath: string; profileName: string; verbose: boolean; }, ) => { if (options.verbose) { log.setDefaultLevel(log.levels.INFO); } else { log.setDefaultLevel(log.levels.ERROR); } const parser = new GtfsParser(gtfsPath, profiles[options.profileName]); const stopsIndex = await parser.parseStops(); fs.writeFileSync(options.stopsOutputPath, stopsIndex.serialize()); }, ); program .command('repl') .description('Find stops matching a textual query') .option('-s, --stopsPath <path>', 'Path to the stops file', '/tmp/stops') .option( '-t, --timetablePath <path>', 'Path to the timetable file', '/tmp/timetable', ) .action((options: { stopsPath: string; timetablePath: string }) => { startRepl(options.stopsPath, options.timetablePath); }); program .command('perf') .description('Evaluate the performance of the router on a set of routes.') .argument('<routesPath>', 'Path to the JSON file containing the routes') .option('-s, --stopsPath <path>', 'Path to the stops file', '/tmp/stops') .option( '-t, --timetablePath <path>', 'Path to the timetable file', '/tmp/timetable', ) .option( '-i, --iterations <number>', 'Number of iterations for performance tests', '20', ) .action( ( routesPath: string, options: { stopsPath: string; timetablePath: string; iterations: string; }, ) => { const stopsIndex = StopsIndex.fromData( fs.readFileSync(options.stopsPath), ); const timetable = Timetable.fromData( fs.readFileSync(options.timetablePath), ); const router = new Router(timetable, stopsIndex); const queries = loadQueriesFromJson(routesPath); const performanceResults = testRouterPerformance( router, stopsIndex, queries, parseInt(options.iterations, 10), ); prettyPrintPerformanceResults(performanceResults); }, ); program.parse(process.argv);