mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-20 22:16:26 +00:00
fix(tours): read ways past the grade cap as not asked instead of untagged
A long hike or mountain bike tour can run over more distinct ways than one grade request may ask about. The ways past that cap were never asked, yet the facets read them as carrying no surface, way type or grade in OpenStreetMap. They now land under 'Could not be asked this time' with the unanswered ones.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { TOUR_TRAIL_GRADE_MAX_WAYS } from '@trek/shared';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { encodePolyline } from '../../../../tests/helpers/polyline';
|
||||
@@ -175,4 +176,27 @@ describe('useRouteWays (BIK-01 to BIK-05, RUN-02)', () => {
|
||||
rerender(input({ matching: 'bike', withGrades: true }));
|
||||
expect(result.current.status).toBe('loading');
|
||||
});
|
||||
|
||||
it('FE-TOUR-WAYS-HOOK-010: ways past the cap were never asked, so they read as unasked, not as untagged (MAP-04)', async () => {
|
||||
const count = TOUR_TRAIL_GRADE_MAX_WAYS + 2;
|
||||
const edges = Array.from({ length: count }, (_, index) => ({
|
||||
begin_shape_index: 0,
|
||||
end_shape_index: 1,
|
||||
length: 0.01,
|
||||
use: 'path',
|
||||
way_id: index + 1,
|
||||
}));
|
||||
trace.valhallaTraceAttributes.mockResolvedValue({ ...ANSWER, edges });
|
||||
gradesRepo.grades.mockResolvedValue({ ways: [], unanswered: [5] });
|
||||
const { result } = renderHook(() => useRouteWays(input({ matching: 'foot', withGrades: true })));
|
||||
await settle();
|
||||
const asked = gradesRepo.grades.mock.calls[0][1].way_ids as number[];
|
||||
expect(asked).toHaveLength(TOUR_TRAIL_GRADE_MAX_WAYS);
|
||||
const unasked = result.current.grades?.unasked;
|
||||
expect(unasked?.has(5)).toBe(true);
|
||||
expect(unasked?.has(count - 1)).toBe(true);
|
||||
expect(unasked?.has(count)).toBe(true);
|
||||
expect(unasked?.has(1)).toBe(false);
|
||||
expect(unasked?.size).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -44,6 +44,20 @@ interface Question {
|
||||
withGrades: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ways whose grades stay unknown after an answer: those it left unanswered,
|
||||
* and those past the cap that were never asked, so neither reads as a way
|
||||
* OpenStreetMap records nothing for.
|
||||
*/
|
||||
function unaskedWays(ways: RouteWays, asked: readonly number[], unanswered: readonly number[]): Set<number> {
|
||||
const askedIds = new Set(asked);
|
||||
const unasked = new Set(unanswered);
|
||||
for (const edge of ways.edges) {
|
||||
if (edge.wayId !== null && !askedIds.has(edge.wayId)) unasked.add(edge.wayId);
|
||||
}
|
||||
return unasked;
|
||||
}
|
||||
|
||||
/** The ways of a route, and where asked for their grades; the grades' outcome as it came. */
|
||||
async function askRouteWays(
|
||||
{ tripId, route, matching, withGrades }: Question,
|
||||
@@ -59,7 +73,8 @@ async function askRouteWays(
|
||||
try {
|
||||
const answer = await tourTrailGradeRepo.grades(tripId, { way_ids: ids }, signal);
|
||||
const byWay = new Map(answer.ways.map((grade) => [grade.id, grade]));
|
||||
return { status: 'ready', ways, grades: { status: 'ready', byWay, unasked: new Set(answer.unanswered) } };
|
||||
const unasked = unaskedWays(ways, ids, answer.unanswered);
|
||||
return { status: 'ready', ways, grades: { status: 'ready', byWay, unasked } };
|
||||
} catch (failure) {
|
||||
const status = failure instanceof OnlineOnlyError ? 'offline' : 'failed';
|
||||
return { status: 'ready', ways, grades: { status, ...NO_GRADES } };
|
||||
|
||||
Reference in New Issue
Block a user