mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(roadtrip): the hotel at the edge of a day stands, drives and reads right
A hotel row now takes its position and name from the trip's place instead of the stay row, which the planner fetches again only when a stay is edited. A moved pin no longer seats the hotel at its old spot while the server plans from the new one. The drive out of the morning hotel goes the way the first place is reached from it, the mode Days draws that leg in, and it is set in the shared rule so the browser and calculate_roadtrip agree. On the rail, a hotel row that took in the morning marker starts the line. A day that only drives from one stay to the next shows no stop count and takes a dropped stop as its first. The hotel keeps its pin on the desktop map, and the switch explains itself under its label and to screen readers. On the phone, the note about figures set on the desktop now sits above the switch it does not cover. The hint and the refusal on the hotel's drive say what they mean in all 23 languages. The via tools and the wiki say that a via into a booked night is kept but not used, the wiki states the overlap rule Days applies, and the arrived-from branch of the via anchor has tests.
This commit is contained in:
@@ -356,6 +356,20 @@ describe('road-trip MCP tools', () => {
|
||||
expect(testDb.prepare('SELECT COUNT(*) c FROM roadtrip_preferences WHERE trip_id = ?').get(trip.id)).toEqual({ c: 0 });
|
||||
});
|
||||
|
||||
it('MCP-ROADTRIP-014: both via tools say that a via on the drive into a booked night is kept and not used', async () => {
|
||||
// The planner refuses that click with a sentence; a tool stores the via as asked, so
|
||||
// the note on the tool is the only place the assistant can learn it changes nothing.
|
||||
const { user } = createUser(testDb);
|
||||
await withHarness(user.id, async (h) => {
|
||||
const tools = (await h.client.listTools()).tools;
|
||||
for (const name of ['add_route_via', 'add_route_vias']) {
|
||||
const description = tools.find(t => t.name === name)?.description ?? '';
|
||||
expect(description, name).toContain('roadtrip_hotel_bookends');
|
||||
expect(description, name).toContain('kept but not used');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('MCP-ROADTRIP-009: removing one that is not on the day is refused, not silently ignored', async () => {
|
||||
const { user, trip, day } = scenario();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
function hourlyRouter() {
|
||||
return {
|
||||
profiles: () => ['driving'],
|
||||
route: vi.fn(async (_user: number, _trip: number, _day: number, points: { lat: number; lng: number }[]) => ({
|
||||
route: vi.fn(async (_user: number, _trip: number, _day: number, points: { lat: number; lng: number }[], _profile?: string) => ({
|
||||
parts: points.slice(1).map(() => ({ distance: 60000, duration: 3600 })),
|
||||
avoidMissed: [],
|
||||
leg: {
|
||||
@@ -512,6 +512,23 @@ describe('a booked night at both ends of its days', () => {
|
||||
expect(lats(router)[1]).toEqual([HOTEL.lat, 45.3, 45.4, HOTEL.lat]);
|
||||
});
|
||||
|
||||
it('drives out of the morning hotel the way the first place is reached from it, as the browser and the day plan do', async () => {
|
||||
const { user, trip: created, router, plans } = simeon();
|
||||
db.prepare(
|
||||
"UPDATE day_assignments SET incoming_leg_transport_mode = 'walking' WHERE place_id = (SELECT id FROM places WHERE trip_id = ? AND name = 'P3')",
|
||||
).run(created.id);
|
||||
|
||||
const { calculated } = await plans.calculate(created.id, user.id);
|
||||
|
||||
expect(calculated.days[1].stops[0]).toMatchObject({ legMode: 'walking', bookend: { phase: 'morning' } });
|
||||
const runs = router.route.mock.calls.map((call) => [call[4], call[3].map((p: { lat: number }) => p.lat)]);
|
||||
// The hotel's leg on foot on its own, the rest of the day in the day's own mode.
|
||||
expect(runs).toContainEqual(['walking', [HOTEL.lat, 45.3]]);
|
||||
expect(runs).toContainEqual(['driving', [45.3, 45.4, HOTEL.lat]]);
|
||||
// The other mornings are reached no particular way and stay in one run.
|
||||
expect(runs).toContainEqual(['driving', [HOTEL.lat, 45.5, 45.6, HOTEL.lat]]);
|
||||
});
|
||||
|
||||
it('drives the stored days while the trip has it off, and a preview can switch it either way', async () => {
|
||||
const off = simeon({});
|
||||
const stored = await off.plans.calculate(off.trip.id, off.user.id);
|
||||
|
||||
Reference in New Issue
Block a user