fix(tours): search along a tour through the places index along the line, and name what could not be searched (PLN-02, CW-05)

The search along a tour found nothing. It asked the places index for all
kinds of a stretch at once, above the 100 rows and 200 characters of terms
the index takes, so the index refused and every stretch went to the public
Overpass mirrors, which do not answer from this server. Now the index is
asked in small circles strung along the line, one request per kind and
circle within its limits, and an empty circle counts as an answer, so a
city walk lists its sights, museums, parks, cafes, restaurants and markets
in well under a second. The kinds the index does not know (viewpoints,
huts, drinking water, toilets and the like) are asked of Overpass along the
whole line at the same time, one query per stretch of up to 50 km, three at
a time, each with a short deadline of its own; a line past 400 km is
searched along its start and says so. When the index answers no circle at
all, its kinds go to Overpass beside the others instead of after them. A
kind no source could be searched for is named in a calm notice above the
list instead of reporting nothing found, and the reason is written to the
log. Unnamed taps, toilets, shelters, picnic spots, viewpoints, summits,
slipways and repair stands stay in the list and on the map under the name
of their kind; an unnamed garden, cafe or memorial is left out. The places
nearest the line are kept when there are more than sixty, listed from the
start, with the opening hours the source has.

A walk's parks are parks and gardens only, and its museums are museums
and galleries only, no longer the beaches, summits, theatres and cinemas of
the map's explore buttons; a water park the index files under parks is not
one of them. The index also answers markets and summits. The explore
buttons keep their single request, and a search of several kinds that
would exceed the index limits is asked one kind at a time instead of being
refused. The MCP tool search_tour_pois and its wiki row describe the walk
kinds and the new unavailable list, and the OVERPASS_TIMEOUT_MS row says
the search along a tour keeps its own shorter deadline.
This commit is contained in:
Maurice
2026-10-19 22:34:10 +00:00
parent 9ed944c1e6
commit 3c823e07f4
55 changed files with 1841 additions and 236 deletions
+1
View File
@@ -330,6 +330,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'لم ينجح البحث. حاول مرة أخرى بعد قليل.',
'tours.poi.outdated': 'وُجدت للمسار كما كان سابقًا. ابحث مرة أخرى لتطابق المسار الحالي.',
'tours.poi.partial': 'تعذّر البحث في بعض المقاطع، وقد تكون هناك أماكن مفقودة.',
'tours.poi.unavailable': 'تعذّر البحث عن هذه الآن: {kinds}. حاول مرة أخرى بعد قليل.',
'tours.poi.capped': 'الجولة طويلة: تم البحث في جزئها الأول فقط.',
'tours.poi.truncated': 'هناك أماكن أكثر مما يظهر. قلّل المسافة أو الأنواع.',
'tours.poi.empty': 'لم يُعثر على شيء ضمن {distance} من المسار.',
+1
View File
@@ -319,6 +319,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Axtarış alınmadı. Bir azdan yenidən cəhd et.',
'tours.poi.outdated': 'Marşrutun əvvəlki halı üçün tapılıb. İndikinə uyğun olması üçün yenidən axtar.',
'tours.poi.partial': 'Bəzi hissələrdə axtarış aparılmadı; orada yerlər çatışmaya bilər.',
'tours.poi.unavailable': 'Bunlar hazırda axtarıla bilmədi: {kinds}. Bir azdan yenidən cəhd et.',
'tours.poi.capped': 'Tur uzundur: yalnız ilk hissəsində axtarış aparıldı.',
'tours.poi.truncated': 'Göstəriləndən çox yer var. Məsafəni və ya növləri azalt.',
'tours.poi.empty': 'Marşrutdan {distance} məsafədə heç nə tapılmadı.',
+1
View File
@@ -324,6 +324,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'A busca não funcionou. Tente novamente em instantes.',
'tours.poi.outdated': 'Encontrado para a rota como era antes. Busque novamente para combinar com a atual.',
'tours.poi.partial': 'Alguns trechos não puderam ser buscados; podem faltar lugares neles.',
'tours.poi.unavailable': 'Não foi possível buscar agora: {kinds}. Tente novamente em instantes.',
'tours.poi.capped': 'O passeio é longo: só a primeira parte foi buscada.',
'tours.poi.truncated': 'Há mais lugares do que os mostrados. Reduza a distância ou os tipos.',
'tours.poi.empty': 'Nada encontrado a até {distance} da rota.',
+1
View File
@@ -325,6 +325,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': "La cerca no ha funcionat. Torna-ho a provar d'aquí a una estona.",
'tours.poi.outdated': "Trobat per a la ruta tal com era abans. Torna a cercar perquè encaixi amb l'actual.",
'tours.poi.partial': "No s'han pogut cercar alguns trams; hi poden faltar llocs.",
'tours.poi.unavailable': "Ara no s'ha pogut cercar: {kinds}. Torna-ho a provar d'aquí a una estona.",
'tours.poi.capped': "La ruta és llarga: només se n'ha cercat la primera part.",
'tours.poi.truncated': 'Hi ha més llocs dels que es mostren. Redueix la distància o els tipus.',
'tours.poi.empty': "No s'ha trobat res a menys de {distance} de la ruta.",
+1
View File
@@ -319,6 +319,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Hledání se nepovedlo. Zkus to za chvíli znovu.',
'tours.poi.outdated': 'Nalezeno pro trasu v dřívější podobě. Hledej znovu, aby to odpovídalo té současné.',
'tours.poi.partial': 'Některé úseky se nepodařilo prohledat; místa tam mohou chybět.',
'tours.poi.unavailable': 'Teď se nepodařilo prohledat: {kinds}. Zkus to za chvíli znovu.',
'tours.poi.capped': 'Túra je dlouhá: prohledána byla jen její první část.',
'tours.poi.truncated': 'Míst je víc, než se zobrazuje. Zmenši vzdálenost nebo druhy.',
'tours.poi.empty': 'Do {distance} od trasy nic nenalezeno.',
+1
View File
@@ -328,6 +328,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Die Suche hat nicht geklappt. Versuch es gleich noch einmal.',
'tours.poi.outdated': 'Gefunden für die Route, wie sie vorher war. Suche erneut, damit es zur jetzigen passt.',
'tours.poi.partial': 'Einige Abschnitte ließen sich nicht durchsuchen; dort können Orte fehlen.',
'tours.poi.unavailable': 'Gerade nicht durchsuchbar: {kinds}. Versuch es gleich noch einmal.',
'tours.poi.capped': 'Die Tour ist lang: Nur ihr erster Teil wurde durchsucht.',
'tours.poi.truncated': 'Es gibt mehr Orte als angezeigt. Verkleinere den Abstand oder wähle weniger Arten.',
'tours.poi.empty': 'Nichts gefunden im Abstand von {distance} zur Route.',
+1
View File
@@ -318,6 +318,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'The search did not work. Try again in a moment.',
'tours.poi.outdated': 'Found for the route as it was before. Search again to match it now.',
'tours.poi.partial': 'Some stretches could not be searched; places there may be missing.',
'tours.poi.unavailable': 'Could not be searched right now: {kinds}. Try again in a moment.',
'tours.poi.capped': 'The tour is long: only its first part was searched.',
'tours.poi.truncated': 'There are more places than shown. Narrow the distance or the kinds.',
'tours.poi.empty': 'Nothing found within {distance} of the route.',
+1
View File
@@ -324,6 +324,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'La búsqueda no funcionó. Inténtalo de nuevo en un momento.',
'tours.poi.outdated': 'Encontrado para la ruta tal como era antes. Busca de nuevo para que coincida con la actual.',
'tours.poi.partial': 'Algunos tramos no se pudieron buscar; pueden faltar lugares allí.',
'tours.poi.unavailable': 'No se ha podido buscar ahora: {kinds}. Inténtalo de nuevo en un momento.',
'tours.poi.capped': 'La ruta es larga: solo se buscó su primera parte.',
'tours.poi.truncated': 'Hay más lugares de los que se muestran. Reduce la distancia o los tipos.',
'tours.poi.empty': 'No se encontró nada a menos de {distance} de la ruta.',
+1
View File
@@ -321,6 +321,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Otsing ei õnnestunud. Proovi kohe uuesti.',
'tours.poi.outdated': 'Leitud marsruudi varasema kuju jaoks. Otsi uuesti, et see sobiks praegusega.',
'tours.poi.partial': 'Mõnda lõiku ei saanud läbi otsida; sealt võivad kohad puududa.',
'tours.poi.unavailable': 'Praegu ei saanud otsida: {kinds}. Proovi kohe uuesti.',
'tours.poi.capped': 'Matk on pikk: läbi otsiti ainult selle esimene osa.',
'tours.poi.truncated': 'Kohti on rohkem, kui näidatakse. Vähenda kaugust või liike.',
'tours.poi.empty': 'Marsruudist {distance} kaugusel ei leitud midagi.',
+1
View File
@@ -331,6 +331,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': "La recherche n'a pas abouti. Réessaie dans un instant.",
'tours.poi.outdated': "Trouvé pour l'itinéraire tel qu'il était avant. Cherche à nouveau pour l'actuel.",
'tours.poi.partial': "Certains tronçons n'ont pas pu être cherchés ; des lieux peuvent y manquer.",
'tours.poi.unavailable': 'Recherche impossible pour le moment : {kinds}. Réessaie dans un instant.',
'tours.poi.capped': "L'itinéraire est long : seule sa première partie a été cherchée.",
'tours.poi.truncated': "Il y a plus de lieux qu'affichés. Réduis la distance ou les types.",
'tours.poi.empty': "Rien trouvé à moins de {distance} de l'itinéraire.",
+1
View File
@@ -331,6 +331,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Η αναζήτηση δεν πέτυχε. Δοκίμασε ξανά σε λίγο.',
'tours.poi.outdated': 'Βρέθηκαν για τη διαδρομή όπως ήταν πριν. Αναζήτησε ξανά για την τωρινή.',
'tours.poi.partial': 'Ορισμένα τμήματα δεν αναζητήθηκαν· μπορεί να λείπουν μέρη εκεί.',
'tours.poi.unavailable': 'Δεν ήταν δυνατή η αναζήτηση τώρα: {kinds}. Δοκίμασε ξανά σε λίγο.',
'tours.poi.capped': 'Η διαδρομή είναι μεγάλη: αναζητήθηκε μόνο το πρώτο της μέρος.',
'tours.poi.truncated': 'Υπάρχουν περισσότερα μέρη από όσα εμφανίζονται. Μείωσε την απόσταση ή τα είδη.',
'tours.poi.empty': 'Δεν βρέθηκε τίποτα σε απόσταση {distance} από τη διαδρομή.',
+1
View File
@@ -326,6 +326,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'A keresés nem sikerült. Próbáld újra egy kicsit később.',
'tours.poi.outdated': 'Az útvonal korábbi állapotához találva. Keress újra, hogy a mostanihoz illjen.',
'tours.poi.partial': 'Néhány szakaszt nem sikerült átkeresni; ott helyek hiányozhatnak.',
'tours.poi.unavailable': 'Ezeket most nem lehetett keresni: {kinds}. Próbáld újra egy kicsit később.',
'tours.poi.capped': 'A túra hosszú: csak az első részét kerestük át.',
'tours.poi.truncated': 'Több hely van, mint amennyi látszik. Szűkítsd a távolságot vagy a fajtákat.',
'tours.poi.empty': 'Az útvonaltól {distance} távolságon belül nincs találat.',
+1
View File
@@ -318,6 +318,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Pencarian gagal. Coba lagi sebentar lagi.',
'tours.poi.outdated': 'Ditemukan untuk rute seperti sebelumnya. Cari lagi agar cocok dengan yang sekarang.',
'tours.poi.partial': 'Beberapa ruas tidak dapat dicari; tempat di sana mungkin terlewat.',
'tours.poi.unavailable': 'Saat ini tidak dapat dicari: {kinds}. Coba lagi sebentar lagi.',
'tours.poi.capped': 'Turnya panjang: hanya bagian pertamanya yang dicari.',
'tours.poi.truncated': 'Ada lebih banyak tempat daripada yang ditampilkan. Persempit jarak atau jenisnya.',
'tours.poi.empty': 'Tidak ada yang ditemukan dalam {distance} dari rute.',
+1
View File
@@ -326,6 +326,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'La ricerca non è riuscita. Riprova tra un momento.',
'tours.poi.outdated': "Trovato per il percorso com'era prima. Cerca di nuovo per quello attuale.",
'tours.poi.partial': 'Alcuni tratti non sono stati cercati; lì potrebbero mancare dei luoghi.',
'tours.poi.unavailable': 'Al momento non è stato possibile cercare: {kinds}. Riprova tra un momento.',
'tours.poi.capped': 'Il percorso è lungo: è stata cercata solo la prima parte.',
'tours.poi.truncated': 'Ci sono più luoghi di quelli mostrati. Riduci la distanza o i tipi.',
'tours.poi.empty': 'Nulla trovato entro {distance} dal percorso.',
+1
View File
@@ -312,6 +312,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': '検索できませんでした。少ししてからもう一度お試しください。',
'tours.poi.outdated': '以前のルートで見つかった結果です。現在のルートに合わせるにはもう一度検索してください。',
'tours.poi.partial': '一部の区間は検索できませんでした。その区間の場所が欠けている可能性があります。',
'tours.poi.unavailable': '現在は検索できませんでした:{kinds}。少ししてからもう一度お試しください。',
'tours.poi.capped': 'ツアーが長いため、最初の部分だけを検索しました。',
'tours.poi.truncated': '表示されている以上の場所があります。距離か種類を絞り込んでください。',
'tours.poi.empty': 'ルートから {distance} 以内には見つかりませんでした。',
+1
View File
@@ -310,6 +310,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': '검색하지 못했습니다. 잠시 후 다시 시도하세요.',
'tours.poi.outdated': '이전 경로 기준의 결과입니다. 지금 경로에 맞추려면 다시 검색하세요.',
'tours.poi.partial': '일부 구간은 검색하지 못했습니다. 그 구간의 장소가 빠졌을 수 있습니다.',
'tours.poi.unavailable': '지금은 검색할 수 없었습니다: {kinds}. 잠시 후 다시 시도하세요.',
'tours.poi.capped': '투어가 길어서 앞부분만 검색했습니다.',
'tours.poi.truncated': '표시된 것보다 장소가 더 많습니다. 거리나 종류를 줄이세요.',
'tours.poi.empty': '경로에서 {distance} 이내에 찾은 것이 없습니다.',
+1
View File
@@ -327,6 +327,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Het zoeken lukte niet. Probeer het zo opnieuw.',
'tours.poi.outdated': 'Gevonden voor de route zoals die eerst was. Zoek opnieuw voor de huidige.',
'tours.poi.partial': 'Sommige stukken konden niet worden doorzocht; daar kunnen plekken ontbreken.',
'tours.poi.unavailable': 'Kon nu niet worden doorzocht: {kinds}. Probeer het zo opnieuw.',
'tours.poi.capped': 'De tocht is lang: alleen het eerste deel is doorzocht.',
'tours.poi.truncated': 'Er zijn meer plekken dan getoond. Verklein de afstand of de soorten.',
'tours.poi.empty': 'Niets gevonden binnen {distance} van de route.',
+1
View File
@@ -333,6 +333,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Wyszukiwanie się nie powiodło. Spróbuj ponownie za chwilę.',
'tours.poi.outdated': 'Znalezione dla trasy w poprzedniej postaci. Wyszukaj ponownie dla obecnej.',
'tours.poi.partial': 'Niektórych odcinków nie udało się przeszukać; może tam brakować miejsc.',
'tours.poi.unavailable': 'Nie udało się teraz wyszukać: {kinds}. Spróbuj ponownie za chwilę.',
'tours.poi.capped': 'Trasa jest długa: przeszukano tylko jej pierwszą część.',
'tours.poi.truncated': 'Miejsc jest więcej, niż pokazano. Zmniejsz odległość lub liczbę rodzajów.',
'tours.poi.empty': 'Nic nie znaleziono w odległości {distance} od trasy.',
+1
View File
@@ -337,6 +337,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Поиск не удался. Попробуйте ещё раз чуть позже.',
'tours.poi.outdated': 'Найдено для прежнего варианта маршрута. Чтобы учесть текущий, найдите снова.',
'tours.poi.partial': 'Некоторые участки не удалось проверить; там могут отсутствовать места.',
'tours.poi.unavailable': 'Сейчас не удалось выполнить поиск: {kinds}. Попробуйте ещё раз чуть позже.',
'tours.poi.capped': 'Маршрут длинный: проверена только его первая часть.',
'tours.poi.truncated': 'Мест больше, чем показано. Уменьшите расстояние или число видов.',
'tours.poi.empty': 'В пределах {distance} от маршрута ничего не найдено.',
+1
View File
@@ -320,6 +320,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Hľadanie sa nepodarilo. Skús to o chvíľu znova.',
'tours.poi.outdated': 'Nájdené pre trasu v predchádzajúcej podobe. Hľadaj znova pre súčasnú.',
'tours.poi.partial': 'Niektoré úseky sa nepodarilo prehľadať; miesta tam môžu chýbať.',
'tours.poi.unavailable': 'Teraz sa nepodarilo prehľadať: {kinds}. Skús to o chvíľu znova.',
'tours.poi.capped': 'Túra je dlhá: prehľadaná bola len jej prvá časť.',
'tours.poi.truncated': 'Miest je viac, než sa zobrazuje. Zmenši vzdialenosť alebo druhy.',
'tours.poi.empty': 'Do {distance} od trasy sa nič nenašlo.',
+1
View File
@@ -317,6 +317,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Sökningen fungerade inte. Försök igen om en stund.',
'tours.poi.outdated': 'Hittat för rutten som den var tidigare. Sök igen för den nuvarande.',
'tours.poi.partial': 'Vissa sträckor kunde inte genomsökas; platser där kan saknas.',
'tours.poi.unavailable': 'Gick inte att söka efter just nu: {kinds}. Försök igen om en stund.',
'tours.poi.capped': 'Turen är lång: bara den första delen genomsöktes.',
'tours.poi.truncated': 'Det finns fler platser än som visas. Minska avståndet eller slagen.',
'tours.poi.empty': 'Inget hittades inom {distance} från rutten.',
+1
View File
@@ -305,6 +305,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'ค้นหาไม่สำเร็จ ลองอีกครั้งในอีกสักครู่',
'tours.poi.outdated': 'ผลนี้ได้จากเส้นทางแบบเดิม ค้นหาอีกครั้งให้ตรงกับเส้นทางปัจจุบัน',
'tours.poi.partial': 'ค้นหาบางช่วงไม่ได้ อาจมีสถานที่ในช่วงนั้นหายไป',
'tours.poi.unavailable': 'ค้นหาตอนนี้ไม่ได้: {kinds} ลองอีกครั้งในอีกสักครู่',
'tours.poi.capped': 'ทัวร์ยาว ค้นหาได้เฉพาะช่วงแรก',
'tours.poi.truncated': 'มีสถานที่มากกว่าที่แสดง ลดระยะหรือประเภทลง',
'tours.poi.empty': 'ไม่พบสิ่งใดภายใน {distance} จากเส้นทาง',
+1 -1
View File
@@ -20,7 +20,7 @@ const tokens = (value: string) => [...value.matchAll(/\{[^{}]+\}/g)].map((match)
// placeholder spec; here only the general keys are.
const groups = pluralGroups(Object.keys(english));
const generalKeys = (keys: string[]) => keys.filter((key) => !pluralFormOf(key, groups));
const GENERAL_KEY_COUNT = 766;
const GENERAL_KEY_COUNT = 767;
function literalKeys(source: string): string[] {
const tree = ts.createSourceFile('locale.ts', source, ts.ScriptTarget.Latest, true);
+1
View File
@@ -319,6 +319,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Arama olmadı. Birazdan tekrar dene.',
'tours.poi.outdated': 'Rotanın önceki hâli için bulundu. Şimdikine uyması için yeniden ara.',
'tours.poi.partial': 'Bazı kısımlarda arama yapılamadı; orada yerler eksik olabilir.',
'tours.poi.unavailable': 'Şu anda aranamadı: {kinds}. Birazdan tekrar dene.',
'tours.poi.capped': 'Tur uzun: yalnızca ilk kısmında arama yapıldı.',
'tours.poi.truncated': 'Gösterilenden fazla yer var. Mesafeyi veya türleri daralt.',
'tours.poi.empty': 'Rotaya {distance} mesafe içinde bir şey bulunamadı.',
+1
View File
@@ -332,6 +332,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Пошук не вдався. Спробуйте ще раз трохи згодом.',
'tours.poi.outdated': 'Знайдено для попереднього варіанта маршруту. Щоб урахувати поточний, шукайте знову.',
'tours.poi.partial': 'Деякі ділянки не вдалося перевірити; там можуть бракувати місць.',
'tours.poi.unavailable': 'Зараз не вдалося виконати пошук: {kinds}. Спробуйте ще раз трохи згодом.',
'tours.poi.capped': 'Маршрут довгий: перевірено лише його першу частину.',
'tours.poi.truncated': 'Місць більше, ніж показано. Зменште відстань або кількість видів.',
'tours.poi.empty': 'У межах {distance} від маршруту нічого не знайдено.',
+1
View File
@@ -319,6 +319,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': 'Tìm kiếm không thành công. Hãy thử lại sau giây lát.',
'tours.poi.outdated': 'Kết quả cho lộ trình trước đó. Hãy tìm lại để khớp với lộ trình hiện tại.',
'tours.poi.partial': 'Một số đoạn không tìm được; có thể thiếu địa điểm ở đó.',
'tours.poi.unavailable': 'Hiện không thể tìm: {kinds}. Hãy thử lại sau giây lát.',
'tours.poi.capped': 'Chuyến đi dài: chỉ phần đầu được tìm.',
'tours.poi.truncated': 'Có nhiều địa điểm hơn số hiển thị. Hãy thu hẹp khoảng cách hoặc loại.',
'tours.poi.empty': 'Không tìm thấy gì trong khoảng {distance} tới lộ trình.',
+1
View File
@@ -295,6 +295,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': '搜尋未成功。請稍後再試。',
'tours.poi.outdated': '這是依先前的路線找到的。請重新搜尋以符合目前路線。',
'tours.poi.partial': '有些路段無法搜尋,那裡可能缺少地點。',
'tours.poi.unavailable': '暫時無法搜尋:{kinds}。請稍後再試。',
'tours.poi.capped': '路線較長:只搜尋了前一段。',
'tours.poi.truncated': '地點比顯示的更多。請縮小範圍或類型。',
'tours.poi.empty': '距路線 {distance} 內沒有找到任何地點。',
+1
View File
@@ -296,6 +296,7 @@ const tours: TranslationStrings = {
'tours.poi.failed': '搜索未成功。请稍后再试。',
'tours.poi.outdated': '这是按之前的路线找到的。请重新搜索以匹配当前路线。',
'tours.poi.partial': '有些路段无法搜索,那里可能缺少地点。',
'tours.poi.unavailable': '暂时无法搜索:{kinds}。请稍后再试。',
'tours.poi.capped': '路线较长:只搜索了前一段。',
'tours.poi.truncated': '地点比显示的更多。请缩小范围或类型。',
'tours.poi.empty': '距路线 {distance} 内没有找到任何地点。',
@@ -63,8 +63,18 @@ describe('tour POI search contracts (PLN-02)', () => {
truncated: false,
partial: true,
capped: false,
unavailable: [],
});
expect(answer.partial).toBe(true);
expect(answer.pois[0]?.distance_m).toBe(40);
});
it('names the kinds that could not be searched, each a known category, and always says so', () => {
const answer = { pois: [], truncated: false, partial: false, capped: false };
expect(tourPoiSearchResponseSchema.parse({ ...answer, unavailable: ['viewpoint'] }).unavailable).toEqual([
'viewpoint',
]);
expect(tourPoiSearchResponseSchema.safeParse({ ...answer, unavailable: ['fuel'] }).success).toBe(false);
expect(tourPoiSearchResponseSchema.safeParse(answer).success).toBe(false);
});
});
+3 -1
View File
@@ -55,7 +55,7 @@ export const WALK_THEME_KEYS = Object.keys(WALK_THEMES) as WalkTheme[];
/** How far from the line a place may lie, the choices offered, in metres. */
export const TOUR_POI_CORRIDORS_M = [250, 500, 1000, 2000] as const;
/** The most places one answer carries, nearest the start first. */
/** The most places one answer carries: the nearest to the line, listed from the start. */
export const TOUR_POI_LIMIT = 60;
/** The most points the line sent may have; a longer line is thinned first. */
export const TOUR_POI_MAX_LINE_POINTS = 1000;
@@ -108,5 +108,7 @@ export const tourPoiSearchResponseSchema = z.object({
partial: z.boolean(),
/** The line was longer than one search covers; only its first part was searched. */
capped: z.boolean(),
/** Kinds no source could be asked for right now; their places are missing, not absent. */
unavailable: z.array(tourPoiCategorySchema),
});
export type TourPoiSearchResponse = z.infer<typeof tourPoiSearchResponseSchema>;