Skip to content

Commit

Permalink
gtfs: Allow to configure the walking time for stop aggregation
Browse files Browse the repository at this point in the history
fixes #807

Also fix the node's color, that, if the user's preferences was changed,
was not used by default.
  • Loading branch information
tahini committed Dec 14, 2023
1 parent 9353da9 commit b74e1de
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 12 deletions.
2 changes: 2 additions & 0 deletions locales/en/transit.json
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,8 @@
"MergeSamePeriodServices": "Merge services for same periods? (use with caution, the resulting service will contain all services for the same period)",
"DefaultAgencyColor": "Default agencies color",
"DefaultNodeColor": "Default nodes and stops color",
"StopAggregationWalkingRadiusSeconds": "Maximum walking time to aggregate stops in a node",
"StopAggregationWalkingRadiusSecondsHelp": "If the walking time between 2 stops is less than this value, they will be merged in the same transit node, located at the centroid of all the stops composing it. Put 0 to keep all stops in their original position. But calculation times will increase with the number of nodes.",
"ImportPaths": "Import paths",
"ImportTrips": "Import trips",
"OperationInProgress": "Import operation in progress",
Expand Down
2 changes: 2 additions & 0 deletions locales/fr/transit.json
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,8 @@
"MergeSamePeriodServices": "Combiner les services pour les mêmes périodes? (attention, le service résultant contiendra tous les services combinés)",
"DefaultAgencyColor": "Couleur par défaut des agences",
"DefaultNodeColor": "Couleur par défaut des noeuds et arrêts",
"StopAggregationWalkingRadiusSeconds": "Temps de marche maximal pour agréger les arrêts dans un noeud",
"StopAggregationWalkingRadiusSecondsHelp": "Si le temps de marche entre 2 arrêts est inférieur à cette valeur, ils seront rassemblés dans un seul noeud d'arrêt situé au centroïde de tous les arrêts le composant. Mettre 0 pour conserver les arrêts tels quels. Mais les temps de calcul vont augmenter avec le nombre de noeuds.",
"ImportPaths": "Importer les trajets",
"ImportTrips": "Importer les voyages",
"ImportGtfsData": "Importer les données",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,18 @@ export class StopImporter implements GtfsObjectPreparator<StopImportData> {
async import(stops: StopImportData[], importData: GtfsImportData): Promise<{ [key: string]: Node }> {
const importedStops: { [key: string]: Node } = {};
const defaultNodesColor = importData.nodes_color;
const aggregationWalkingRadiusSeconds =
importData.stopAggregationWalkingRadiusSeconds ||
Preferences.get('transit.nodes.defaultStopAggregationWalkingRadiusSecondsWhenImportingFromGtfs', 60);

const aggregationWalkingRadiusSeconds =
importData.stopAggregationWalkingRadiusSeconds === undefined
? Preferences.get('transit.nodes.defaultStopAggregationWalkingRadiusSecondsWhenImportingFromGtfs', 60)
: importData.stopAggregationWalkingRadiusSeconds;
const updatedNodesById = {};

// Split the nodes to import into already existing nodes to update and new nodes
const promiseQueue = new PQueue({ concurrency: 1 });

const promiseProducer = async (stopData: StopImportData) => {
// Even if aggregation radius is 0, we still run the query in case the node already exists in the database
const nodesInRadius = await this._existingNodes.nodesInWalkingTravelTimeRadiusSecondsAround(
{
type: 'Point',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { GtfsConstants, GtfsImportStatus } from 'transition-common/lib/api/gtfs'
import { GtfsImportData } from 'transition-common/lib/services/gtfs/GtfsImportTypes';
import GtfsImportServiceComponent from './GtfsImportServiceComponent';
import GtfsImportAgenciesComponent from './GtfsImportAgenciesComponent';
import GtfsImportNodesComponent from './GtfsImportNodesComponent';

type GtfsImportProps = WithTranslation;

Expand Down Expand Up @@ -101,7 +102,7 @@ class GtfsImportForm extends React.Component<GtfsImportProps, GtfsImportState> {
});
}

updateSelectedValue(path: keyof GtfsImportData, value: string | boolean) {
updateSelectedValue = (path: keyof GtfsImportData, value: string | boolean | number | undefined) => {
const importData = this.state.availableImportData;
if (!importData) {
return;
Expand All @@ -110,7 +111,7 @@ class GtfsImportForm extends React.Component<GtfsImportProps, GtfsImportState> {
this.setState({
availableImportData: importData
});
}
};

componentDidMount() {
this._zipFileUploader.on('start', this.onZipFileUploadStart);
Expand Down Expand Up @@ -179,6 +180,15 @@ class GtfsImportForm extends React.Component<GtfsImportProps, GtfsImportState> {
validator.set('defaultMinLayoverTimeSeconds', Preferences.current.transit.paths.defaultMinLayoverTimeSeconds);
console.log('gtfsImporter.prepared', validator);
validator.set('isPrepared', true);
if (validatorAttributes.stopAggregationWalkingRadiusSeconds === undefined) {
validatorAttributes.stopAggregationWalkingRadiusSeconds = Preferences.get(
'transit.nodes.defaultStopAggregationWalkingRadiusSecondsWhenImportingFromGtfs',
60
);
}
if (validatorAttributes.nodes_color === undefined) {
validatorAttributes.nodes_color = Preferences.get('transit.nodes.defaultColor', '#0086FF');
}
this.setState({
validator: validator,
gtfsDataImported: false,
Expand Down Expand Up @@ -435,13 +445,11 @@ class GtfsImportForm extends React.Component<GtfsImportProps, GtfsImportState> {
</div>
)}
{availableImportData?.agencies.length > 0 && availableImportData?.services.length > 0 && (
<div className="apptr__form-input-container _two-columns">
<label className="_flex">{this.props.t('transit:gtfs:DefaultNodeColor')}</label>
<InputColor
id={`formFieldTransitGtfsImporterFileDefaultNodeColor${validatorId}`}
value={availableImportData.nodes_color}
defaultColor={Preferences.get('transit.nodes.defaultColor', '#0086FF')}
onValueChange={(e) => this.updateSelectedValue('nodes_color', e.target.value)}
<div className="apptr__form-input-container">
<GtfsImportNodesComponent
id={validatorId}
updateSelectedValue={this.updateSelectedValue}
gtfsImportData={availableImportData}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2023, Polytechnique Montreal and contributors
*
* This file is licensed under the MIT License.
* License text available at https://opensource.org/licenses/MIT
*/
import React from 'react';
import { withTranslation, WithTranslation } from 'react-i18next';

import { GtfsImportData } from 'transition-common/lib/services/gtfs/GtfsImportTypes';
import InputColor from 'chaire-lib-frontend/lib/components/input/InputColor';
import Preferences from 'chaire-lib-common/lib/config/Preferences';
import InputWrapper from 'chaire-lib-frontend/lib/components/input/InputWrapper';
import InputString from 'chaire-lib-frontend/lib/components/input/InputString';
import { _isBlank } from 'chaire-lib-common/lib/utils/LodashExtensions';

export interface GtfsImportServiceComponentProps extends WithTranslation {
id: string;
updateSelectedValue: (path: keyof GtfsImportData, value: string | boolean | number | undefined) => void;
gtfsImportData: GtfsImportData;
}

const GtfsImportServiceComponent: React.FunctionComponent<GtfsImportServiceComponentProps> = (
props: GtfsImportServiceComponentProps
) => {
const stopAggregationWalkingTime = props.gtfsImportData.stopAggregationWalkingRadiusSeconds;

return (
<React.Fragment>
<InputWrapper
twoColumns={true}
label={props.t('transit:gtfs:StopAggregationWalkingRadiusSeconds')}
help={props.t('transit:gtfs:StopAggregationWalkingRadiusSecondsHelp')}
>
<InputString
id={`formFieldTransitGtfsImporterFileDefaultNodeColor${props.id}`}
value={stopAggregationWalkingTime === undefined ? '' : String(stopAggregationWalkingTime)}
pattern="[0-9]+"
onValueUpdated={({ value }) =>
props.updateSelectedValue(
'stopAggregationWalkingRadiusSeconds',
!_isBlank(value) ? parseInt(value) : undefined
)
}
/>
</InputWrapper>
<InputWrapper twoColumns={true} label={props.t('transit:gtfs:DefaultNodeColor')}>
<InputColor
id={`formFieldTransitGtfsImporterFileDefaultNodeColor${props.id}`}
value={props.gtfsImportData.nodes_color}
defaultColor={Preferences.get('transit.nodes.defaultColor', '#0086FF')}
onValueChange={(e) => props.updateSelectedValue('nodes_color', e.target.value)}
/>
</InputWrapper>
</React.Fragment>
);
};

export default withTranslation(['transit', 'main'])(GtfsImportServiceComponent);

0 comments on commit b74e1de

Please sign in to comment.