mirror of
https://github.com/HSLdevcom/digitransit-ui
synced 2025-09-20 20:32:47 +02:00
337 lines
10 KiB
JavaScript
337 lines
10 KiB
JavaScript
import omitBy from 'lodash/omitBy';
|
|
import moment from 'moment';
|
|
|
|
import {
|
|
filterModes,
|
|
getDefaultModes,
|
|
getModes,
|
|
modesAsOTPModes,
|
|
getBicycleCompatibleModes,
|
|
isTransportModeAvailable,
|
|
} from './modeUtils';
|
|
import { otpToLocation, getIntermediatePlaces } from './otpStrings';
|
|
import { getCitybikeNetworks, getDefaultNetworks } from './citybikes';
|
|
import { getCustomizedSettings } from '../store/localStorage';
|
|
import { estimateItineraryDistance } from './geo-utils';
|
|
|
|
/**
|
|
* Retrieves the default settings from the configuration.
|
|
*
|
|
* @param {*} config the configuration for the software installation
|
|
*/
|
|
export const getDefaultSettings = config => {
|
|
if (!config) {
|
|
return {};
|
|
}
|
|
return {
|
|
...config.defaultSettings,
|
|
modes: getDefaultModes(config).sort(),
|
|
allowedBikeRentalNetworks: config.transportModes.citybike.defaultValue
|
|
? getDefaultNetworks(config)
|
|
: [],
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Retrieves the current (customized) settings that are in use.
|
|
*
|
|
* @param {*} config the configuration for the software installation
|
|
* @param {*} query the query part of the current url
|
|
*/
|
|
export const getCurrentSettings = config => {
|
|
const defaultSettings = getDefaultSettings(config);
|
|
const customizedSettings = getCustomizedSettings();
|
|
return {
|
|
...defaultSettings,
|
|
...customizedSettings,
|
|
modes: customizedSettings?.modes
|
|
? [
|
|
...customizedSettings?.modes.filter(mode =>
|
|
isTransportModeAvailable(config, mode),
|
|
),
|
|
'WALK',
|
|
].sort()
|
|
: defaultSettings.modes,
|
|
allowedBikeRentalNetworks: getCitybikeNetworks(),
|
|
};
|
|
};
|
|
|
|
function getTicketTypes(settingsTicketType, defaultTicketType) {
|
|
// separator used to be _, map it to : to keep old URLs compatible
|
|
const remap = str => [`${str}`.replace('_', ':')];
|
|
const isRestriction = type => type !== 'none';
|
|
|
|
if (settingsTicketType) {
|
|
return isRestriction(settingsTicketType) ? remap(settingsTicketType) : null;
|
|
}
|
|
return defaultTicketType && isRestriction(defaultTicketType)
|
|
? remap(defaultTicketType)
|
|
: null;
|
|
}
|
|
/**
|
|
* Find an option nearest to the value
|
|
*
|
|
* @param value a number
|
|
* @param options array of numbers
|
|
* @returns on option from options that is closest to the provided value
|
|
*/
|
|
export const findNearestOption = (value, options) => {
|
|
let currNearest = options[0];
|
|
let diff = Math.abs(value - currNearest);
|
|
for (let i = 0; i < options.length; i++) {
|
|
const newdiff = Math.abs(value - options[i]);
|
|
if (newdiff < diff) {
|
|
diff = newdiff;
|
|
currNearest = options[i];
|
|
}
|
|
}
|
|
return currNearest;
|
|
};
|
|
|
|
function nullOrUndefined(val) {
|
|
return val === null || val === undefined;
|
|
}
|
|
|
|
const getNumberValueOrDefault = (value, defaultValue = undefined) =>
|
|
value !== undefined ? Number(value) : defaultValue;
|
|
|
|
export const getSettings = config => {
|
|
const custSettings = getCustomizedSettings();
|
|
|
|
return {
|
|
walkSpeed:
|
|
config.defaultOptions.walkSpeed.find(
|
|
option =>
|
|
option ===
|
|
getNumberValueOrDefault(
|
|
custSettings.walkSpeed,
|
|
config.defaultSettings.walkSpeed,
|
|
),
|
|
) ||
|
|
config.defaultOptions.walkSpeed.find(
|
|
option =>
|
|
option ===
|
|
findNearestOption(
|
|
getNumberValueOrDefault(
|
|
custSettings.walkSpeed,
|
|
config.defaultSettings.walkSpeed,
|
|
),
|
|
config.defaultOptions.walkSpeed,
|
|
),
|
|
),
|
|
walkReluctance: getNumberValueOrDefault(custSettings.walkReluctance),
|
|
walkBoardCost: getNumberValueOrDefault(custSettings.walkBoardCost),
|
|
modes: undefined,
|
|
accessibilityOption: getNumberValueOrDefault(
|
|
custSettings.accessibilityOption,
|
|
),
|
|
ticketTypes: custSettings.ticketTypes,
|
|
bikeSpeed:
|
|
config.defaultOptions.bikeSpeed.find(
|
|
option =>
|
|
option ===
|
|
getNumberValueOrDefault(
|
|
custSettings.bikeSpeed,
|
|
config.defaultSettings.bikeSpeed,
|
|
),
|
|
) ||
|
|
config.defaultOptions.bikeSpeed.find(
|
|
option =>
|
|
option ===
|
|
findNearestOption(
|
|
getNumberValueOrDefault(
|
|
custSettings.bikeSpeed,
|
|
config.defaultSettings.bikeSpeed,
|
|
),
|
|
config.defaultOptions.bikeSpeed,
|
|
),
|
|
),
|
|
allowedBikeRentalNetworks: custSettings.allowedBikeRentalNetworks,
|
|
includeBikeSuggestions: custSettings.includeBikeSuggestions,
|
|
includeCarSuggestions: custSettings.includeCarSuggestions,
|
|
includeParkAndRideSuggestions: custSettings.includeParkAndRideSuggestions,
|
|
showBikeAndParkItineraries: custSettings.showBikeAndParkItineraries,
|
|
};
|
|
};
|
|
|
|
const getShouldMakeParkRideQuery = (
|
|
linearDistance,
|
|
config,
|
|
settings,
|
|
defaultSettings,
|
|
) => {
|
|
return (
|
|
linearDistance > config.suggestCarMinDistance &&
|
|
(settings.includeParkAndRideSuggestions
|
|
? settings.includeParkAndRideSuggestions
|
|
: defaultSettings.includeParkAndRideSuggestions)
|
|
);
|
|
};
|
|
|
|
const getShouldMakeCarQuery = (
|
|
linearDistance,
|
|
config,
|
|
settings,
|
|
defaultSettings,
|
|
) => {
|
|
const forceCarRouting = config.showCO2InItinerarySummary
|
|
? config.showCO2InItinerarySummary
|
|
: defaultSettings.showCO2InItinerarySummary;
|
|
|
|
const includeCarSuggestions = settings.includeCarSuggestions
|
|
? settings.includeCarSuggestions
|
|
: defaultSettings.includeCarSuggestions;
|
|
return (
|
|
forceCarRouting ||
|
|
(linearDistance > config.suggestCarMinDistance && includeCarSuggestions)
|
|
);
|
|
};
|
|
|
|
export const hasStartAndDestination = ({ from, to }) =>
|
|
from && to && from !== '-' && to !== '-';
|
|
|
|
export const preparePlanParams = (config, useRelaxedRoutingPreferences) => (
|
|
{ from, to },
|
|
{
|
|
location: {
|
|
query: { arriveBy, intermediatePlaces, time },
|
|
},
|
|
},
|
|
) => {
|
|
const settings = getSettings(config);
|
|
const fromLocation = otpToLocation(from);
|
|
const toLocation = otpToLocation(to);
|
|
const intermediatePlaceLocations = getIntermediatePlaces({
|
|
intermediatePlaces,
|
|
});
|
|
let modesOrDefault = useRelaxedRoutingPreferences
|
|
? getDefaultModes(config)
|
|
: filterModes(
|
|
config,
|
|
getModes(config),
|
|
fromLocation,
|
|
toLocation,
|
|
intermediatePlaceLocations,
|
|
);
|
|
const defaultSettings = { ...getDefaultSettings(config) };
|
|
const allowedCitybikeNetworks = getDefaultNetworks(config);
|
|
// legacy settings used to set network name in uppercase in localstorage
|
|
const allowedBikeRentalNetworksMapped =
|
|
Array.isArray(settings.allowedBikeRentalNetworks) &&
|
|
settings.allowedBikeRentalNetworks.length > 0
|
|
? settings.allowedBikeRentalNetworks
|
|
.filter(
|
|
network =>
|
|
allowedCitybikeNetworks.includes(network) ||
|
|
allowedCitybikeNetworks.includes(network.toLowerCase()),
|
|
)
|
|
.map(network =>
|
|
allowedCitybikeNetworks.includes(network.toLowerCase())
|
|
? network.toLowerCase()
|
|
: network,
|
|
)
|
|
: defaultSettings.allowedBikeRentalNetworks;
|
|
if (
|
|
!allowedBikeRentalNetworksMapped ||
|
|
!allowedBikeRentalNetworksMapped.length
|
|
) {
|
|
// do not ask citybike routes if no networks are allowed
|
|
modesOrDefault = modesOrDefault.filter(mode => mode !== 'BICYCLE_RENT');
|
|
}
|
|
const formattedModes = modesAsOTPModes(modesOrDefault);
|
|
const wheelchair =
|
|
getNumberValueOrDefault(settings.accessibilityOption, defaultSettings) ===
|
|
1;
|
|
const includeBikeSuggestions =
|
|
settings.includeBikeSuggestions !== undefined
|
|
? settings.includeBikeSuggestions
|
|
: defaultSettings.includeBikeSuggestions;
|
|
const linearDistance = estimateItineraryDistance(
|
|
fromLocation,
|
|
toLocation,
|
|
intermediatePlaceLocations,
|
|
);
|
|
|
|
// Use defaults or user given settings
|
|
const ticketTypes = useRelaxedRoutingPreferences
|
|
? null
|
|
: getTicketTypes(settings.ticketTypes, defaultSettings.ticketTypes);
|
|
const walkReluctance = useRelaxedRoutingPreferences
|
|
? defaultSettings.walkReluctance
|
|
: settings.walkReluctance;
|
|
const walkBoardCost = useRelaxedRoutingPreferences
|
|
? defaultSettings.walkBoardCost
|
|
: settings.walkBoardCost;
|
|
|
|
return {
|
|
...defaultSettings,
|
|
...omitBy(
|
|
{
|
|
fromPlace: from,
|
|
toPlace: to,
|
|
from: fromLocation,
|
|
to: toLocation,
|
|
numItineraries: 5,
|
|
date: (time ? moment(time * 1000) : moment()).format('YYYY-MM-DD'),
|
|
time: (time ? moment(time * 1000) : moment()).format('HH:mm:ss'),
|
|
walkReluctance,
|
|
walkBoardCost,
|
|
minTransferTime: config.minTransferTime,
|
|
walkSpeed: settings.walkSpeed,
|
|
arriveBy: arriveBy === 'true',
|
|
wheelchair,
|
|
transferPenalty: config.transferPenalty,
|
|
bikeSpeed: settings.bikeSpeed,
|
|
optimize: config.optimize,
|
|
},
|
|
nullOrUndefined,
|
|
),
|
|
modes: formattedModes,
|
|
ticketTypes,
|
|
modeWeight: config.customWeights,
|
|
allowedBikeRentalNetworks: allowedBikeRentalNetworksMapped,
|
|
shouldMakeWalkQuery:
|
|
!wheelchair &&
|
|
linearDistance < config.suggestWalkMaxDistance &&
|
|
!config.onlyCarPlan,
|
|
shouldMakeBikeQuery:
|
|
!wheelchair &&
|
|
linearDistance < config.suggestBikeMaxDistance &&
|
|
includeBikeSuggestions &&
|
|
!config.onlyCarPlan,
|
|
shouldMakeCarQuery: getShouldMakeCarQuery(
|
|
linearDistance,
|
|
config,
|
|
settings,
|
|
defaultSettings,
|
|
),
|
|
shouldMakeParkRideQuery:
|
|
getShouldMakeParkRideQuery(
|
|
linearDistance,
|
|
config,
|
|
settings,
|
|
defaultSettings,
|
|
) && !config.onlyCarPlan,
|
|
showBikeAndPublicItineraries:
|
|
!wheelchair &&
|
|
config.showBikeAndPublicItineraries &&
|
|
modesOrDefault.length > 1 &&
|
|
includeBikeSuggestions,
|
|
showBikeAndParkItineraries:
|
|
!wheelchair &&
|
|
config.showBikeAndParkItineraries &&
|
|
modesOrDefault.length > 1 &&
|
|
!config.includePublicWithBikePlan
|
|
? settings.showBikeAndParkItineraries ||
|
|
defaultSettings.showBikeAndParkItineraries
|
|
: includeBikeSuggestions,
|
|
bikeAndPublicModes: [
|
|
{ mode: 'BICYCLE' },
|
|
...modesAsOTPModes(getBicycleCompatibleModes(config, modesOrDefault)),
|
|
],
|
|
bikeParkModes: [
|
|
{ mode: 'BICYCLE', qualifier: 'PARK' },
|
|
...formattedModes,
|
|
].filter(mode => mode.qualifier !== 'RENT'), // BICYCLE_RENT can't be used together with BICYCLE_PARK
|
|
};
|
|
};
|