// ----------------------------------------------------------------------------- // Rent-Ka — Rental listings aggregator (Canada, outside Québec) // Author: Simon-Pierre Boucher — contact@spboucher.ai // pages/KaScores.tsx: "How are KA Scores calculated?" // Public methodology (mandatory scale transparency), live coverage of the // inventory, and personal priority settings (the sliders reweight the // global KA Score shown on listing pages). // ----------------------------------------------------------------------------- import { useEffect, useMemo, useState } from "react"; import { KA_DEFAULT_WEIGHTS, KaScoresStats, fetchKaScoresStats, kaWeights, } from "../api"; import { KaScoreCircle } from "../components/KaScoreBadge"; const SCORES: { key: string; nom: string; mesure: string; methode: string }[] = [ { key: "walk", nom: "KA Walk Score", mesure: "Doing everything on foot.", methode: "Estimated walking distance to the nearest of each daily need " + "(grocery, pharmacy, park, café, school, clinic, daycare, convenience " + "store, gym, library), weighted by importance — a grocery store weighs " + "three times more than a gym. Full marks below a per-category " + "threshold (e.g. grocery ≤ 400 m), linear decay afterwards. Small " + "bonus when there is choice (3 grocery stores or cafés within 800 m).", }, { key: "transit", nom: "KA Transit Score", mesure: "Public transit service.", methode: "Two parts: the walking distance to the nearest bus stop or rapid " + "transit station (OpenStreetMap), and the area's transit service level " + "measured by Statistics Canada (2021 proximity measures database, " + "Canadian percentile). An area with no stop within walking distance " + "shows \"Not served\", not a raw 0.", }, { key: "bike", nom: "KA Bike Score", mesure: "Everyday cycling.", methode: "Kilometres of bike lanes (OSM paths and lanes) within 1 km, plus " + "the reachability of daily needs at biking distance. Elevation is not " + "yet taken into account (v1).", }, { key: "calme", nom: "KA Quiet Score", mesure: "The estimated quietness of the area.", methode: "Decaying penalties by distance to mapped noise sources: " + "highways, main arteries, railways, airports and heliports, industrial " + "zones, bar concentrations. Bonus for a park close by. This is an " + "environment-based estimate, NOT a sound measurement.", }, { key: "services", nom: "KA Services Score", mesure: "The overall richness of services.", methode: "Weighted count of points of interest by family — shops (1 km), " + "health (3 km), education (3 km), leisure (1 km) — with diminishing " + "returns: going from 0 to 3 grocery stores counts much more than from " + "12 to 15.", }, ]; const NOMS_COURTS: Record = { walk: "Walk", transit: "Transit", bike: "Bike", calme: "Quiet", services: "Services", }; export default function KaScoresPage() { const [stats, setStats] = useState(null); const [weights, setWeights] = useState>(() => kaWeights()); useEffect(() => { fetchKaScoresStats().then(setStats).catch(() => {}); document.title = "KA Scores — methodology | Rent-Ka"; }, []); const somme = useMemo( () => Object.values(weights).reduce((a, b) => a + b, 0), [weights]); const setW = (k: string, v: number) => { const next = { ...weights, [k]: v }; setWeights(next); try { localStorage.setItem("rentka_ks_weights", JSON.stringify(next)); } catch { /* private */ } }; const reset = () => { setWeights(KA_DEFAULT_WEIGHTS); try { localStorage.removeItem("rentka_ks_weights"); } catch { /* private */ } }; return (
Transparency

How are KA Scores calculated?

Five in-house scores from 0 to 100 rate each rental's location: walking, public transit, biking, quiet and services. Here is exactly how — method, sources and limits.

{stats && (
{stats.couverture_pct.toLocaleString("en-CA")} % of the inventory scored ({stats.avec_score.toLocaleString("en-CA")} listings) {stats.moyennes.global?.moyenne != null && ( average global score {stats.moyennes.global.moyenne} )} scale {stats.version}
)}
{SCORES.map((s) => (

{s.nom}

What it measures: {s.mesure}

{s.methode}

{stats?.moyennes[s.key]?.moyenne != null && (

Inventory average: {stats.moyennes[s.key]!.moyenne} —{" "} {stats.moyennes[s.key]!.n.toLocaleString("en-CA")} buildings rated.

)}
))}

Your priorities, your score

The global KA Score shown everywhere is a weighted average of the five scores. Set here what matters to you — listing pages will show your personalized score next to the standard one. These settings stay on your device.

{Object.keys(KA_DEFAULT_WEIGHTS).map((k) => ( ))}

Sources, honesty and limits

  • Sources: points of interest, roads, rails and bike lanes © OpenStreetMap contributors (ODbL); transit service: Proximity Measures Database, Statistics Canada (2021).
  • Distances: straight-line multiplied by 1.3 (usual network factor) — not exact pedestrian routing.
  • Insufficient data: a poorly mapped area (rural zone) shows "Insufficient data" rather than a misleading score; an area with no public transit shows "Not served".
  • Consistency: scores are computed per building; two rentals in the same building share exactly the same scores.
  • Versioning: the scale is versioned; any method change recomputes the whole inventory and the computation date is shown on every listing page.
); }