Add check-in feature and update travel planner UI

This commit is contained in:
周瑞哲
2026-07-31 12:50:14 +08:00
parent ac4179086c
commit 3ef7266591
44 changed files with 2919 additions and 144 deletions
+41 -4
View File
@@ -228,6 +228,31 @@ function rankedCandidates(
})
}
function canCompleteMinimumRoute(
candidates: readonly PoiResolved[],
preferences: TravelPreferences,
cursor: PlanningOrigin | PoiResolved | null,
remainingMinutes: number,
stopsNeeded: number,
): boolean {
if (stopsNeeded <= 0)
return true
return candidates.some((poi, index) => {
const requiredMinutes = (cursor ? transferMinutes(cursor, poi, preferences) : 0)
+ activityMinutes(poi, preferences.pace)
if (requiredMinutes > remainingMinutes)
return false
return canCompleteMinimumRoute(
[...candidates.slice(0, index), ...candidates.slice(index + 1)],
preferences,
poi,
remainingMinutes - requiredMinutes,
stopsNeeded - 1,
)
})
}
function selectQuickPois(
preferences: TravelPreferences,
repository: PoiRepository,
@@ -238,13 +263,28 @@ function selectQuickPois(
const selected: PoiResolved[] = []
let usedMinutes = 0
let cursor: PlanningOrigin | PoiResolved | null = origin
const minimumTargetCount = Math.min(remaining.length, requestedMinutes >= 240 ? 3 : 1)
while (remaining.length > 0 && selected.length < 8) {
const ranked = rankedCandidates(remaining, preferences, selected, cursor)
const next = ranked.find((poi) => {
const fitting = ranked.filter((poi) => {
const transfer = cursor ? transferMinutes(cursor, poi, preferences) : 0
return usedMinutes + transfer + activityMinutes(poi, preferences.pace) <= requestedMinutes
})
const next = fitting.find((poi) => {
const transfer = cursor ? transferMinutes(cursor, poi, preferences) : 0
const requiredMinutes = transfer + activityMinutes(poi, preferences.pace)
const stopsNeeded = minimumTargetCount - selected.length - 1
if (stopsNeeded <= 0)
return true
return canCompleteMinimumRoute(
remaining.filter(candidate => candidate.id !== poi.id),
preferences,
poi,
requestedMinutes - usedMinutes - requiredMinutes,
stopsNeeded,
)
}) ?? fitting[0]
if (!next)
break
const transfer = cursor ? transferMinutes(cursor, next, preferences) : 0
@@ -254,9 +294,6 @@ function selectQuickPois(
cursor = next
}
if (selected.length === 0 && remaining.length > 0)
selected.push(rankedCandidates(remaining, preferences, [], origin)[0])
return selected
}