Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 59 additions & 2 deletions src/components/settings-panel/settings-options.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BicycleType } from '@/components/types';
import type { BicycleType, PedestrianType } from '@/components/types';

interface NumericSetting {
name: string;
Expand Down Expand Up @@ -194,6 +194,32 @@ const gatePenalty = {
},
};

const destinationOnlyPenalty = {
name: 'Destination-only Penalty',
param: 'destination_only_penalty',
description:
'A penalty applied when entering an road which is only allowed to enter if necessary to reach the destination.',
unit: 'sec',
settings: {
min: 0,
max: 600,
step: 30,
},
};

const elevatorPenalty = {
name: 'Elevator Penalty',
param: 'elevator_penalty',
description:
'A penalty in seconds added to each transition via an elevator node or onto an elevator edge. Higher values apply larger cost penalties to avoid elevators.',
unit: 'sec',
settings: {
min: 0,
max: 600,
step: 30,
},
};

const tollBoothCost = {
name: 'Toll Booth Cost',
param: 'toll_booth_cost',
Expand Down Expand Up @@ -551,6 +577,29 @@ const bicycleType = {
],
};

const pedestrianType = {
name: 'Pedestrian Type',
description: `One of "foot", "wheelchair", "blind". If set to blind, enables additional route instructions, especially useful for blind users: Announcing crossed streets, the stairs, bridges, tunnels, gates and bollards, which need to be passed on route; information about traffic signals on crosswalks; route numbers not announced for named routes. If set to wheelchair, changes the defaults for max_distance, walking_speed, and step_penalty to be better aligned to the needs of wheelchair users.`,
param: 'type',
enums: [
{
key: 'Foot',
text: 'Foot',
value: 'Foot',
},
{
key: 'Wheelchair',
text: 'Wheelchair',
value: 'Wheelchair',
},
{
key: 'Blind',
text: 'Blind',
value: 'Blind',
},
],
};

const cyclingSpeed = {
name: 'Cycling Speed',
param: 'cycling_speed',
Expand Down Expand Up @@ -826,6 +875,8 @@ export const settingsInit = {
use_living_streets: 0.5,
use_tracks: 0,
private_access_penalty: 450,
destination_only_penalty: 300,
elevator_penalty: 120,
ignore_closures: false,
ignore_restrictions: false,
ignore_access: false,
Expand All @@ -836,6 +887,7 @@ export const settingsInit = {
shortest: false,
exclude_cash_only_tolls: false,
bicycle_type: 'Hybrid' as BicycleType,
type: 'Foot' as PedestrianType,
cycling_speed: 20,
use_roads: 0.5,
use_hills: 0.5,
Expand Down Expand Up @@ -891,6 +943,7 @@ const commonVehicleProfileNumeric = [
topSpeed,
fixedSpeed,
privateAccessPenalty,
destinationOnlyPenalty,
closureFactor,
...serviceSettings,
...gateSettings,
Expand Down Expand Up @@ -964,10 +1017,14 @@ export const profileSettings: Record<SettingsProfile, SettingsGroup> = {
sidewalkFactor,
alleyFactor,
drivewayFactor,
privateAccessPenalty,
destinationOnlyPenalty,
elevatorPenalty,
stepPenalty,
maxHikingDifficulty,
],
[shortest]
[shortest],
[pedestrianType]
),

motor_scooter: createSettings(
Expand Down
56 changes: 56 additions & 0 deletions src/components/settings-panel/settings-panel.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ vi.mock('@/stores/common-store', () => ({
use_living_streets: 0.5,
alternates: 2,
bicycle_type: 'Hybrid',
type: 'Foot',
service_penalty: 15,
service_factor: 1,
maneuver_penalty: 5,
Expand All @@ -61,6 +62,16 @@ vi.mock('@/stores/common-store', () => ({
country_crossing_cost: 600,
country_crossing_penalty: 0,
turn_penalty_factor: 0,
use_lit: 0.5,
walking_speed: 5.1,
walkway_factor: 1,
sidewalk_factor: 1,
alley_factor: 2,
driveway_factor: 5,
step_penalty: 0,
max_hiking_difficulty: 1,
destination_only_penalty: 300,
elevator_penalty: 120,
},
settingsPanelOpen: true,
updateSettings: mockUpdateSettings,
Expand Down Expand Up @@ -501,6 +512,51 @@ describe('SettingsPanel', () => {
});
});

describe('Enum Settings', () => {
it('should render Bicycle Type select only once for bicycle profile', () => {
renderWithQueryClient(<SettingsPanel />);
const bicycleTypeLabels = screen.getAllByText('Bicycle Type');
expect(bicycleTypeLabels).toHaveLength(1);
});

it('should display current bicycle_type value from settings', () => {
renderWithQueryClient(<SettingsPanel />);
// The mock has bicycle_type: 'Hybrid'
expect(screen.getByText('Hybrid')).toBeInTheDocument();
});

it('should render Pedestrian Type select only once for pedestrian profile', () => {
mockUseSearch.mockReturnValue({ profile: 'pedestrian' });
renderWithQueryClient(<SettingsPanel />);
const pedestrianTypeLabels = screen.getAllByText('Pedestrian Type');
expect(pedestrianTypeLabels).toHaveLength(1);
});

it('should display current pedestrian type value from settings', () => {
mockUseSearch.mockReturnValue({ profile: 'pedestrian' });
renderWithQueryClient(<SettingsPanel />);
// The mock has type: 'Foot'
expect(screen.getByText('Foot')).toBeInTheDocument();
});

it('should render bicycle type combobox with correct id', () => {
renderWithQueryClient(<SettingsPanel />);
const bicycleTypeSelect = screen.getByRole('combobox', {
name: /Bicycle Type/i,
});
expect(bicycleTypeSelect).toBeInTheDocument();
});

it('should render pedestrian type combobox with correct id', () => {
mockUseSearch.mockReturnValue({ profile: 'pedestrian' });
renderWithQueryClient(<SettingsPanel />);
const pedestrianTypeSelect = screen.getByRole('combobox', {
name: /Pedestrian Type/i,
});
expect(pedestrianTypeSelect).toBeInTheDocument();
});
});

describe('Language Picker', () => {
it('should render Directions Language section when activeTab is directions', () => {
renderWithQueryClient(<SettingsPanel />);
Expand Down
4 changes: 2 additions & 2 deletions src/components/settings-panel/settings-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ export const SettingsPanel = () => {
id={option.param}
label={option.name}
description={option.description}
placeholder="Select Bicycle Type"
value={settings.bicycle_type as string}
placeholder={`Select ${option.name}`}
value={settings[option.param] as string}
options={option.enums}
onValueChange={(value) => {
handleUpdateSettings({
Expand Down
25 changes: 4 additions & 21 deletions src/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type Settings = Record<
>;

export type BicycleType = 'Hybrid' | 'Road' | 'City' | 'Cross' | 'Mountain';
export type PedestrianType = 'Foot' | 'Wheelchair' | 'Blind';

export interface PossibleSettings {
maneuver_penalty: number;
Expand All @@ -37,6 +38,8 @@ export interface PossibleSettings {
use_living_streets: number;
use_tracks: number;
private_access_penalty: number;
destination_only_penalty: number;
elevator_penalty: number;
ignore_closures: boolean;
ignore_restrictions: boolean;
ignore_access: boolean;
Expand All @@ -47,6 +50,7 @@ export interface PossibleSettings {
shortest: boolean;
exclude_cash_only_tolls: boolean;
bicycle_type: BicycleType;
type: PedestrianType;
cycling_speed: number;
use_roads: number;
use_hills: number;
Expand Down Expand Up @@ -180,27 +184,6 @@ export interface Center {
addressindex: number;
}

export interface Costing {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these were unused

maneuver_penalty: number;
use_ferry: number;
use_living_streets: number;
service_penalty: number;
service_factor: number;
shortest: boolean;
bicycle_type: string;
cycling_speed: number;
use_roads: number;
use_hills: number;
avoid_bad_surfaces: number;
gate_penalty: number;
gate_cost: number;
}

export interface Directions {
alternates: number;
exclude_polygons: GeoJSON.GeoJSON[];
}

export interface NominationResponse {
place_id: number;
licence: string;
Expand Down
12 changes: 12 additions & 0 deletions src/utils/valhalla.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ describe('valhalla.ts', () => {

const mockSettings: Settings = {
costing: {
destination_only_penalty: 300,
elevator_penalty: 300,
maneuver_penalty: 5,
country_crossing_penalty: 0,
country_crossing_cost: 600,
Expand All @@ -225,6 +227,7 @@ describe('valhalla.ts', () => {
shortest: false,
exclude_cash_only_tolls: false,
bicycle_type: 'Hybrid',
type: 'Foot',
cycling_speed: 20,
use_roads: 0.5,
use_hills: 0.5,
Expand Down Expand Up @@ -260,6 +263,8 @@ describe('valhalla.ts', () => {
speed_types: [],
},
directions: {
destination_only_penalty: 300,
elevator_penalty: 300,
maneuver_penalty: 5,
country_crossing_penalty: 0,
country_crossing_cost: 600,
Expand All @@ -286,6 +291,7 @@ describe('valhalla.ts', () => {
shortest: false,
exclude_cash_only_tolls: false,
bicycle_type: 'Hybrid',
type: 'Foot',
cycling_speed: 20,
use_roads: 0.5,
use_hills: 0.5,
Expand Down Expand Up @@ -719,6 +725,8 @@ describe('valhalla.ts', () => {

const mockSettings: Settings = {
costing: {
destination_only_penalty: 300,
elevator_penalty: 300,
maneuver_penalty: 5,
country_crossing_penalty: 0,
country_crossing_cost: 600,
Expand All @@ -745,6 +753,7 @@ describe('valhalla.ts', () => {
shortest: false,
exclude_cash_only_tolls: false,
bicycle_type: 'Hybrid',
type: 'Foot',
cycling_speed: 20,
use_roads: 0.5,
use_hills: 0.5,
Expand Down Expand Up @@ -780,6 +789,8 @@ describe('valhalla.ts', () => {
speed_types: [],
},
directions: {
destination_only_penalty: 300,
elevator_penalty: 300,
maneuver_penalty: 5,
country_crossing_penalty: 0,
country_crossing_cost: 600,
Expand All @@ -806,6 +817,7 @@ describe('valhalla.ts', () => {
shortest: false,
exclude_cash_only_tolls: false,
bicycle_type: 'Hybrid',
type: 'Foot',
cycling_speed: 20,
use_roads: 0.5,
use_hills: 0.5,
Expand Down