trips/mock/data.js
Greg Pomerantz efde2cc71b maps project: design, survey, mock app, and route-aware planning backend
- DESIGN.md: full design incl. driving-trip requirements (R1-R4),
  stays model, focus mode, mobile, provenance rules
- SURVEY.md: open-source landscape
- mock/: interaction mock (Florence itinerary, focus mode, stays,
  region stops, mobile layout)
- router/: Go module (stdlib-only) with Router interface
  (Valhalla + OSRM backends), stop_cost, optimize_stops, corridor,
  routectl CLI, bench (5 real NE-corridor tasks, 26 checks passing),
  integration tests, and setup-osrm.sh for the self-hosted router
- osm/: NH+MA+CT+NY PBFs (gitignored) + setup artifacts
2026-09-06 00:05:17 -04:00

265 lines
18 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Fake data layer — same shapes the real API will return.
// Each stop: day, slot (mutual-exclusion group), state: planned | maybe | alt.
// Only one `planned` stop per slot per day; `alt`/`maybe` don't count against
// the day's time budget.
window.MOCK = {
trip: {
id: 'trip-2026-09',
version: 1,
title: 'Florence 1215 Sep',
// stays, not a single hotel: {hotel, place, checkIn, checkOut, state}.
// Days resolve their anchor per date; >1 candidate stay covering the
// same nights → worst-case anchoring for those nights.
// Multi-city trips = more stays, each anchoring its own dates.
stays: [
{ id: 'ST1', name: 'Hotel Palagio', at: [43.7684, 11.2566], place: 'Florence',
checkIn: '2026-09-12', checkOut: '2026-09-15', state: 'booked', price: 180 },
],
places: [
{ id: 'PL1', name: 'Florence', bbox: [43.73, 11.21, 43.80, 11.29],
center: [43.769, 11.255], vibe: 'art + food, relaxed pace',
dates: ['2026-09-12', '2026-09-15'] }
],
bookings: [
{ type: 'hotel', name: 'Hotel Palagio', ref: 'H-77821',
dates: '1215 Sep', where: [43.7684, 11.2566],
status: 'booked', source: 'user_booking' },
{ type: 'train', name: 'Frecciarossa 9512', ref: 'F-55812',
from: 'Firenze SMN', to: 'Pisa Centrale', date: '2026-09-15',
depart: '09:12', arrive: '09:58', status: 'booked', source: 'user_booking',
stations: { from: [43.7726, 11.2597], to: [43.7157, 10.3922] } }
]
},
days: [
{ id: 'D1', date: '2026-09-12', label: 'Day 1 · Fri 12',
startMin: 8 * 60, wakingHours: 11,
base: { name: 'Hotel Palagio', at: [43.7684, 11.2566] },
legs: [],
stops: [
{ id: 'S1', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
slot: 'breakfast', state: 'planned',
at: [43.7684, 11.2566], dur: 30, durConf: 3,
suggested: { value: 30, conf: 2, src: 'triptadvisor.com' } },
{ id: 'S2', name: 'Palazzo Pitti', kind: 'visit', slot: 'visit', state: 'planned',
url: 'https://www.palazzopittiturin.it',
at: [43.7639, 11.2518], dur: 60, durConf: 5, // user override (sticky)
suggested: { value: 150, conf: 2, src: 'wikivoyage.org' },
price: { amount: 14, cur: '€', conf: 2, src: 'uffizi.it' },
note: 'guides suggest 23 h', img: ['🏛️', 'Palazzo Pitti', 'linear-gradient(135deg,#b5533c,#7a3a2c)',
'https://thumb.wikimedia.org/wikipedia/commons/thumb/7/72/Palacio_Pitti%2C_Florencia%2C_Italia%2C_2022-09-18%2C_DD_197.jpg/1280px-Palacio_Pitti%2C_Florencia%2C_Italia%2C_2022-09-18%2C_DD_197.jpg'],
detail: {
summary: 'The Medici familys riverside palazzo: the Galleria Palatina (Portraiture, the 500 Room) and the modern-art Galleria dArte Moderna. Rooms are small and crowded in peak season — the apartments alone run 1.52 h if you linger, ~1 h for the highlights. September afternoons are the sweet spot: light is good for photos and lines thin after 16:00.',
links: [
{ label: 'Official site', href: 'https://www.palazzopittiturin.it' },
{ label: 'Tickets', href: 'https://www.uffizi.it/en/visit/tickets' },
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Attraction_Review-g187791-d183726-Reviews-Palazzo_Pitti-Florence_Tuscany.html' },
{ label: 'Reddit r/Florence', href: 'https://www.reddit.com/r/Florence/search/?q=palazzo+pitti&restrict_sr=1' }
] } },
{ id: 'S4', name: 'Lunch — Trattoria Mario', kind: 'meal', mealKind: 'lunch',
slot: 'lunch', state: 'planned', url: 'https://www.trattoriamario.it',
at: [43.7667, 11.2544], dur: 45, durConf: 3,
suggested: { value: 90, conf: 2, src: 'trattoriamario.it' },
price: { amount: 25, cur: '€', conf: 2, src: 'trattoriamario.it' },
img: ['🍝', 'Trattoria Mario', 'linear-gradient(135deg,#d08b3c,#9c5f1e)',
'https://upload.wikimedia.org/wikipedia/commons/1/12/Bistecca_alla_fiorentina-01.jpg'],
detail: {
summary: 'A no-frills Florentine kitchen on Via dei Neri, open since 1954. Counter seating, short menu (bistecca, lampredotto, tripe soup), and the queue is real — arriving as lunch opens (12:00) is the difference between 10 minutes and 40. Budget ~1 h including eating.',
links: [
{ label: 'Official site', href: 'https://www.trattoriamario.it' },
{ label: 'Menu', href: 'https://www.trattoriamario.it/menu' },
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Restaurant_Review-g187791-d310951-Reviews-Trattoria_Mario-Florence_Tuscany.html' },
{ label: 'Reddit r/food', href: 'https://www.reddit.com/r/food/search/?q=trattoria+mario+florence&restrict_sr=1' }
] } },
{ id: 'S5', name: 'Boboli Gardens', kind: 'visit', slot: 'visit', state: 'planned',
url: 'https://www.boboli.it',
at: [43.7579, 11.2463], dur: 120, durConf: 3,
suggested: { value: 120, conf: 2, src: 'boboli.it' },
price: { amount: 10, cur: '€', conf: 2, src: 'uffizi.it' },
img: ['🌿', 'Boboli Gardens', 'linear-gradient(135deg,#4f9e63,#2c6b40)',
'https://thumb.wikimedia.org/wikipedia/commons/thumb/d/d2/Obelisco%2C_Boboli_Gardens%2C_Florence_%2826408174180%29.jpg/1280px-Obelisco%2C_Boboli_Gardens%2C_Florence_%2826408174180%29.jpg'],
detail: {
summary: 'The Medicis formal garden behind Pitti — statues, the Apollo fountain, a hilltop view over the city. The full loop with the Accademia annex runs 2 h; the upper terraces alone are a fine 45-minute pace-break. Pairs naturally with Pitti: the entrance is the courtyard behind it.',
links: [
{ label: 'Official site', href: 'https://www.boboli.it' },
{ label: 'Tickets', href: 'https://www.uffizi.it/en/visit/tickets' },
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Attraction_Review-g187791-d183872-Reviews-Giardini_Di_Boboli-Florence_Tuscany.html' },
{ label: 'Reddit r/Florence', href: 'https://www.reddit.com/r/Florence/search/?q=boboli&restrict_sr=1' }
] } },
{ id: 'S6', name: 'Gelato — Vivoli', kind: 'meal', mealKind: 'snack',
slot: 'snack', state: 'planned',
at: [43.7680, 11.2537], dur: 20, durConf: 3,
suggested: { value: 20, conf: 1, src: null },
price: null,
img: ['🍦', 'Vivoli gelato', 'linear-gradient(135deg,#e0a5c0,#a56a92)'] },
{ id: 'S7', name: 'Lunch — Ristorante Santini', kind: 'meal', mealKind: 'lunch',
slot: 'lunch', state: 'alt', url: 'https://www.santini.it',
at: [43.7646, 11.2528], dur: 75, durConf: 3,
suggested: { value: 90, conf: 2, src: 'santini.it' },
price: { amount: 45, cur: '€', conf: 2, src: 'santini.it' },
img: ['🍷', 'Ristorante Santini', 'linear-gradient(135deg,#7a4a5c,#4c2b3a)',
'https://thumb.wikimedia.org/wikipedia/commons/thumb/c/c0/View_from_Giotto%27s_Bell_Tower_-_Florence.jpg/1280px-View_from_Giotto%27s_Bell_Tower_-_Florence.jpg'],
detail: {
summary: 'A classic Florentine restaurant in a 16th-century building on the Arno — the terrace looks across to Pitti. Set tables, longer menus, lunch from 12:30. The step-up option: worth holding if Marios queue looks long, or if the day goes well and you want to mark it.',
links: [
{ label: 'Official site', href: 'https://www.santini.it' },
{ label: 'Menu', href: 'https://www.santini.it/en/menu' },
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Restaurant_Review-g187791-d1442007-Reviews-Ristorante_Santini-Florence_Tuscany.html' },
{ label: 'Reddit r/food', href: 'https://www.reddit.com/r/food/search/?q=santini+florence&restrict_sr=1' }
] } }
]
},
{ id: 'D2', date: '2026-09-13', label: 'Day 2 · Sat 13',
startMin: 8 * 60 + 30, wakingHours: 11,
base: { name: 'Hotel Palagio', at: [43.7684, 11.2566] },
legs: [],
stops: [
{ id: 'S8', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
slot: 'breakfast', state: 'planned',
at: [43.7684, 11.2566], dur: 30, durConf: 3,
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
{ id: 'S9', name: 'Galleria dellAccademia (David)', kind: 'visit', slot: 'visit', state: 'planned',
url: 'https://www.galleriaaccademia.firenze.it',
at: [43.7734, 11.2628], dur: 90, durConf: 3,
suggested: { value: 120, conf: 2, src: 'wikivoyage.org' },
price: { amount: 16, cur: '€', conf: 2, src: 'galleriaaccademia.firenze.it' },
img: ['🗿', 'Accademia', 'linear-gradient(135deg,#6b7280,#3f4650)'],
detail: {
summary: 'Home of the original David plus Donatellos Prigione. Timed-entry tickets, and the David room moves in batches — a 09:30 slot is noticeably calmer than midday. Allow ~90 min; 2 h if you do the whole collection.',
links: [
{ label: 'Official site', href: 'https://www.galleriaaccademia.firenze.it' },
{ label: 'Tickets', href: 'https://www.galleriaaccademia.firenze.it/en/tickets' },
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Attraction_Review-g187791-d183692-Reviews-Galleria_dell_Accademia-Florence_Tuscany.html' },
{ label: 'Reddit r/Florence', href: 'https://www.reddit.com/r/Florence/search/?q=accademia+david&restrict_sr=1' }
] } },
{ id: 'S10', name: 'Lunch — Trattoria Sostanza', kind: 'meal', mealKind: 'lunch',
slot: 'lunch', state: 'planned', url: 'https://www.sostanza.it',
at: [43.7609, 11.2469], dur: 75, durConf: 3,
suggested: { value: 90, conf: 2, src: 'tripadvisor.com' },
price: { amount: 35, cur: '€', conf: 2, src: 'tripadvisor.com' },
img: ['🍕', 'Trattoria Sostanza', 'linear-gradient(135deg,#b0563c,#7a3a2c)'],
detail: {
summary: 'Oltrarno kitchen a short walk across the Arno from the Accademia: Florentine classics, a proper wine list, and a roomy back — the kind of lunch that runs long. Reservations recommended on Saturdays.',
links: [
{ label: 'Official site', href: 'https://www.sostanza.it' },
{ label: 'Menu', href: 'https://www.sostanza.it/menu' },
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Restaurant_Review-g187791-d559983-Reviews-Trattoria_Sostanza-Florence_Tuscany.html' },
{ label: 'Reddit r/food', href: 'https://www.reddit.com/r/food/search/?q=sostanza+florence&restrict_sr=1' }
] } },
{ id: 'S11', name: 'Oltrarno stroll · San Niccolò', kind: 'visit', slot: 'visit', state: 'planned',
at: [43.7613, 11.2497], dur: 60, durConf: 3,
suggested: { value: 60, conf: 1, src: null },
price: null,
img: ['⛪', 'Oltrarno', 'linear-gradient(135deg,#8f7a4f,#5c4d2e)'] }
]
},
{ id: 'D3', date: '2026-09-14', label: 'Day 3 · Sun 14',
startMin: 9 * 60, wakingHours: 11,
base: { name: 'Hotel Palagio', at: [43.7684, 11.2566] },
legs: [],
stops: [
{ id: 'S12', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
slot: 'breakfast', state: 'planned',
at: [43.7684, 11.2566], dur: 30, durConf: 3,
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
{ id: 'S13', name: 'San Marco & cloister', kind: 'visit', slot: 'visit', state: 'planned',
at: [43.7723, 11.2597], dur: 45, durConf: 3,
suggested: { value: 45, conf: 1, src: null },
price: { amount: 8, cur: '€', conf: 1, src: null },
img: ['🖼️', 'San Marco', 'linear-gradient(135deg,#7a6a4f,#4d422e)'] },
{ id: 'S14', name: 'Aperitivo — Il Latte', kind: 'meal', mealKind: 'dinner',
slot: 'dinner', state: 'maybe',
url: 'https://www.illatte.it',
at: [43.7700, 11.2560], dur: 60, durConf: 3,
suggested: { value: 60, conf: 1, src: null },
price: { amount: 12, cur: '€', conf: 2, src: 'tripadvisor.com' },
img: ['🥂', 'Il Latte', 'linear-gradient(135deg,#c9a13c,#8f6f1e)'] }
]
},
{ id: 'D4', date: '2026-09-15', label: 'Day 4 · Mon 15', isDeparture: true,
startMin: 8 * 60, wakingHours: 11,
base: { name: 'Hotel Palagio', at: [43.7684, 11.2566] },
legs: [],
stops: [
{ id: 'S15', name: 'Breakfast & check-out', kind: 'meal', mealKind: 'breakfast',
slot: 'breakfast', state: 'planned',
at: [43.7684, 11.2566], dur: 30, durConf: 3,
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
{ id: 'S16', name: 'Train → Pisa Centrale', kind: 'transit', slot: 'transit', state: 'planned',
at: [43.7726, 11.2597], dur: 30, durConf: 4,
transit: { name: 'Frecciarossa 9512', ref: 'F-55812',
from: 'Firenze SMN', to: 'Pisa Centrale',
depart: '09:12', arrive: '09:58', arriveBy: '08:42',
buffer: '30 min before departure' },
suggested: null,
price: { amount: 45, cur: '€', conf: 4, src: 'booking' },
img: ['🚄', 'Frecciarossa 9512', 'linear-gradient(135deg,#274b8f,#16294d)'] }
]
}
],
// focus-mode candidate pools (what a slot search returns)
candidates: {
hotel: [
{ id: 'H1', name: 'Hotel Palagio', at: [43.7684, 11.2566], price: 180, dur: null,
tags: ['central', 'quiet', 'refundable'], pitch: 'Where you are now — refundable until the 8th.', url: null },
{ id: 'H2', name: 'Hotel Savoy', at: [43.7726, 11.2565], price: 210, dur: null,
tags: ['near SMN', 'grand', 'rooftop'], pitch: 'Grand hotel by the station — handy for the 15th, 10 min from the centre.', url: null },
{ id: 'H3', name: 'Residenza Oltrarno', at: [43.7604, 11.2510], price: 140, dur: null,
tags: ['oltrarno', 'small', 'value'], pitch: 'Six rooms above a bookshop — cheaper, and puts you on the south side.', url: null },
],
lunch: [
{ id: 'C1', name: 'Trattoria Mario', at: [43.7667, 11.2544], price: 25, dur: 90,
tags: ['counter', 'local', 'queue'], pitch: 'No-frills counter since 1954 — the queue is the point.',
url: 'https://www.trattoriamario.it', img: ['🍝', 'Trattoria Mario', 'linear-gradient(135deg,#d08b3c,#9c5f1e)', 'https://upload.wikimedia.org/wikipedia/commons/1/12/Bistecca_alla_fiorentina-01.jpg'] },
{ id: 'C2', name: 'Ristorante Santini', at: [43.7646, 11.2528], price: 45, dur: 90,
tags: ['views', 'terrace', 'splurge'], pitch: '16th-century set tables on the Arno, terrace across from Pitti.',
url: 'https://www.santini.it', img: ['🍷', 'Santini', 'linear-gradient(135deg,#7a4a5c,#4c2b3a)'] },
{ id: 'C3', name: 'Trattoria Sostanza', at: [43.7609, 11.2469], price: 35, dur: 90,
tags: ['oltrarno', 'roomy', 'wine'], pitch: 'Oltrarno kitchen, proper wine list, a roomy back — runs long.',
url: 'https://www.sostanza.it', img: ['🍕', 'Sostanza', 'linear-gradient(135deg,#b0563c,#7a3a2c)'] },
{ id: 'C4', name: 'Vendemmia', at: [43.7735, 11.2585], price: 30, dur: 75,
tags: ['vegetarian', 'garden', 'near SMN'], pitch: 'Garden terrace by SMN, strong vegetarian menu, calmer pace.',
url: 'https://www.vendemmia.it', img: ['🥗', 'Vendemmia', 'linear-gradient(135deg,#5f9e6b,#33613c)'] },
{ id: 'C5', name: 'La Cantina di San Niccolò', at: [43.7615, 11.2490], price: 22, dur: 75,
tags: ['cellar', 'cozy', 'oltrarno'], pitch: 'Stone cellar, candlelight, short honest menu — book ahead.',
url: 'https://www.lacantina.it', img: ['🕯️', 'La Cantina', 'linear-gradient(135deg,#8f7a4f,#5c4d2e)'] },
{ id: 'C6', name: 'Buonami Pizza', at: [43.7680, 11.2550], price: 15, dur: 45,
tags: ['fast', 'casual', 'near hotel'], pitch: 'Two-stop, fast, good — the reset-button lunch.',
url: 'https://www.buonami.it', img: ['🍕', 'Buonami', 'linear-gradient(135deg,#c98a2c,#8a5f1a)'] }
],
visit: [
{ id: 'V1', name: 'Piazzale Michelangelo', at: [43.7669, 11.2455], price: 0, dur: 60,
tags: ['views', 'sunset', 'free'], pitch: 'The postcard view — best from 17:00 as the light warms.',
url: 'https://en.wikipedia.org/wiki/Piazzale_Michelangelo', img: ['🌇', 'Piazzale Michelangelo', 'linear-gradient(135deg,#c97a3c,#8a4f1a)'] },
{ id: 'V2', name: 'San Miniato al Monte', at: [43.7620, 11.2521], price: 4, dur: 60,
tags: ['views', 'romanesque', 'calm'], pitch: 'Romanesque basilica on the hill — quiet, cool in the afternoon.',
url: 'https://en.wikipedia.org/wiki/San_Miniato_al_Monte', img: ['⛪', 'San Miniato', 'linear-gradient(135deg,#8f9a7a,#5c644d)'] },
{ id: 'V3', name: 'Santo Spirito square', at: [43.7603, 11.2496], price: 0, dur: 45,
tags: ['square', 'lazier', 'market'], pitch: 'Oltrarnos lazy square; Saturdays market is the event.',
url: 'https://en.wikipedia.org/wiki/Santo_Spirito,_Florence', img: ['☕', 'Santo Spirito', 'linear-gradient(135deg,#a58a6a,#6d5840)'] },
{ id: 'V4', name: 'Terme di Caracalla (ruins)', at: [43.7589, 11.2707], price: 10, dur: 75,
tags: ['ruins', 'open', 'afternoon'], pitch: 'Third-century baths in open fields — cool, empty, odd.',
url: 'https://en.wikipedia.org/wiki/Baths_of_Caracalla', img: ['🏛️', 'Terme di Caracalla', 'linear-gradient(135deg,#b0a58a,#756a4f)'] }
]
},
vibes: [
{ id: 'v1', label: 'art & food · relaxed pace' },
{ id: 'v2', label: 'gardens & walking' },
{ id: 'v3', label: 'day trip · Fiesole' },
{ id: 'v4', label: 'views & aperitivo' }
],
suggestions: [
{ stop: 'S2', pitch: 'The Palazzo Medicis private apartments — less crowded than the Uffizi, opens right at 9:30.',
enrich: 'open 09:3019:30 · skip-the-line available' },
{ stop: 'S4', pitch: 'No-frills Florentine kitchen the locals queue for. Expect a wait without a reservation.',
enrich: 'lunch 12:0014:30 · dinner from 19:30 · ~1 h typically' },
{ stop: 'S5', pitch: 'Renaissance gardens behind Pitti — a good pace-break in the heat; ~2 h is the sweet spot.',
enrich: 'open 08:1519:30 · last entry 18:15' },
{ stop: 'S7', pitch: 'The step-up lunch: set tables on the Arno, terrace across from Pitti. Worth holding if Marios queue looks long.',
enrich: 'lunch from 12:30 · book ahead in season' }
]
};