Skip to content

Commit

Permalink
Merge pull request #4 from TransitApp/feature/add-fares
Browse files Browse the repository at this point in the history
Add fare attributes and fare rules
  • Loading branch information
gcamp authored Jun 18, 2018
2 parents c551c74 + def1720 commit f4075ef
Show file tree
Hide file tree
Showing 8 changed files with 477 additions and 50 deletions.
270 changes: 237 additions & 33 deletions gtfs.js

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions helpers/export.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ function exportTable(tableName, gtfs, outputPath, callback) {
will be fixed.
2015-03-10
*/
const indexKeys = gtfs._schema.indexKeysByTableName[tableName];
const deepness = gtfs._schema.deepnessByTableName[tableName];

if (deepness === 0) {
if (indexKeys.singleton) {
let item = gtfs.getIndexedTable(tableName);
if (item) {
if (gtfs._preExportItemFunction) {
Expand All @@ -98,7 +99,7 @@ function exportTable(tableName, gtfs, outputPath, callback) {
let rowsBuffer = [];

async.eachSeries(gtfs.getIndexedTable(tableName), acomb.ensureAsync(([key, object], subDone) => {
if (deepness === 1) {
if (deepness === 0 || deepness === 1) {
if (gtfs._preExportItemFunction) {
object = gtfs._preExportItemFunction(object, tableName, key);
}
Expand Down
12 changes: 9 additions & 3 deletions helpers/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ 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) {
gtfs.forEachItemInTable(tableName, gtfs._postImportItemFunction);
if (indexKeys.singleton) {
gtfs._postImportItemFunction(gtfs.getIndexedTable(tableName));
} else {
gtfs.forEachItemInTable(tableName, gtfs._postImportItemFunction);
}
}
};

Expand Down Expand Up @@ -76,7 +80,7 @@ function getRows(buffer, regexPatternObjects, tableName) {
}

function processRows(gtfs, tableName, indexKeys, rows, shouldThrow) {
let table = new Map();
let table = (indexKeys.setOfItems) ? new Set() : new Map();

if (rows === undefined || rows === null || rows.length === 0) {
return table;
Expand Down Expand Up @@ -124,6 +128,8 @@ function processRows(gtfs, tableName, indexKeys, rows, shouldThrow) {
table.get(item[indexKeys.firstIndexKey]).set(item[indexKeys.secondIndexKey], item);
} else if (indexKeys.singleton) {
table = item;
} else if (indexKeys.setOfItems) {
table.add(item);
}
}

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
119 changes: 119 additions & 0 deletions tests/test_fare_attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
'use strict';

const { expect } = require('chai');
const { Gtfs } = require('../index');

describe('Tests on GTFS fare attributes', () => {
it('Tests on gtfs.getNumberOfFareAttributes(), .add…(), .remove…() and .getFareAttributeWithId', (done) => {
const path = `${__dirname}/samples/1`;
const gtfs = new Gtfs(path);
const fareAttribute1 = buildFareAttribute(1);
const fareAttribute2 = buildFareAttribute(2);
const fareAttribute3 = buildFareAttribute(3);

expect(gtfs.getNumberOfFareAttributes()).to.equal(0);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.1') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.2') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.3') !== undefined).to.equal(false);

gtfs.addFareAttributes([fareAttribute1, fareAttribute2]);

expect(gtfs.getNumberOfFareAttributes()).to.equal(2);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.1') !== undefined).to.equal(true);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.2') !== undefined).to.equal(true);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.3') !== undefined).to.equal(false);

gtfs.addFareAttribute(fareAttribute3);

expect(gtfs.getNumberOfFareAttributes()).to.equal(3);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.1') !== undefined).to.equal(true);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.2') !== undefined).to.equal(true);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.3') !== undefined).to.equal(true);

gtfs.removeFareAttribute(fareAttribute2);

expect(gtfs.getNumberOfFareAttributes()).to.equal(2);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.1') !== undefined).to.equal(true);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.2') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.3') !== undefined).to.equal(true);

gtfs.removeFareAttributes([fareAttribute1, fareAttribute3]);

expect(gtfs.getNumberOfFareAttributes()).to.equal(0);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.1') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.2') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.3') !== undefined).to.equal(false);

done();
});

it('Tests on gtfs.setFareAttributes() and .resetFareAttributes', (done) => {
const path = `${__dirname}/samples/1`;
const gtfs = new Gtfs(path);
const fareAttribute1 = buildFareAttribute(1);
const fareAttribute2 = buildFareAttribute(2);

expect(gtfs.getNumberOfFareAttributes()).to.equal(0);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.1') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.2') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.3') !== undefined).to.equal(false);

gtfs.setIndexedFareAttributes(new Map([
['fareAttribute.fare_id.1', fareAttribute1],
['fareAttribute.fare_id.2', fareAttribute2],
]));

expect(gtfs.getNumberOfFareAttributes()).to.equal(2);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.1') !== undefined).to.equal(true);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.2') !== undefined).to.equal(true);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.3') !== undefined).to.equal(false);

gtfs.resetFareAttributes();

expect(gtfs.getNumberOfFareAttributes()).to.equal(0);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.1') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.2') !== undefined).to.equal(false);
expect(gtfs.getFareAttributeWithId('fareAttribute.fare_id.3') !== undefined).to.equal(false);

done();
});

it('Tests on gtfs.forEachFareAttribute()', (done) => {
const path = `${__dirname}/samples/1`;
const gtfs = new Gtfs(path);
gtfs.addFareAttributes([buildFareAttribute(1), buildFareAttribute(3)]);

const fareIds = [];
gtfs.forEachFareAttribute(fareAttribute => fareIds.push(fareAttribute.fare_id));

expect(fareIds.sort()).to.deep.equal(['fareAttribute.fare_id.1', 'fareAttribute.fare_id.3']);

done();
});

it('Tests on gtfs.getIndexedFareAttributes()', (done) => {
const path = `${__dirname}/samples/1`;
const gtfs = new Gtfs(path);
gtfs.addFareAttributes([buildFareAttribute(1), buildFareAttribute(3)]);

const fareIds = [];
const indexedFareAttributes = gtfs.getIndexedFareAttributes();
indexedFareAttributes.forEach(fareAttribute => fareIds.push(fareAttribute.fare_id));

expect(fareIds.sort()).to.deep.equal(['fareAttribute.fare_id.1', 'fareAttribute.fare_id.3']);

done();
});
});

function buildFareAttribute(integer) {
return {
'fare_id': `fareAttribute.fare_id.${integer}`,
'price': `fareAttribute.price.${integer}`,
'currency_type': `fareAttribute.currency_type.${integer}`,
'payment_method': `fareAttribute.payment_method.${integer}`,
'transfers': `fareAttribute.transfers.${integer}`,
'agency_id': `fareAttribute.agency_id.${integer}`,
'transfer_duration': `fareAttribute.transfer_duration.${integer}`,
};
}
101 changes: 101 additions & 0 deletions tests/test_fare_rules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use strict';

const { expect } = require('chai');
const { Gtfs } = require('../index');

describe('Tests on GTFS fare rules', () => {
it('Tests on gtfs.getNumberOfFareRules(), .addFareRules?(), .getFareRules?() and .hasFareRule', (done) => {
const path = `${__dirname}/samples/1`;
const gtfs = new Gtfs(path);
const fareRule1 = buildFareRule(1);
const fareRule2 = buildFareRule(2);
const fareRule3 = buildFareRule(3);

expect(gtfs.getNumberOfFareRules()).to.equal(0);
expect(gtfs.hasFareRule(fareRule1)).to.equal(false);
expect(gtfs.hasFareRule(fareRule2)).to.equal(false);
expect(gtfs.hasFareRule(fareRule3)).to.equal(false);

gtfs.addFareRules([fareRule1, fareRule2]);

expect(gtfs.getNumberOfFareRules()).to.equal(2);
expect(gtfs.hasFareRule(fareRule1)).to.equal(true);
expect(gtfs.hasFareRule(fareRule2)).to.equal(true);
expect(gtfs.hasFareRule(fareRule3)).to.equal(false);

gtfs.addFareRule(fareRule3);

expect(gtfs.getNumberOfFareRules()).to.equal(3);
expect(gtfs.hasFareRule(fareRule1)).to.equal(true);
expect(gtfs.hasFareRule(fareRule2)).to.equal(true);
expect(gtfs.hasFareRule(fareRule3)).to.equal(true);

gtfs.removeFareRule(fareRule2);

expect(gtfs.getNumberOfFareRules()).to.equal(2);
expect(gtfs.hasFareRule(fareRule1)).to.equal(true);
expect(gtfs.hasFareRule(fareRule2)).to.equal(false);
expect(gtfs.hasFareRule(fareRule3)).to.equal(true);

gtfs.removeFareRules([fareRule1, fareRule3]);

expect(gtfs.getNumberOfFareRules()).to.equal(0);
expect(gtfs.hasFareRule(fareRule1)).to.equal(false);
expect(gtfs.hasFareRule(fareRule2)).to.equal(false);
expect(gtfs.hasFareRule(fareRule3)).to.equal(false);

done();
});

it('Tests on gtfs.setFareRules() and .resetFareRules', (done) => {
const path = `${__dirname}/samples/1`;
const gtfs = new Gtfs(path);
const fareRule1 = buildFareRule(1);
const fareRule2 = buildFareRule(2);
const fareRule3 = buildFareRule(3);

expect(gtfs.getNumberOfFareRules()).to.equal(0);
expect(gtfs.hasFareRule(fareRule1)).to.equal(false);
expect(gtfs.hasFareRule(fareRule2)).to.equal(false);
expect(gtfs.hasFareRule(fareRule3)).to.equal(false);

gtfs.setFareRules(new Set([fareRule1, fareRule2]));

expect(gtfs.getNumberOfFareRules()).to.equal(2);
expect(gtfs.hasFareRule(fareRule1)).to.equal(true);
expect(gtfs.hasFareRule(fareRule2)).to.equal(true);
expect(gtfs.hasFareRule(fareRule3)).to.equal(false);

gtfs.resetFareRules();

expect(gtfs.getNumberOfFareRules()).to.equal(0);
expect(gtfs.hasFareRule(fareRule1)).to.equal(false);
expect(gtfs.hasFareRule(fareRule2)).to.equal(false);
expect(gtfs.hasFareRule(fareRule3)).to.equal(false);

done();
});

it('Tests on gtfs.forEachFareRule()', (done) => {
const path = `${__dirname}/samples/1`;
const gtfs = new Gtfs(path);
gtfs.addFareRules([buildFareRule(1), buildFareRule(3)]);

const fareIds = [];
gtfs.forEachFareRule(fareRule => fareIds.push(fareRule.fare_id));

expect(fareIds.sort()).to.deep.equal(['fareRule.fare_id.1', 'fareRule.fare_id.3']);

done();
});
});

function buildFareRule(integer) {
return {
'fare_id': `fareRule.fare_id.${integer}`,
'route_id': `fareRule.route_id.${integer}`,
'origin_id': `fareRule.origin_id.${integer}`,
'destination_id': `fareRule.destination_id.${integer}`,
'contains_id': `fareRule.contains_id.${integer}`,
};
}
2 changes: 1 addition & 1 deletion tests/test_generic_table_functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Tests on GTFS generic table functions', () => {
expect(agency0.agency_name).to.equal('Agency 0');

const expectedTableNames = [
'agency', 'calendar', 'calendar_dates', 'fare_attributes', 'frequencies',
'agency', 'calendar', 'calendar_dates', 'fare_attributes', 'fare_rules', 'frequencies',
'routes', 'stop_times', 'stops', 'trips', 'shapes', 'transfers', 'feed_info',
];
expect(Array.from(gtfs.getTableNames())).to.deep.equal(expectedTableNames);
Expand Down
6 changes: 1 addition & 5 deletions tests/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,4 @@ describe('Tests on GTFS', () => {

done();
});
});

function sortedKeys(map) {
return Array.from(map.keys()).sort();
}
});

0 comments on commit f4075ef

Please sign in to comment.