-
Notifications
You must be signed in to change notification settings - Fork 21
/
virtual_rider.js
88 lines (78 loc) · 2.75 KB
/
virtual_rider.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
let atStopState = (id) => "at_stop:" + id;
let onTripState = (id) => "on_trip:" + id;
let MAX_TIME = 1000 * 60;
class StateMap {
constructor() {
this.earliestRidersAtStates = {};
}
addRider(rider) {
let existing = this.earliestRidersAtStates[rider.state];
if (!existing || rider.time < existing.time) {
this.earliestRidersAtStates[rider.state] = rider;
return true;
}
return false;
}
addRiderAndTransfersByAppendingStop(oldRider, stopId, time, allTransfers) {
let direct = oldRider.byAdding(atStopState(stopId), time);
if (this.addRider(direct)) {
// add all transfers:
for (let transfer of allTransfers[stopId] || []) {
this.addRiderAndTransfersByAppendingStop(direct, transfer['to'], time + transfer.time, allTransfers);
}
}
}
}
class Rider {
constructor(states, time) {
this.states = states; // states are strings
this.time = time;
this.state = states.length ? states[states.length-1] : null;
}
byAdding(state, finalTime) {
return new Rider([...this.states, state], finalTime);
}
}
let _computeTravelTimes = (startStationId, endStationIds, transfers, events, startTime) => {
let stateMap = new StateMap();
let emptyPath = new Rider([], startTime);
stateMap.addRiderAndTransfersByAppendingStop(emptyPath, startStationId, startTime, transfers);
// console.log(stateMap);
for (let {time, trip_id, stop_id, route_name} of events) {
// model exiting the train:
let riderOnTrain = stateMap.earliestRidersAtStates[onTripState(trip_id)];
if (riderOnTrain && riderOnTrain.time <= time) {
stateMap.addRiderAndTransfersByAppendingStop(riderOnTrain, stop_id, time, transfers);
}
// model boarding the train:
let riderOnPlatform = stateMap.earliestRidersAtStates[atStopState(stop_id)];
if (riderOnPlatform && riderOnPlatform.time <= time) {
let riderOnTrain = riderOnPlatform.byAdding(onTripState(trip_id), time);
stateMap.addRider(riderOnTrain);
}
}
let travelTimes = {};
for (let stationId of endStationIds) {
let rider = stateMap.earliestRidersAtStates[atStopState(stationId)];
travelTimes[stationId] = rider ? rider.time - startTime : MAX_TIME;
}
return travelTimes;
}
let scheduleCache = {};
let getSchedule = (name, callback) => {
if (scheduleCache[name]) {
callback(scheduleCache[name]);
} else {
d3.json('/schedules/' + name + '.json', (schedule) => {
scheduleCache[name] = schedule;
callback(schedule);
})
}
}
let computeTravelTimes = (startStationId, scheduleName, callback) => {
getSchedule(scheduleName, (schedule) => {
callback(_computeTravelTimes(startStationId, Object.keys(subway.stations), gtfs_transfers, schedule.events, schedule.start_time));
});
};
// let HOURS = 60 * 60;
// console.log(computeTravelTimes('127', Object.keys(subway.stations), 8*HOURS, gtfs_json, 'weekdays'));