Skip to content

Commit

Permalink
Implement fare_rules.txt
Browse files Browse the repository at this point in the history
  • Loading branch information
Léo Frachet committed Apr 16, 2018
1 parent f15caf2 commit f9ae220
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 36 deletions.
175 changes: 147 additions & 28 deletions gtfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ function addItems(gtfs, tableName, items) {
const indexedTable = gtfs.getIndexedTable(tableName);
const indexKeys = gtfs._schema.indexKeysByTableName[tableName];

if (indexKeys.setOfItems) {
items.forEach(item => indexedTable.add(item));
return;
}

if (indexKeys.indexKey) {
items.forEach(item => indexedTable.set(item[indexKeys.indexKey], item));
return;
Expand Down Expand Up @@ -62,6 +67,26 @@ function getIndexedTable(gtfs, tableName) {
return gtfs._tables.get(tableName);
}

/**
* Check if an object is already in a table. Can only be used for not indexed table.
*
* @param {Gtfs} gtfs - GTFS object containing the table to check
* @param {Object} item - Item which will be searched in the table
* @param {string} tableName - Name of the table of the GTFS in which to search the object.
* @returns {Boolean} Whether or not the item is in the table.
*/

function hasItemInTable(gtfs, item, tableName) {
const items = gtfs.getIndexedTable(tableName);
const indexKeys = gtfs._schema.indexKeysByTableName[tableName];

if (indexKeys.setOfItems) {
return items.has(item);
}

throw new Error('hasItemInTable can only be used on table stored as Set. Use the key in other cases.');
}

/**
* Table-generic function to get an iterate in a table of a GTFS.
*
Expand All @@ -77,7 +102,7 @@ function forEachItem(gtfs, tableName, iterator) {
const indexedTable = gtfs.getIndexedTable(tableName);
const deepness = gtfs._schema.deepnessByTableName[tableName];

if (deepness === 1) {
if (deepness === 0 || deepness === 1) {
forEachWithLog(`Iterating:${tableName}`, indexedTable, (item) => {
iterator(item);
});
Expand Down Expand Up @@ -106,6 +131,11 @@ function removeItems(gtfs, tableName, items) {
const indexedTable = gtfs.getIndexedTable(tableName);
const indexKeys = gtfs._schema.indexKeysByTableName[tableName];

if (indexKeys.setOfItems) {
items.forEach(item => indexedTable.delete(item));
return;
}

if (indexKeys.indexKey) {
items.forEach(item => indexedTable.delete(item[indexKeys.indexKey]));
return;
Expand All @@ -129,18 +159,24 @@ function removeItems(gtfs, tableName, items) {
*
* @param {Gtfs} gtfs GTFS object in which the table will be set.
* @param {string} tableName Name of the table of the GTFS to set.
* @param {Object|Map} indexedItems Object properly indexed as the schema requires the table to be (see schema.js).
* @param {Object|Map|Set} table Object properly indexed as the schema requires the table to be (see schema.js).
*/
function setIndexedItems(gtfs, tableName, indexedItems) {
if (indexedItems instanceof Map === false && gtfs._schema.deepnessByTableName[tableName] !== 0) {
throw new Error(`indexedItems must be a Map instead of: ${indexedItems}`);
}
function setTable(gtfs, tableName, table) {
const indexKeys = gtfs._schema.indexKeysByTableName[tableName];

gtfs._tables.set(tableName, indexedItems);
if (indexKeys.setOfItems && table instanceof Set === true) {
gtfs._tables.set(tableName, table);
} else if (indexKeys.singleton && table instanceof Set === false && table instanceof Map === false ) {
gtfs._tables.set(tableName, table);
} else if (indexKeys.setOfItems !== true && indexKeys.singleton !== true && table instanceof Map === true) {
gtfs._tables.set(tableName, table);
} else {
throw new Error(`setTable cannot be used with the table: ${table}`);
}
}

/**
* Return the size of the map if define, otherwise 0
* Return the size of the Map if define, otherwise 0
*
* @param {Map} map
* @returns {number}
Expand All @@ -149,14 +185,30 @@ function getSizeOfMap(map) {
return (map instanceof Map) ? map.size : 0;
}

/**
* Return the size of the Set if define, otherwise 0
*
* @param {Set} set
* @returns {number}
*/
function getSizeOfSet(set) {
return (set instanceof Set) ? set.size : 0;
}

/**
* Table-generic function to reset a table of a GTFS (ie, create a new Map)
*
* @param {Gtfs} gtfs GTFS object containing the table to be reset.
* @param {string} tableName Name of the table to be reset.
*/
function resetTable(gtfs, tableName) {
gtfs._tables.set(tableName, new Map());
const indexKeys = gtfs._schema.indexKeysByTableName[tableName];

if (indexKeys.setOfItems) {
gtfs._tables.set(tableName, new Set());
} else {
gtfs._tables.set(tableName, new Map());
}
}

/**
Expand All @@ -166,16 +218,22 @@ function resetTable(gtfs, tableName) {
* @param {string} tableName Name of the table to be get the number of item from.
*/
function getNumberOfItemsInTable(gtfs, tableName) {
const indexKeys = gtfs._schema.indexKeysByTableName[tableName];
const deepness = gtfs._schema.deepnessByTableName[tableName];

if (deepness !== 1) {
throw new Error(`'${tableName}' has a deepness of ${deepness}. \
getNumberOfItemsInTable can only apply on a first level table.`);
if (deepness === 1) {
const indexedTable = gtfs.getIndexedTable(tableName);
return getSizeOfMap(indexedTable);
}
if (deepness === 0 && indexKeys.setOfItems) {
const items = gtfs.getIndexedTable(tableName);
return getSizeOfSet(items);
}

const indexedTable = gtfs.getIndexedTable(tableName);

return getSizeOfMap(indexedTable);
throw new Error(
`'${tableName}' has a deepness of ${deepness}.` +
'getNumberOfItemsInTable can only apply on a first level table or a Set.'
);
}

class Gtfs {
Expand Down Expand Up @@ -409,7 +467,7 @@ class Gtfs {
* @param {Map} indexedItems Object properly indexed as the schema requires the table to be (see schema.js).
* @param {string} tableName Name of the table of the GTFS to set.
*/
setIndexedItemsAsTable(indexedItems, tableName) { setIndexedItems(this, tableName, indexedItems); }
setIndexedItemsAsTable(indexedItems, tableName) { setTable(this, tableName, indexedItems); }

/* agency.txt */

Expand Down Expand Up @@ -493,7 +551,7 @@ class Gtfs {
*
* @param {Map.<string, Object>} indexedAgencies Map of agencies properly indexed (see schema.js).
*/
setIndexedAgencies(indexedAgencies) { setIndexedItems(this, 'agency', indexedAgencies); }
setIndexedAgencies(indexedAgencies) { setTable(this, 'agency', indexedAgencies); }


/* stops.txt */
Expand Down Expand Up @@ -585,7 +643,7 @@ class Gtfs {
*
* @param {Map.<string, Object>} indexedStops Map of stops properly indexed (see schema.js).
*/
setIndexedStops(indexedStops) { setIndexedItems(this, 'stops', indexedStops); }
setIndexedStops(indexedStops) { setTable(this, 'stops', indexedStops); }


/* routes.txt */
Expand Down Expand Up @@ -694,7 +752,7 @@ class Gtfs {
*
* @param {Map.<string, Object>} indexedRoutes Map of routes properly indexed (see schema.js).
*/
setIndexedRoutes(indexedRoutes) { setIndexedItems(this, 'routes', indexedRoutes); }
setIndexedRoutes(indexedRoutes) { setTable(this, 'routes', indexedRoutes); }

/* trips.txt */

Expand Down Expand Up @@ -789,7 +847,7 @@ class Gtfs {
*
* @param {Map.<string, Object>} indexedTrips Map of trips properly indexed (see schema.js).
*/
setIndexedTrips(indexedTrips) { setIndexedItems(this, 'trips', indexedTrips); }
setIndexedTrips(indexedTrips) { setTable(this, 'trips', indexedTrips); }

/**
* Reset the map of indexed trips.
Expand Down Expand Up @@ -918,7 +976,7 @@ class Gtfs {
*
* @param {Map.<string, Map.<string, Object>>} indexedStopTimes Map of stopTimes properly indexed (see schema.js).
*/
setIndexedStopTimes(indexedStopTimes) { setIndexedItems(this, 'stop_times', indexedStopTimes); }
setIndexedStopTimes(indexedStopTimes) { setTable(this, 'stop_times', indexedStopTimes); }

/**
* Reset the map of indexed stop times.
Expand Down Expand Up @@ -1023,7 +1081,7 @@ class Gtfs {
*
* @param {Map.<string, Object>} indexedCalendars Map of calendars properly indexed (see schema.js).
*/
setIndexedCalendars(indexedCalendars) { setIndexedItems(this, 'calendar', indexedCalendars); }
setIndexedCalendars(indexedCalendars) { setTable(this, 'calendar', indexedCalendars); }


/* calendar_dates.txt */
Expand Down Expand Up @@ -1155,15 +1213,76 @@ class Gtfs {
* Map.<string, Map.<string, Object>>
* } indexedCalendarDates Map of calendarDates properly indexed (see schema.js).
*/
setIndexedCalendarDates(indexedCalendarDates) { setIndexedItems(this, 'calendar_dates', indexedCalendarDates); }
setIndexedCalendarDates(indexedCalendarDates) { setTable(this, 'calendar_dates', indexedCalendarDates); }


/* fare_attributes.txt */
// Not used, therefore not implemented


/* fare_rules.txt */
// Not used, therefore not implemented

/**
* Adds a fareRule in the GTFS.
*
* @param {Object} fareRule - FareRule to add in the GTFS.
*/
addFareRule(fareRule) { addItems(this, 'fare_rules', [fareRule]); }

/**
* Adds a list of fareRules in the GTFS.
*
* @param {Array.<Object>} fareRules - Array of fareRules to add in the GTFS.
*/
addFareRules(fareRules) { addItems(this, 'fare_rules', fareRules); }

/**
* Apply a function to each fareRule in the GTFS.
*
* @param {function} iterator - Function which will be applied on every fareRule.
*/
forEachFareRule(iterator) { forEachItem(this, 'fare_rules', iterator); }

/**
* Get the number of fareRule defined
*
* @returns {number}
*/
getNumberOfFareRules() { return getNumberOfItemsInTable(this, 'fare_rules'); }

/**
* Check if a fareRule is in the GTFS.
*
* @param {Object} fareRule - FareRule which could be in the GTFS.
* @returns {Boolean} true is the item is in the GTFS, false otherwise.
*/
hasFareRule(fareRule) { return hasItemInTable(this, fareRule, 'fare_rules'); }

/**
* Removes a fareRule of the GTFS.
*
* @param {Object} fareRule - FareRule to remove of the GTFS.
*/
removeFareRule(fareRule) { removeItems(this, 'fare_rules', [fareRule]); }

/**
* Removes a list of fareRules of the GTFS.
*
* @param {Array.<Object>} fareRules - FareRules to remove of the GTFS.
*/
removeFareRules(fareRules) { removeItems(this, 'fare_rules', fareRules); }

/**
* Reset the map of indexed fareRules.
*/
resetFareRules() { resetTable(this, 'fare_rules'); }

/**
* Set the Set of fareRules.
*
* @param {Set.<Object>} fareRules - Set of fareRules properly indexed (see schema.js).
*/
setFareRules(fareRules) { setTable(this, 'fare_rules', fareRules); }


/* shapes.txt */
Expand Down Expand Up @@ -1266,7 +1385,7 @@ class Gtfs {
*
* @param {Map.<string, Object>} indexedShapePoints Map of shapePoints properly indexed (see schema.js).
*/
setIndexedShapePoints(indexedShapePoints) { setIndexedItems(this, 'shapes', indexedShapePoints); }
setIndexedShapePoints(indexedShapePoints) { setTable(this, 'shapes', indexedShapePoints); }


/* frequencies.txt */
Expand Down Expand Up @@ -1336,7 +1455,7 @@ class Gtfs {
*
* @param {Map.<string, Object>} indexedFrequencies Map of frequencies properly indexed (see schema.js).
*/
setIndexedFrequencies(indexedFrequencies) { setIndexedItems(this, 'frequencies', indexedFrequencies); }
setIndexedFrequencies(indexedFrequencies) { setTable(this, 'frequencies', indexedFrequencies); }


/* transfers.txt */
Expand Down Expand Up @@ -1406,7 +1525,7 @@ class Gtfs {
*
* @param {Map.<string, Map.<string, Object>>} indexedTransfers Map of transfers properly indexed (see schema.js).
*/
setIndexedTransfers(indexedTransfers) { setIndexedItems(this, 'transfers', indexedTransfers); }
setIndexedTransfers(indexedTransfers) { setTable(this, 'transfers', indexedTransfers); }


/* feed_info.txt */
Expand All @@ -1423,7 +1542,7 @@ class Gtfs {
*
* @param {Object} feedInfo The feed info object.
*/
setFeedInfo(feedInfo) { setIndexedItems(this, 'feed_info', feedInfo); }
setFeedInfo(feedInfo) { setTable(this, 'feed_info', feedInfo); }
}

module.exports = Gtfs;
2 changes: 1 addition & 1 deletion helpers/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ exports.importTable = (gtfs, tableName) => {
} else {
infoLog(`Empty table will be set for table ${tableName} (no input file at path ${gtfs._path}).`);

gtfs._tables.set(tableName, new Map());
gtfs._tables.set(tableName, (indexKeys.setOfItems) ? new Set() : new Map());
}

if (gtfs._postImportItemFunction) {
Expand Down
12 changes: 6 additions & 6 deletions helpers/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ const indexKeysByTableName = {
calendar: { indexKey: 'service_id' },
calendar_dates: { firstIndexKey: 'service_id', secondIndexKey: 'date' },
fare_attributes: { indexKey: 'fare_id' },
fare_rules: { setOfItems: true },
frequencies: { firstIndexKey: 'trip_id', secondIndexKey: 'start_time' },
routes: { indexKey: 'route_id' },
stop_times: { firstIndexKey: 'trip_id', secondIndexKey: 'stop_sequence' },
Expand All @@ -144,14 +145,13 @@ const indexKeysByTableName = {
const tableNames = Object.keys(indexKeysByTableName);

const deepnessByTableName = tableNames.reduce((accumulator, tableName) => {
if (indexKeysByTableName[tableName].singleton) {
const indexKeys = indexKeysByTableName[tableName];

if (indexKeys.singleton || indexKeys.setOfItems) {
accumulator[tableName] = 0;
} else if (indexKeysByTableName[tableName].indexKey) {
} else if (indexKeys.indexKey) {
accumulator[tableName] = 1;
} else if (
indexKeysByTableName[tableName].firstIndexKey &&
indexKeysByTableName[tableName].secondIndexKey
) {
} else if (indexKeys.firstIndexKey && indexKeys.secondIndexKey) {
accumulator[tableName] = 2;
}

Expand Down
Loading

0 comments on commit f9ae220

Please sign in to comment.