Lou-Ka — Rapport de validation : synchronisation liste ↔ carte + KA Scores
Date : 2026-08-18 · Nœud : M3U96b (~/apps/lou-ka) · Prod : www.lou-ka.com
Suite E2E : scripts/test-sync.mjs (Playwright/Chromium) — 25/25 réussis.
Tests API : tests/test_search.py (9/9) · Barème : tests/test_kascores.py (8/8)
· Framework : ka-maps vitest (36/36, dont drawGeo.test.ts).
Architecture livrée
Une seule vérité partagée : `filtres + zone (bbox visible ou polygone) + tri
- page
→ **une requête**/api/search` → une réponse contenant la page de liste ET tous les points carte, triés pareil. Le compteur de liste est par construction égal au nombre de marqueurs ; l'index d'un point donne sa page.
Critères d'acceptation
| # | Critère | Verdict | Preuve |
|---|---|---|---|
| 1 | Compteur liste = points carte (filtres seuls, carte seule, combinés, polygone) | ✅ structurel | E2E : 44 744=44 744 · 2 902=2 902 (≤900 $) · 369=369 (polygone) · 0=0 (zone vide) ; test_search.py |
| 2 | Filtre → carte < 300 ms perçues ; carte → liste en fin de geste | ✅ | API 82-98 ms (bbox/polygone), 364 ms province entière (45 k points, une fois puis cache client) ; debounce 280 ms fin de geste |
| 3 | Survol miroir < 100 ms, deux sens | ✅ | feature-state GPU sans re-rendu ; E2E vérifie l'état à 90 ms dans les deux sens |
| 4 | Clic marqueur → liste défile (page ajustée au besoin) ; clic annonce → recentrage + mini-fiche | ✅ | E2E « visible » + mini-fiche ; l'index des points garantit le « toujours » |
| 5 | Aucune requête périmée n'écrase une récente | ✅ | numéro de séquence + AbortController ; E2E rafale de 4 drags rapides |
| 6 | 2 000+ résultats fluides, mobile compris | ✅* | 45 k points en clustering natif Mapbox GL (aucun marqueur DOM), liste paginée (20/page), images lazy ; *fps non instrumenté en headless — architecture 60 fps (couches GPU) |
| 7 | URL partagée = recherche reproduite (filtres+zone+tri) | ✅ | E2E : caméra+tri+zone+move restaurés, 236 résultats identiques |
| 8 | Bascule mobile sans perte + carrousel synchronisé 2 sens | ✅ | E2E : marqueur→carrousel et carrousel→marqueur, URL stable à la bascule |
| 9 | États vides & dégradés propres | ✅ | « Aucun logement dans cette zone » + Élargir la zone ; +N sans position affiché honnêtement |
| 10 | Rapport + captures | ✅ | ce fichier + 11 captures dans ce dossier |
Captures
01 carte desktop (compteur partagé + « sans position ») · 02 sélection miroir (mini-fiche + carte surlignée) · 03 filtre+tri partagé · 04 polygone dessiné (puce retirable, 369=369) · 05 zéro résultat · 06 URL partagée · 07 carrousel mobile synchronisé · 08 bascule mobile · 09 géolocalisation d'accueil · 10 fiche KA Scores · 11 page méthodologie /ka-scores.
Fonctionnalités au-delà des critères
- Géolocalisation d'accueil : à l'arrivée (URL nue, 1×/session), demande de position → vue carte centrée sur l'utilisateur (garde-fou hors-Québec, refus silencieux, liens partagés respectés) + bouton « Me localiser ».
- Respect de l'intention :
moveend.byUser(framework) distingue geste et mouvement programmé — recadrage auto seulement si l'utilisateur n'a pas la main, sinon « Recadrer sur les résultats ». - Marqueurs « déjà vus » atténués, fourchette de prix des clusters au survol, écartement discret des unités d'un même immeuble (toutes cliquables à z max).
KA Scores (v1, barème 2026.08-v1)
- 5 scores 0-100 par immeuble + global pondéré (pondérations personnalisables côté client, /ka-scores). Sources : OSM (Overpass par tuiles, cache 3 mois, table env_tiles) + percentile transport PMD StatCan 2021 (quartier.db).
- Honnêteté : « Données insuffisantes » / « Non desservi » au lieu de 0 ; détail par score sur la fiche ; distances vol d'oiseau ×1,3 documentées ; date + version affichées ; méthodologie publique.
- Perf : ~7 900 immeubles calculés en 8 s (incrémental) ; distribution (déciles global, zone urbaine) : 18 · 53 · 63 · 69 · 74 · 78 · 81 · 84 · 87 · 90 · 98.
- Intégration : pastille sur les cartes d'annonces, section fiche, tri « Meilleur KA Score », filtre « KA Score minimal », /api/kascores/stats, recalcul incrémental à chaque cycle de sync (watch).
- Couverture finale (2026-08-19) : 85/86 tuiles OSM (1 tuile rurale refusée par Overpass après 10 reprises — la boucle watch la complétera), 42 845 annonces scorées sur 45 258 (94,7 %), 21 748 immeubles. Moyennes du parc : walk 67,1 · transit 75,7 · bike 88,2 · calme 68,9 · services 86,0 · global 74,7. Déciles global : 17 · 51 · 62 · 69 · 74 · 79 · 82 · 85 · 88 · 91 · 98. Test de non-aberration spatiale : réussi sur le parc complet. (Recalibrage v2 envisagé : le Bike sature vite en ville.)
Restes à faire (documentés, non bloquants)
- Fréquences GTFS réelles (v1 : proximité des arrêts × PMD) ; dénivelé du Bike Score ; numérotation optionnelle des marqueurs selon le tri ; précédent/suivant navigateur sur les filtres (l'URL est complète, la restauration ne réagit pas encore à popstate) ; « Mon point » / isochrones / heatmap des loyers / alertes par polygone (PARTIES 2-5 du chantier KA géographique) ; recalibrage du barème une fois le parc complet scoré.