UNPKG

timetable

Version:

Using GTFS and other sources to produce beautiful and usable timetables for public transport.

344 lines (302 loc) 10.9 kB
// Generated by CoffeeScript 1.7.1 (function() { var $, ASYNC, COURSES, DEV, P, REGISTRY, TRM, alert, badge, debug, echo, help, info, log, options, rainbow, rpr, urge, warn, whisper, __slice = [].slice; TRM = require('coffeenode-trm'); rpr = TRM.rpr.bind(TRM); badge = 'TIMETABLE/READER'; log = TRM.get_logger('plain', badge); info = TRM.get_logger('info', badge); whisper = TRM.get_logger('whisper', badge); alert = TRM.get_logger('alert', badge); debug = TRM.get_logger('debug', badge); warn = TRM.get_logger('warn', badge); help = TRM.get_logger('help', badge); urge = TRM.get_logger('urge', badge); echo = TRM.echo.bind(TRM); rainbow = TRM.rainbow.bind(TRM); ASYNC = require('async'); REGISTRY = require('./REGISTRY'); COURSES = require('./COURSES'); P = require('pipedreams'); $ = P.$.bind(P); options = require('../options'); DEV = options['mode'] === 'dev'; /* TAINT very Berlin-specific method, shouldnt appear here */ this.normalize_berlin_station_name = function(name) { name = name.replace(/\s+\(Berlin\)(\s+Bus)?$/, ''); if (!/^(U|S) Olympiastadion/.test(name)) { name = name.replace(/^(U|S\+U|S)\s+/, ''); } name = name.replace(/^(Alexanderplatz) Bhf\/(.+)$/, '$1 ($2)'); name = name.replace(/^(Lichtenberg) Bhf\/(.+)$/, '$1 ($2)'); name = name.replace(/^(Alexanderplatz) Bhf/, '$1'); name = name.replace(/^(Zoologischer Garten) Bhf/, '$1'); name = name.replace(/^(Gesundbrunnen) Bhf/, '$1'); name = name.replace(/^(Potsdamer Platz) Bhf/, '$1'); name = name.replace(/^(Lichtenberg) Bhf/, '$1'); name = name.replace(/^(Friedrichstr\.) Bhf/, '$1'); name = name.replace(/^(Jungfernheide) Bhf/, '$1'); name = name.replace(/^(Stadtmitte) U[26]/, '$1'); name = name.replace(/str\./g, 'straße'); name = name.replace(/\s+Str\./g, ' Straße'); return name; }; this.$rn_normalize_station_name = function(key) { return $((function(_this) { return function(_arg, handler) { var name, node, record; record = _arg[0], node = _arg[1]; name = node[key]; if (name == null) { return handler(new Error("unable to find key " + (rpr(key)) + " in\n" + (rpr(node)))); } node[key] = _this.normalize_berlin_station_name(name); return handler(null, [record, node]); }; })(this)); }; this.$remove_gtfs_fields = function() { return $(function(node, handler) { var name; for (name in node) { if (/^%gtfs/.test(name)) { delete node[name]; } } return handler(null, node); }); }; this.$side_by_side = function() { return $(function(node, handler) { var name, record, value; record = {}; for (name in node) { value = node[name]; record[name] = value; } return handler(null, [record, node]); }); }; this.$rn_one_by_one = function() { var on_data; on_data = function(_arg) { var node, record; record = _arg[0], node = _arg[1]; this.emit('data', record); return this.emit('data', node); }; return P.through(on_data, null); }; this.$rn_add_ids_etc = function(label) { var idx; idx = 0; return $(function(_arg, handler) { var node, node_id, record; record = _arg[0], node = _arg[1]; node['~isa'] = 'node'; node['~label'] = label; record['node-id'] = node_id = node['id'] = "timetable/" + label + "/" + idx; node['record-id'] = record['id']; delete node['gtfs-id']; delete node['gtfs-type']; idx += 1; return handler(null, [record, node]); }); }; this.read_agency_nodes = function(registry, handler) { var input; input = registry.createReadStream({ keys: false, gte: 'gtfs/agency', lte: 'gtfs/agency\xff' }); return input.pipe(this.$side_by_side()).pipe(this.$rn_add_agency_id_etc()).pipe(P.$collect_sample(1, function(_, sample) { return whisper('agency', sample); })).pipe(this.$rn_one_by_one()).pipe(REGISTRY.$register(registry)).pipe(P.$on_end(function() { return handler(null); })); }; this.$rn_add_agency_id_etc = function() { return $(function(_arg, handler) { var node, node_id, record; record = _arg[0], node = _arg[1]; node['~isa'] = 'node'; node['~label'] = 'agency'; record['node-id'] = node_id = node['id'] = record['id'].replace(/^gtfs\/([^-_]+)[-_]+$/, 'timetable/$1'); delete node['gtfs-id']; node['record-id'] = record['id']; delete node['gtfs-type']; return handler(null, [record, node]); }); }; this.read_station_nodes = function(registry, handler) { var input, ratio; ratio = DEV ? 1 / 5000 : 1; input = registry.createReadStream({ keys: false, gte: 'gtfs/stops', lte: 'gtfs/stops\xff' }); return input.pipe(P.$sample(ratio, { headers: true, seed: 5 })).pipe(this.$side_by_side()).pipe(this.$rn_normalize_station_name('name')).pipe(this.$rn_add_ids_etc('station')).pipe(P.$collect_sample(1, function(_, sample) { return whisper('station', sample); })).pipe(this.$rn_one_by_one()).pipe(REGISTRY.$register(registry)).pipe(P.$on_end(function() { return handler(null); })); }; this.read_route_nodes = function(registry, handler) { var input; input = registry.createReadStream({ keys: false, gte: 'gtfs/routes', lte: 'gtfs/routes\xff' }); return input.pipe(this.$side_by_side()).pipe(this.$rn_add_ids_etc('route')).pipe(P.$collect_sample(1, function(_, sample) { return whisper('route', sample); })).pipe(this.$rn_agency_id_from_gtfs(registry)).pipe(this.$rn_one_by_one()).pipe(REGISTRY.$register(registry)).pipe(P.$on_end(function() { return handler(null); })); }; this.$rn_agency_id_from_gtfs = function(registry) { return $(function(_arg, handler) { var gtfs_agency_id, node, record; record = _arg[0], node = _arg[1]; gtfs_agency_id = node['gtfs-agency-id']; return registry.get("gtfs/agency/" + gtfs_agency_id, function(error, gtfs_agency_record) { if (error != null) { return handler(error); } node['agency-id'] = gtfs_agency_record['node-id']; delete node['gtfs-agency-id']; return handler(null, [record, node]); }); }); }; this.read_tour_nodes = function(registry, handler) { /* OBS implies reading courses and halts. */ var input, ratio; ratio = DEV ? 1 / 5000 : 1; input = registry.createReadStream({ keys: false, gte: 'gtfs/trips', lte: 'gtfs/trips\xff' }); return input.pipe(this.$side_by_side()).pipe(P.$sample(ratio, { headers: true, seed: 5 })).pipe(P.$collect_sample(1, function(_, sample) { return whisper('station', sample); })).pipe(this.$rn_one_by_one()).pipe(P.$on_end(function() { return handler(null); })); }; this.$clean_trip_arr_dep = function() { /* Replace the first stoptime's arrival and the last stoptime's departure time from the trip. */ return $(function(node, handler) { var last_idx; last_idx = node['%gtfs-stoptimes'].length - 1; node['%gtfs-stoptimes'][0]['arr'] = null; node['%gtfs-stoptimes'][last_idx]['dep'] = null; return handler(null, node); }); }; this.$tour_from_trip = function(registry) { return $((function(_this) { return function(node, handler) { var course, gtfs_routes_id, headsign, reltrip_info, route, route_id, tour; reltrip_info = COURSES.reltrip_info_from_abstrip(node); course = COURSES.registered_course_from_reltrip_info(registry, reltrip_info); headsign = _this.normalize_berlin_station_name(reltrip_info['headsign']); gtfs_routes_id = node['%gtfs-routes-id']; route = registry['%gtfs']['routes'][gtfs_routes_id]; route_id = route['id']; tour = { '~isa': 'node', '~label': 'tour', 'course-id': reltrip_info['course-id'], 'route-id': route_id, 'headsign': headsign, 'offset.hhmmss': reltrip_info['offset.hhmmss'], 'offset.s': reltrip_info['offset.s'] }; return handler(null, tour); }; })(this)); }; this.$add_tour_id = function() { var idxs; idxs = {}; return $((function(_this) { return function(node, handler) { var idx, route_id; route_id = node['route-id']; idx = idxs[route_id] = (idxs[route_id] != null ? idxs[route_id] : idxs[route_id] = 0) + 1; node['id'] = "tour/" + route_id + "/" + idx; return handler(null, node); }; })(this)); }; this.main = function(registry, handler) { var message, messages, method, method_name, no_method, no_source, node_type, ok_types, t0, tasks, _fn, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; t0 = 1 * new Date(); tasks = []; no_source = []; no_method = []; ok_types = []; _ref = options['data']['node-types']; _fn = (function(_this) { return function(method_name, method) { return tasks.push(function(async_handler) { help("" + badge + "/" + method_name); return method(registry, function() { var P; P = 1 <= arguments.length ? __slice.call(arguments, 0) : []; info("" + badge + "/" + method_name); return async_handler.apply(null, P); }); }); }; })(this); for (_i = 0, _len = _ref.length; _i < _len; _i++) { node_type = _ref[_i]; if (node_type !== 'agency' && node_type !== 'station' && node_type !== 'route' && node_type !== 'tour') { warn("skipping " + node_type); continue; } method_name = "read_" + node_type + "_nodes"; method = this[method_name]; if (method == null) { no_method.push("no method to read nodes of type " + (rpr(node_type)) + "; skipping"); continue; } method = method.bind(this); ok_types.push(node_type); _fn(method_name, method); } _ref1 = [no_source, no_method]; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { messages = _ref1[_j]; for (_k = 0, _len2 = messages.length; _k < _len2; _k++) { message = messages[_k]; warn(message); } } info("reading data for " + ok_types.length + " type(s)"); info(" (" + (ok_types.join(', ')) + ")"); ASYNC.series(tasks, (function(_this) { return function(error) { var t1; if (error != null) { throw error; } t1 = 1 * new Date(); urge('dt:', (t1 - t0) / 1000); return handler(null, registry); }; })(this)); return null; }; }).call(this);