# Scoring i Stedsvalgs Oslo- og Bærum-modeller

Modellen er deterministisk: samme svar gir alltid samme rangering. Ingen tekstmodell eller tilfeldig komponent brukes.

## 1. Krav

Før scoring tas kandidater ut dersom de bryter det eksplisitte reisekravet:

- Primær eller sekundær reisetid over brukerens oppgitte maksimum. Per kollektivreisemål kan brukeren i tillegg sette et maksimalt antall bytter og maksimal gangtid (`maxTransfers`, `maxWalkMinutes`, uten grense som standard). Disse sjekkes bare mot Enturs faktiske reiseforslag; et estimat kan aldri ta ut et område på en grense det ikke kan måle. Områder som bryter grensen tas ut, og resultatsiden sier hvilken grense det var og lar brukeren fjerne den. Maksimum er alltid en reell grense, ikke en preferanse - et reisemål over grensen tas ut av kortlisten. Begge reisemål starter på 45 minutter.

Et oppgitt boligbudsjett er en reell grense for boligen brukeren kan velge, men områdeestimatet har ikke listingpresisjon og brukes derfor ikke som et hardt geografisk filter. Estimatet vises som «Typisk innenfor budsjett» når det er på eller under budsjettet, «Mulig, men typisk dyrere» når kjøpsestimatet er inntil 15 % over (25 % for leie), og «Lite realistisk på oppgitt størrelse» over denne marginen. Dette er transparente sammenligningsmarginer, ikke statistiske konfidensintervaller. Ingen områder elimineres av et aggregert prisestimat; lite realistiske estimater grupperes etter mer plausible områder i resultatlisten. Leiemarginen er bredere fordi BOL014 bare skiller fem byområder. Budsjettet påvirker ingenting hvis boligbehovet er slått av, eller slått på uten et utfylt budsjettbeløp. Områdetallene dokumenterer typisk prisnivå, men ikke om en konkret bolig er tilgjengelig til den prisen.

Kollektivtilbud og ro har ingen egen av/på-bryter for eliminering. De påvirker rangeringen utelukkende gjennom vekten brukeren gir dem i preferansene (avsnitt 2) – å sette en av dem til «Svært viktig» øker innflytelsen i det vektede gjennomsnittet, men garanterer ikke at svake områder sorteres bort slik et eksplisitt krav gjør.

## 2. Preferanser

De seksten aktive områdemetrikkene ligger på en nominell skala fra 0 til 100 og er alle avledet fra offentlig kart-, reise-, kartleggings- og spørreundersøkelsesdata (ro, store naturområder, grønt i hverdagen, nærhet til fjorden, innsjø og elv, barn i hverdagen, behagelig å gå, behagelig å sykle, bebyggelsesform, restauranter/kafeer, kollektivtilbud, hverdagstilbud, boligprisgunstighet, opplevd trygghet, bebyggelsens alder og investeringspotensial). Kalibrerte maksimumsverdier stopper ved 98 fordi kildene ikke kan dokumentere et perfekt område. Grensesnittet viser målene som «av 100», som resultatsiden gjør for samlepoengene; at skalaen i praksis stopper på 98 forklares på metodesiden. «Nærhet til hverdagen» er tatt ut av scoringen fordi det kombinerte de samme serverings- og hverdagspunktene som allerede inngår i to andre mål. Verdien beholdes foreløpig i rådataene, men kan ikke påvirke rangeringen. Fjorten av de seksten metrikkene er ensrettede («hvor viktig er mer X»). Brukerens fem valg mappes til vektene:

| Valg | Vekt |
|---|---:|
| Ikke viktig | 0 |
| Litt viktig | 0,5 |
| Middels viktig | 1,0 |
| Viktig | 1,5 |
| Svært viktig | 2,0 |

Vektene er monotone og beskriver relativ betydning. Et urørt skjema starter på «Ikke viktig» (vekt 0) for alle ni ensrettede metrikkene, ikke «Nøytral» - en metrikk ingen har rørt bidrar dermed ingenting til scoren, i stedet for en antatt gjennomsnittlig interesse. «Ikke viktig» er derfor det eneste valget som tar en kategori helt ut av beregningen, og det er nettopp den uttrykte betydningen av dette valget, ikke manglende data. «Middels viktig» er det valget som gir samme innflytelse som den gamle «Nøytral»-vekten gjorde, for den som aktivt ønsker det. Den niende metrikken, bebyggelsens alder, er bipolar og bruker samme vekttabell på tallverdien, men fortegnet er en retning, ikke en styrke - se avsnitt 10.

Vekttabellen over gir den *uttrykte* betydningen, men ikke nødvendigvis den samme *gjennomslagskraften* i rangeringen for alle seksten metrikker - noen områdemål varierer over nesten hele 0-98-skalaen på tvers av de 321 rutene (mat, kollektiv, hverdagstilbud, fjord, bebyggelsens alder), mens andre i praksis bare bruker en smal del av skalaen fordi Oslo selv ikke varierer mye på akkurat det målet. Trygghet er det tydeligste eksempelet: alle 321 ruter ligger reelt sett mellom ca. 66 og 91 poeng, fordi Oslos delbydeler rapporterer gjennomgående høy opplevd trygghet i Folkehelseundersøkelsen - ikke fordi modellen undervurderer forskjeller. Uten justering ville «svært viktig» trygghet dermed aldri kunne veie opp for et sterkt reisemål på samme måte som «svært viktig» mat eller kollektiv kan, selv om brukeren uttrykker like sterk prioritet. Dette er et kjent problem i flerkriterieanalyse («swing weighting», Edwards & Barron 1994): en vekt betyr først det samme på tvers av kriterier når den er kalibrert mot hvor mye kriteriet faktisk kan svinge mellom byens svakeste og sterkeste rute - ikke bare mot et abstrakt vekttall på en skala kriteriet ikke fyller.

Derfor multipliseres tabellvekten over med en per-metrikk svingfaktor (`metricSwingFactorsFor(region)` i `js/scoring.js`), beregnet fra det observerte spennet og normalisert mot metrikken med størst spenn. Faktorene beregnes over hele søkeregionen (alle 732 ruter i Oslo, Bærum, Lørenskog og Lillestrøm) og er de samme i alle kommuner, fordi brukeren rangerer dem i én felles liste: en viktighetsgrad skal ha samme slagkraft uansett hvilken kommune en rute ligger i. Tidligere ble faktorene beregnet per kommune, og det samme valget telte dobbelt for mat i Lørenskog (2,03) men normalt i Oslo (1,00). Metrikker uten observert data bidrar ikke til spennet. Trygghet har observasjoner i alle områder (delbydeler i Oslo, ett kommunetall i hver Akershus-kommune); kommunetallene ligger innenfor Oslos observerte spenn, så svingfaktoren er uendret. Justeringen endrer aldri selve *scoren* til en rute. Bare hvor mye en brukers valgte viktighetsgrad kan flytte rangeringen, justeres. Tabellen under viser siste beregning:

| Metrikk | Observert spenn | Ruter med observasjon | Svingfaktor |
|---|---:|---:|---:|
| Mat/kollektiv/hverdagstilbud | ~92–97 | 1 090 | 1,01–1,06 |
| Fjordnærhet | ~98 | 732 | 1,00 |
| Bebyggelsens alder | ~98 | 732 | 1,00 |
| Ro | ~92 | 732 | 1,07 |
| Natur | ~90 | 732 | 1,08 |
| Prisgunstighet | ~89 | 732 | 1,10 |
| Investeringspotensial (alle mål) | ~53 | 702 | 1,84 |
| Trygghet | ~24 | 1 090 | 2,00 (begrenset, ellers 4,02) |

Svingfaktoren er begrenset oppad til 2,0 (`MAX_SWING_FACTOR` i `js/scoring.js`). Uten tak ville trygghet (spenn ~24, én kommuneverdi per Akershus-kommune) fått 4,02, slik at det laveste glidertrinnet alene veide mer enn «middels viktig» på alle andre mål og snudde hele rangeringer mellom kommuner. Trygghet er den eneste metrikken som berøres; ingen annen faktor ligger over 2.

Faktorene er ikke håndkalibrert - de regnes ut på nytt hver gang modellen laster, direkte fra rutenes egne scorer, og endrer seg bare hvis det underliggende datasettet endres vesentlig (for eksempel en ny spørreundersøkelsesrunde med et bredere observert spenn).

Den foreløpige totalscoren er det vektede gjennomsnittet av valgte metrikker og reisene. Beregning og sortering bruker full presisjon fra de underliggende avstandene, tellingene, avgangsfrekvensene og prisene; avrunding til et helt tall skjer først når scoren vises, aldri i beregningen eller sorteringen. Scoren begrenses til 1–99, og 100 reserveres fordi modellen har kjente databegrensninger. Hvis boligbehovet er slått av, bruker boligprisgunstighet den generelle, dokumenterte områdeprisen for blokkleiligheter. Ingen bestemt boligstørrelse antas da. Prisgunstighet regnes ut fra forholdet mellom områdets pris og en fast Oslo-referansepris (byens egen gjennomsnittspris for valgt boligtype, ikke min/maks i denne 321-rute-modellen), og bruker faste terskler på det forholdstallet - se avsnitt 8 for samme fastterskel-prinsipp brukt på kollektivtilbud, mat og hverdagstilbud:

| Pris ÷ Oslo-referanse | Prisgunstighetscore |
|---:|---:|
| 0 | 98 |
| 0,6 | 94 |
| 0,8 | 76 |
| 1,0 (lik referansen) | 49 |
| 1,2 | 27 |
| 1,5 | 8 |
| 2,0 eller mer | 0 |

Referansen er den samme for alle kommuner i søkeregionen (Oslos `X i alt`-pris og gjennomsnittlig byleie), slik at «hvor rekker pengene lengst» betyr det samme i Oslo, Bærum, Lørenskog og Lillestrøm. Tidligere ble hver kommune målt mot sin egen gjennomsnittspris, og en gjennomsnittlig leilighet fikk 49 i alle kommuner selv om prisene i kroner er svært ulike (per kvadratmeter: Oslo ca. 101 000, Bærum ca. 87 000, Lillestrøm ca. 72 000, Lørenskog ca. 71 000). Den kommunerelative varianten («billig for sin egen kommune») beholdes som `localScore` på boligestimatet, men påvirker ikke rangeringen. Utenfor Oslo finnes bare én pris per kommune og boligtype, så prisgunstigheten er lik for alle rutene i samme kommune; den skiller kommuner, ikke nabolag.

## 3. Adresser og reiser

Reisemål er valgfrie. Brukeren kan søke via Entur Geocoder v3 eller velge et vanlig reisemål. Når minst ett reisemål er oppgitt, starter live-ruting av alle 472 Oslo- og Bærum-ruter idet reisemålsteget fullføres, slik at den kan arbeide i bakgrunnen mens brukeren svarer på bolig- og prioriteringsspørsmålene. Ingen foreløpig estimat brukes til å velge ut et mindre utvalg først. Modellen brukte tidligere en to-fase tilnærming (et foreløpig estimat valgte ut ~66 av 321 Oslo-ruter for live-sjekk), innført for å begrense antall spørringer mot Entur. Målt mot faktiske live-data på tvers av 15 søkeprofiler viste den tilnærmingen 87 % treffsikkerhet på beste treff totalt, men falt til 0–60 % for reisemål langt fra alle de sju ankerpunktene i den statiske reisematrisen (avsnitt under) - nøyaktig den svakheten estimatet selv har. Siden Entur-dataene er åpne og kostnadsfrie for utviklere, er den risikoen nå fjernet ved å alltid sjekke alle ruter i stedet for å prøve å gjette hvilke som er verdt å sjekke.

Kortlisten bygges bare når hvert forespurte område–reisemål-par har et konklusivt Entur-svar: enten en brukbar live-rute eller en eksplisitt tom `tripPatterns`-liste som betyr at ingen rute finnes. Et manglende alias, en delvis GraphQL-respons eller en mislykket pulje gjør hele matrisen ufullstendig; da vises verken resultatkort, scorefarget kart eller fallback-rangering. Ruter som Entur eksplisitt ikke finner en reise for, kan ikke konkurrere i kortlisten. De fem høyest rangerte rutene tas med direkte; naboruter fjernes ikke fordi de deler et internt delbydelsnavn, siden hver rute har sitt eget offentlige stedsnavn. Hver forespørsel har maksimalt 24 opprinnelse–reisemål-par (Enturs egen grense - 30 fungerer også, men 48 og over avvises), og klienten sender opptil 24 samtidig (målt uten feil ved 8, 12, 16, 24 og 32 samtidige mot 732 ruter; 24 er der gevinsten flater ut). Med to reisemål betyr det 12 opprinnelser per forespørsel, og 40 forespørsler totalt for alle 472 ruter. Søket bruker ønsket ankomsttid på neste hverdag og medianen av inntil tre reiseforslag - antall reiseforslag per spørring har ingen målbar effekt på svartiden, bare på hvor mye detalj (min–maks-spenn) resultatet får. Kollektiv, gange, sykkel og bil støttes. Bilruten inkluderer ikke sanntidskø.

Uten reisemål hoppes live-ruting over. Resultatet bruker da de ni områdemålene med vektene og retningene brukeren har valgt - se avsnitt 2 for hvorfor et helt urørt skjema betyr at ingen av dem teller ennå, ikke en balansert profil med lik grunnvekt.

Det statiske estimatet sammenligner punktet med sju ankerpunkter i reisematrisen. De tre nærmeste ankrene vektes med invers kvadratisk avstand, og 3,5 minutter per kilometer til målet legges til. Dette er ikke ruteberegning og brukes ikke til å publisere en personlig kortliste med oppgitte reisemål. `estimateMinutes()` bruker alltid Entur-resultatet når det finnes; estimatet beholdes for forhåndsberegnede eksempler og diagnostikk.

For live-rutede reiser (ikke fallback-estimatet) telles et bytte eller et gangminutt ikke som «bare enda et minutt» - en direkte reise på 31 minutter slår normalt en reise på nominelt 28 minutter som krever et bytte. Før reisetiden regnes om til en score, justeres den til en «effektiv reisetid»:

`effektivMinutter = minutter + bytter × 10 + gangminutter × 1`

Byttepenaltyen (10 minutter) og gangtidsvekten (1 ekstra minutt per gangminutt, altså dobbel vekt mot sittetid siden minuttet allerede telles én gang i `minutter`) er ikke oppfunnet for denne modellen: de kommer fra publisert transportforskning på generalisert reisekostnad. Litmans VTPI-rapport «Valuing Transit Service Quality Improvements» oppgir byttepenalty på 5–15 ekvivalente kjøretidsminutter (10 minutter under «gjennomsnittlige» forhold, den midterste verdien brukt her), og verdsetter gange/venting til omtrent det dobbelte av sittetid - samme forhold som US DOT sine egne anbefalte reisetidsverdier (ECONorthwest/PBQD 2002: 100 % av lønn for «ekstra» tid mot 50 % for sittetid). Uavhengig forskning fra Vitoria/Madrid finner 13–18 ekvivalente minutter for selve byttepenaltyen, og annet arbeid oppgir 7–15 minutter for kortere og middels lange reiser - alle i samme størrelsesorden. Et fallback-estimat (ingen Entur-svar) har verken byttall eller gangtid å justere for, og scores derfor på rå reisetid alene, som før. Den viste reisetiden i grensesnittet er alltid den ekte klokketiden, aldri den effektive - justeringen påvirker bare rangeringen, ikke hva brukeren får presentert.

Den estimerte (eventuelt justerte) reisetiden omregnes til en score slik:

`reiseScore = clamp(98 × (nullpunkt − effektivMinutter) / (nullpunkt − 6,2), 0, 98)`

Kurven er en rett linje fra 98 poeng ved 6,2 effektive minutter ned til 0 poeng ved et nullpunkt som følger brukerens egen maksimale reisetid `L` for reisemålet: `nullpunkt = maks(L + 25, 1,5 × L)` (`commuteZeroMinutes` i `js/scoring.js`). Uten en oppgitt grense brukes standardgrensen på 45 minutter, altså et nullpunkt på 70 effektive minutter. Nullpunktet lå tidligere fast på 49,8 effektive minutter (`112 − effektivMinutter × 2,25`). Målt mot lagrede Entur-reiser til Nydalen og Skøyen (transitt, ca. 1 120 ruter hver) ga det at 61–62 % av rutene som grensen på 45 minutter slapp gjennom fikk reisescore 0, fordi byttepenalty og gangminutter flytter en reise på 30 klokkeminutter forbi 49,8 effektive minutter; ved 90 minutters grense var 81–91 % av de tillatte rutene like på 0, og spredningen i reisescoren falt fra ca. 20 til 11–14 poeng. Da kunne ikke reisetiden skille mellom områdene brukeren selv hadde sagt var akseptable. Tillegget på 25 minutter gir plass til de to straffene (median 13–31 minutter blant de tillatte rutene i målingen), og faktoren 1,5 tar over når grensen er så lang at 25 minutter blir for lite (over 50 minutter). Med dette kommer bare 2–13 % av rutene på 0 ved 30 og 45 minutter, 5–13 % ved 60 og 1–3 % ved 90, og spredningen holder seg på ca. 18–23 poeng ved alle grenser; antall ulike scoreverdier blant de tillatte rutene går fra ca. 30–38 til ca. 34–92. Å heve grensen ett trinn flytter rekkefølgen blant rutene som allerede var synlige lite (rangkorrelasjon 0,988–0,998 i målingen), men den samme reisen får en litt høyere reisescore jo lengre grense brukeren velger, så reisescoren er sammenlignbar innenfor én brukers valg, ikke på tvers av brukere med ulike grenser. Reisemålet under «Sosialt liv» har ingen reell grense (fast 180 minutter) og beholder den opprinnelige kurven med fast nullpunkt (`LEGACY_COMMUTE_ZERO_MINUTES`). Målingen er gjort for to sentrale reisemål med kollektiv; sykkel, bil og fjerne reisemål er ikke målt mot Entur-data.

**Dag og tidspunkt.** Hvert reisemål har en dag (`when`: hverdager, lørdager eller søndager; fredag brukes bare internt av «Skeive steder») i tillegg til ønsket ankomsttid. Standard er hverdag, som før. Dagen oppløses til en reell dato i Oslo-tid (`nextTripIso` i `js/routing.js`), også over sommer- og vintertidsskiftet, og den oppløste datoen, retningen («arr» for ankomst) og reisemåten inngår i hurtigbufferens nøkkel; bufferversjonen ble hevet til `v2` da nøkkelformen endret seg. Rangeringen bygger på utreisen. Bare «Skeive steder» har i tillegg en returreise (`returnTime`, avgang dagen etter utreisedatoen, `returnTripIso` i `js/routing.js`); den spørres som avgangsbasert Entur-søk fra reisemålet til området, og cachenøklene inneholder den oppløste returdatoen.

**Lagrede reisetider.** Så lenge huskefunksjonen er på (den er det som standard), beholdes også reisetidene som er hentet for de husket adressene (`js/destination-cache.js`). Hver rute har sin egen hentetid (`fetchedAt`), som følger den gjennom gjenbruk og sammenslåing, så aldri noe blir nyere av å bli lest på nytt. Et ferskt søk får tidspunktet satt én gang (`stampMatrix` i `js/routing-cache.js`), før noen av bufrene skrives, og helmatrisebufferen leser det tilbake uendret; en eldre oppføring uten tidspunkt regnes fra sin egen lagringstid. Alderen avgjør bruken: reisetider hentet for under to timer siden (samme levetid som øktbufferen) brukes som gjeldende og gir ingen merking. Reisetider som er to timer til sju døgn gamle vises straks som en foreløpig rangering merket «Viser lagrede reisetider», mens et nytt søk henter dem på nytt og erstatter dem; mislykkes oppdateringen, blir de lagrede tidene stående med en beskjed og en knapp for å prøve igjen. Eldre enn sju døgn brukes ikke, og alt slettes etter 14 døgn. Lagrede tider påvirker poengsummen, men utelukker aldri et område (`liveStale` og `usesSavedTravelTimes` i `js/scoring.js`): et område som mangler er usynlig, mens et område som beholdes feilaktig rettes opp av oppdateringen. Målt på tre reisemålssett endret toppfem seg ikke fra én uke til neste og topp ti hadde minst ni av ti til felles, men 8-11 % av rutenes reisetid endret seg med mer enn 5 minutter og 10-20 områder skiftet mellom innenfor og utenfor en tidsgrense. «Lagrede steder» følger samme regel (`savedTravelTimesFor` i `js/destination-cache.js`): lagrede reisetider på opptil sju døgn gir en foreløpig poengsum merket «Viser lagrede reisetider» med dato, mens søket kjører og viser fremdrift som på resultatsiden (`js/routing-progress.js`); uten lagrede tider som dekker alle rutene vises ingen poengsum før søket er ferdig, og et siste øyeblikksbilde av poengsummer (`js/device-storage.js`) står bare som merket reserve. Poengsummer som hviler på lagrede tider lagres ikke som øyeblikksbilde. Et søk som pågår der avbrytes så snart profilen ikke lenger trenger det (reisemålene fjernet, eller et fullstendig bufret svar finnes), slik at et sent svar eller en sen feil aldri endrer siden.

**Skeive steder (valgfritt, steg 3).** Under «Sosialt liv» kan brukeren slå på «Skeive steder». Det legger til ett vanlig reisemål: gjennomsnittsposisjonen til noen få manuelt verifiserte oppholdssteder i sentrum av Oslo (`data/social-destinations.js`; stedene ligger under 1 km fra punktet og folk beveger seg mellom dem, så brukeren velger ikke enkeltsteder). Hvert sted har egen kilde og kontrolldato, bare steder med åpen adgang er med, og testen i `tests/data-freshness.test.js` feiler etter seks måneder uten ny kontroll. Reisemålet bruker lørdag kveld (fast, ikke valgbart): ankomst 22:30 og hjemreise med avgang 02:30 natten etter, før London Pub stenger kl. 03:30. Begge reisene regnes med, og reisetiden er gjennomsnittet av dem, slik at en god vei dit ikke skjuler en dårlig vei hjem etter at ordinær rutetrafikk har stoppet (nattbuss går først fra ca. kl. 01). Finnes det ingen forbindelse hjem, regnes området som uten forbindelse, på samme måte som uten forbindelse dit. Valget av lørdag, 22:30 og 02:30 er et anslag, ikke målt mot besøksdata, og målingen mot Entur lenger ned (fredag 20:00, bare utreise) gjelder det tidligere valget og er ikke gjentatt for returreisen. Reisemålet kan ha en reisemåte (standard kollektiv) og en viktighet på samme firetrinnsskala som områdemålene (vekt 0,5 / 1 / 1,5 / 2, forslag «Middels»), som erstatter frekvensfaktoren for dette reisemålet. Reisemålet har ingen praktisk tidsgrense (180 minutter, det høyeste tilstanden tillater): reisescoren er allerede 0 ved ca. 50 minutter, og et lagret Entur-scenario (`tests/fixtures/social-destination-scenario.json`, bygges med `node scripts/build-social-scenario.mjs`) viste at en grense på 60 minutter ville fjernet 3 av 14 utvalgte startpunkter med kollektiv og 13 av 14 på sykkel. Dag og klokkeslett er ikke valgbare fordi de knapt flyttet rangeringen i en måling mot Entur for ett av stedene (46 ruter, kollektiv): fredag 20:00 mot hverdag 08:30 ga nesten samme rangering (Spearman 0,92), lørdag 20:00 en tydeligere endring (0,82), og 20:00 mot 23:00 nesten ingen (0,96). Reisemåte er derimot viktig: sykkel mot kollektiv endret reisetiden med en median på 31 minutter. Reisemålet vises ikke i steg 1, huskes på enheten bare hvis brukeren velger å huske reisemål, og er med i resultatlenken slik at den gir samme resultat for mottakeren. Id, navn og posisjon kommer aldri med i en analysehendelse (hendelsene teller bare antall reisemål). Valget sier ingenting om trygghet eller velkomst. Entur mottar posisjonen for å beregne reisene.

Reisen får nøytral grunnvekt 1,0, multiplisert med frekvens. Å oppgi et reisemål betyr at reisen skal telle, men ikke at den uten videre skal veie mer enn en områdemetrikk brukeren har merket «Svært viktig». En eksplisitt maksimal reisetid er fortsatt et krav og behandles før vektingen.

**Hvor mye en reise teller (steg 1).** Hvert vanlig reisemål har et valgfritt felt «Hvor mye skal denne reisen telle?» med fire trinn (litt, middels, mye, svært mye) som gir vekt 0,5 / 1 / 1,5 / 2, altså samme skala som områdeprioriteringene. Står det på «Automatisk» (standard, `importance` er `null`), er vekten frekvensen som før: 1 / 0,72 / 0,38 / 0,16. Velger brukeren et trinn, erstatter det frekvensvekten for dette reisemålet, på samme måte som for «Skeive steder». Frekvensen brukes fortsatt til det ukentlige tidstapet i boligsammenligningen (`TRIPS_PER_WEEK`), så den endrer ikke ukentlig reisemengde. Bakgrunnen er at en daglig reise bare kunne få vekt 1,0, tilsvarende «middels» på en områdemetrikk, så den som synes reisen er det viktigste kriteriet ikke kunne si det. Det trengtes ingen svingfaktor for reisen: reisescoren spenner over omtrent samme bredde som en typisk områdemetrikk ved alle grenser (se kurven i avsnitt 3), så trinnene betyr omtrent det samme som på en metrikk. Bare «Skeive steder» bruker den gamle faste kurven; et vanlig reisemål med eget trinn bruker kurven som følger grensen. Resultatsiden viser hvor stor andel av en typisk score som er reisetid (median av andelen reisevekt av total vekt blant områdene som er med i kortlisten, `travelShareOfScore`), slik at effekten av trinnene er synlig; meldingen skjules når andelen er under 1 % eller over 99 %. Valget følger resultatlenken og den lokale økten, men er ikke med i analysehendelser.

Standard maksimal reisetid er 45 minutter per reisemål, og et område som overskrider grensen tas ut av kortlisten. Fordi standarden lett overses, viser resultatsiden alltid hvilken grense som tok ut områder (`tripLimitBreaches` i `scoreAreas`) og tilbyr å øke nøyaktig den grensen ett trinn.

| Frekvens | Faktor |
|---|---:|
| Daglig | 1,00 |
| Flere ganger i uken | 0,72 |
| Ukentlig | 0,38 |
| Av og til | 0,16 |

Dette gjør en daglig pendling vesentlig viktigere enn en sporadisk reise, uten at alle livsstilspreferanser forsvinner.

## 4. Geografiske ruter og natur

Den scorede enheten er en 750 × 750 meter rute, bygget av SSBs bebodde 250 m-ruter. Bare aggregerte ruter med minst 25 registrerte innbyggere er kandidater. Rute-koordinatet er det befolkningsvektede midtpunktet, slik at ruting ikke starter midt i et ubebodd areal når bosettingen ligger i én del av ruten.

Rutene tegnes med alle fire hjørner transformert fra SSBs UTM-geometri. Dermed følger de samme kantlinjer uten kunstige glipper eller overlapp som kan oppstå når en rotert projeksjon forenkles til breddegrad/lengdegrad-rektangler.

Den fulle 750 m-ruten beholdes både som analyse- og visningsenhet, også ved kommunegrensen og langs fjorden. Dette gir ett sammenhengende, regelmessig kart uten kunstige hull. Andelen bidragende bebodde 250 m-kilderuter lagres som `coverage.inhabitedSourcePercent`; for kyst- og grenseruter er den et granskningssignal, ikke en scorefaktor eller elimineringsregel. Dersom det befolkningsvektede midtpunktet faller mellom adskilte bebodde kilderuter, flyttes rutepunktet til sentrum av nærmeste bidragende kilderute og merkes med `originMethod=populatedSourceCellFallback`. Befolkning, score og kandidatstatus nedjusteres aldri bare fordi mye av analyseruten er vann eller ligger utenfor Oslo.

Naturmålet er gangavstand langs OpenStreetMaps fotgjengernett til en kartlagt sti som krysser inn i et friluftsområde på minst 500 000 m² (50 ha). Målet er «skog og store naturområder», ikke parker: 50 ha ligger mellom Natural Englands Accessible Greenspace Standard-nivåene «Local» (20 ha) og «District» (100 ha), og mindre parker og grønne lommer måles av «Parker og grønt i nærheten» nedenfor. Størrelsesrabatten under er fortsatt forankret i standardens 10 ha-nivå, så å heve minstegrensen fjerner små områder uten å omvekte de som blir igjen. En nær polygonkant uten kartlagt gangforbindelse er ikke en inngang. Ligger rutens befolkningsvektede midtpunkt allerede i området, er avstanden null. Rå luftlinjeavstand til polygonen beholdes separat for QA; manglende eller frakoblet gangnett gir en eksplisitt `straightLineFallback`.

**Samme polygonsett i alle kommuner.** Naturmålet og «Natur»-kartlaget bygges av ett felles polygonsett (`scripts/nature-sources.mjs`; metrikken beregnes på nytt med `scripts/rebuild-nature-metric.mjs` etter modellbygget, kartlaget med `scripts/build-nature-layer.mjs`), slik at ingen kommune er et særtilfelle:

1. Miljødirektoratets kartlagte friluftslivsområder på minst 50 ha, men **uten** områdetypen `strandsoneMedTilhørendeSjøOgVassdrag` (vannflate pluss strandsone: Indre Oslofjord, Bunnefjorden, Glomma, Øyeren og lignende). Målet gjelder skog og land, og fjord-, innsjø- og elvemålene måler allerede tilgang til vann.
2. **Supplert** med eksplisitt utpekte OpenStreetMap-områder i hele regionen: naturreservat, nasjonalpark og områder OSM selv kaller friluftsområde (`scripts/osm-nature-supplement.mjs`). Dette fyller blant annet Lørenskog, der Miljødirektoratets kartlegging ikke har noen områder (kommunenummer 3222 mangler, og det finnes ingen egen kommunefil), så Østmarka innenfor kommunen var usynlig for målet. Generelle verneområder og landskapsvernområder (klasse 5, for eksempel Maridalen og Kolsås) tas ikke med fordi de verner kulturlandskap og jordbruksland, ikke tilgang til stor natur. Markalovens grense (`protect_class=6` og Kartverkets Markagrensen) tas heller ikke med: den er en juridisk sone, ikke et kartlagt friluftsområde, og ett av polygonene er på 145 000 ha, som ville gitt alle nærliggende ruter full størrelsesrabatt. `Østmarka friluftslivsområde` beholdes fordi området selv har det navnet. Vanlig skog tas ikke med.
3. **Uten** polygoner som ligger mest over åpent vann: under halvparten land etter OSMs kystlinje (land til venstre for kystlinjen) og OSM-innsjøer. Det fjerner utfartsområder til havs (Ytre og Indre Skjæregård, Bærumspollen–Lysaker, Lysakerfjorden ytre, Bunnefjorden) og hindrer at et våtmarksreservat som for det meste er innsjø (Nordre Øyeren) slipper vann inn bakveien. Kystlinjen finnes bare for havet og innsjøene bare der OSM har dem.

Virkning: Oslo 25 ruter (snitt 74,2 til 75,3; Ulvøya får Malmøya naturreservat), Bærum 39 ruter (snitt 88,7 til 69,2; Snarøya, Jar og Lysaker hadde nærmeste «natur» i fjorden og faller fra 92–98 til 0–20), Lørenskog 9 ruter (snitt 62,7 til 71,9; Bjørndalen nordøst 48 til 90, Rolvsrud skog 53 til 84) og Lillestrøm 15 ruter (snitt 81,2 til 82,1). Forut for dette var Indre Oslofjord nærmeste «natur» for rundt 100 Oslo-ruter (Loenga øst 97, Grønland 92). Bare ruter der nærmeste område endret seg er berørt. Kartleggingsdekningen i OSM varierer, og vern er ikke det samme som tilgjengelighet.

| Avstand | Naturscore |
|---|---:|
| Inne i området | 98 |
| 250 m | 90 |
| 500 m | 78 |
| 1 000 m | 61 |
| 1 600 m | 39 |
| 2 400 m | 20 |
| 4 000 m eller mer | 0 |

Mellom punktene interpoleres scoren lineært. Tabellen bruker gangavstanden til den valgte inngangen, med samme dokumenterte størrelsesrabatt som før: opptil 90 % kortere effektiv avstand for de største kartlagte områdene.

**Valg av område og gangavtrapping (2026-10-01).** Ruta får scoren til området med best størrelsesrabattert score innen gangavstand, ikke området med kortest vei. Rabatten sier at et større område er effektivt nærmere (Natural Englands standard er «et av nivåene er oppfylt»), så et lite område like ved skal ikke skjule et mye større litt lenger unna. Rabatten gjelder fullt ut til 3 000 m gange og trappes jevnt ned til ingen rabatt ved 5 000 m (`NATURE_DISCOUNT_FULL_WALK_METRES` og `NATURE_DISCOUNT_END_WALK_METRES` i `scripts/model-build-helpers.mjs`, speilet i `natureScore` i `js/scoring.js`). Natural Englands gangnivåer stopper ved 2 km, distriktsnivået på 100 ha ligger ved 5 km, større nivåer forutsetter sykkel, og nærturterreng i Norge er 500 m. Uten noen begrensning ga 90 % rabatt en times gange til et område på 6 500 ha (Bærumsmarka) score 78 og presset hele skalaen mot toppen (snitt 85). En hard grense ved 3 000 m ga et brått fall (88 ved 3 000 m, 11 ved 3 100 m) og ustabile scorer: 7 % av rutene endret seg 20 poeng eller mer ved et forskyvd gangmål på 250 m. Med avtrapping er det 0 %. For et område på 6 000 ha gir 3 000 m score 88, 3 500 m 56, 4 000 m 25 og 4 500 m 6, og ved 5 000 m teller avstanden uten rabatt (0). Søket går i gangnettet til 5 000 m. Settet er felles for alle kommunemodellene; tidligere så hver rute bare polygonene i sitt eget fylkessett, og Oslo-ruter ved Bærum og Lillestrøm så ikke Marka over grensen.

Virkning av felles sett, beste-score-valg og avtrapping: Oslo 65,7 til 71,0 i snitt (Stovnerskogen 28 til 92, Røa sør 19 til 66), Bærum 69,2 til 71,5, Lørenskog 71,9 til 65,6 og Lillestrøm 82,1 til 85,6. Hoppene mellom nabokommuner falt fra 27 til om lag 10 poeng i snitt, mens snittet inni kommunene er uendret rundt 9. Lørenskog går ned fordi mange ruter ligger 3–5 km gange fra Østmarka og Rælingsmarka og tidligere fikk full rabatt på den avstanden; ruter nær 3 km beholder nå mye av kreditten og mister den gradvis, ikke brått.

### Områder med få innbyggere

En rute med færre enn 150 innbyggere (`MIN_RESIDENTS_FOR_SHORTLIST` i `js/scoring.js`) er nesten bare skog, jordbruksland eller industri. Slike ruter kan skåre svært høyt på natur og ro - det er ekte geografi og glattes ikke bort - men det er for få boliger til at de er et realistisk sted å lete. `scoreAreas()` endrer derfor hverken score, kvalifisering eller kartfarge; den setter bare `fewResidents`. `scoreAreasForShortlist()` (`demoteSparseAreas()`) plasserer disse rutene etter alle andre kvalifiserte ruter, på samme måte som budsjettgrupperingen bare grupperer. Resultatsiden sier fra om det og merker kortene. Terskelen er satt til 150 fordi 41 av 508 ruter har under 50 innbyggere og 85 under 150, mens medianen er over 1 800; den er ikke empirisk kalibrert mot boligmassen.

### Parker og grønt i nærheten

Naturmålet over gjelder skog og store friluftsområder (minst 50 ha) og ser ikke den lille parken som brukes hver dag. «Parker og grønt i nærheten» (`greenery`) er derfor et eget mål: gangavstand langs fotgjengernettet til nærmeste inngang til en kartlagt park, grønn lomme eller rekreasjonsplass på minst 5 000 m² (0,5 ha, samme minstestørrelse som WHO Europe og Natural Englands «doorstep green»; OpenStreetMap `leisure=park`/`common`, `landuse=village_green`/`recreation_ground`). Er inngangen til et friluftsområde på minst 10 ha nærmere, brukes den (`localRecreationAccess`), fordi en skogkant også er grøntområde og parkdekningen i OpenStreetMap er tynn utenfor byen. `localRecreationAccess` finnes for alle kommunene (Oslo fikk feltet med `scripts/add-local-recreation-access.mjs`; før det ga en skogkant ved døren nesten null grønt i 51 Oslo-ruter, for eksempel Vettakollen øst med natur 97 og grønt 9). Inngangen defineres som for naturmålet: en kartlagt sti som krysser avgrensningen. Kurven er bratt fordi «nær» for en liten park betyr fem til ti minutters gange:

| Avstand | Grøntscore |
|---|---:|
| Inne i parken | 98 |
| 150 m | 90 |
| 300 m | 76 |
| 500 m | 57 |
| 800 m | 33 |
| 1 200 m | 12 |
| 1 800 m eller mer | 0 |

Målet teller tilstedeværelse og avstand, ikke kvalitet, skjøtsel eller størrelse utover minstegrensen, og OpenStreetMaps dekning av parker varierer. Luftlinje-fallback merkes eksplisitt.

### Behagelig å gå og sykle

To mål beskriver hvor behagelig det er å ferdes ut fra ruten. De måler bare det som lar seg måle pålitelig: underlag, kantstein, kryssing, trafikk og rutekontinuitet er ikke med, fordi kartleggingen av dem er for ujevn til å scores, og manglende kartlagt informasjon tolkes aldri som «tilgjengelig».

**Behagelig å gå:** for opptil 24 punkter på fotgjengernettet 150–600 m gange fra rutepunktet regnes høydeforskjell delt på gangavstand (Kartverkets høydetjeneste, interpolert fra høydekurver), og 75-persentilen av stigningen i prosent scores, slik at ett bratt utgangspunkt ikke midles bort. I tillegg måles andelen av fotgjengernettet innen 600 m gange som er OpenStreetMap `highway=steps`. Scoren er 70 % stigning og 30 % trapper. 5 % er en vanlig komfortgrense for gange og 8,3 % (1:12) den bratteste rampen norsk veiledning tillater, så komforten faller raskt mellom dem:

| P75-stigning i % | Stigningsscore |
|---:|---:|
| 0 | 98 |
| 2 | 92 |
| 4 | 78 |
| 6 | 57 |
| 8 | 35 |
| 12 | 12 |
| 16 eller mer | 0 |

| Andel trapper | Trappescore |
|---:|---:|
| 0 % | 98 |
| 2 % | 86 |
| 5 % | 69 |
| 10 % | 44 |
| 20 % | 15 |
| 35 % eller mer | 0 |

**Behagelig å sykle:** lengden av dedikert sykkelinfrastruktur innen 1 000 m langs nettet (`highway=cycleway`, `bicycle=designated`, `cycleway=track`/`separate` teller fullt, sykkelfelt teller halvt), kombinert med en strengere stigningskurve (55 % infrastruktur, 45 % stigning). Kartleggingen av sykkelinfrastruktur i OpenStreetMap er ujevn utenfor Oslo, så målet kan undervurdere der:

| Sykkelinfrastruktur innen 1 km, km | Infrastrukturscore |
|---:|---:|
| 0 | 0 |
| 0,3 | 29 |
| 1 | 54 |
| 2,5 | 76 |
| 5 | 91 |
| 9 eller mer | 98 |

| P75-stigning i % (sykkel) | Sykkel-stigningsscore |
|---:|---:|
| 0 | 98 |
| 2 | 86 |
| 4 | 59 |
| 6 | 31 |
| 8 | 12 |
| 12 eller mer | 0 |

Ruter uten fotgjengernett eller med for få høydepunkter (færre enn 8) får ingen målt verdi; de behandles som ukjent og erstattes av gjennomsnittet uten å kunne forklare rangeringen, som andre metrikker med delvis dekning. Under «Behagelig å gå» kan brukeren i tillegg sette krav: **maks 8 % stigning** og **få trapper** (høyst 5 % av nettet). Kravene tar ut områder som er målt til å bryte dem; områder som ikke kunne måles tas ikke ut, og et krav du ikke trenger kan slås av igjen. Målingene er første kalibreringer, ikke validert mot bruksdata.

## 5. Fjordnærhet

Fjordnærhet er gangavstand til offentlig tilgjengelige mål: ikke-private dedikerte gangveier som når innen 40 meter av OpenStreetMaps kystlinje, samt kartlagte strender, svømmeområder og offentlige bad. Rå luftlinjeavstand til `natural=coastline` beholdes for QA, og en manglende nettverksrute merkes eksplisitt som fallback. Kystlinjen er fortsatt ikke Kartverkets offisielle Kystkontur-lag.

| Avstand | Fjordscore |
|---|---:|
| 0 m | 98 |
| 250 m | 88 |
| 600 m | 74 |
| 1 200 m | 54 |
| 2 500 m | 29 |
| 5 000 m | 10 |
| 9 000 m eller mer | 0 |

Mellom punktene interpoleres scoren lineært, som for natur. Kurven bruker et lengre spenn enn naturmålets fordi store deler av byen ligger langt fra fjorden. Klassifiseringen er konservativ, men kartdekning og faktiske adgangsforhold kan fortsatt være ufullstendige.

### Innsjø og elv

Fjordmålet gjelder bare kysten. Tidligere kunne strender og badeplasser ved innlandsvann telle som «fjord» i Bærum-modellen (59 ruter); disse er nå regnet om mot kystnære mål (høyst 100 m fra kystlinjen), og innlandsvann har sitt eget mål. «Innsjø og elv» er gangavstand til offentlig innlandstilgang: kartlagte strender, svømmeområder og offentlige bad som ikke ligger ved kysten, og gangveier som når innen 40 m fra en innsjøs strand (minst 5 000 m²) eller 25 m fra en elv (`waterway=river`). Kurven har samme rekkevidde som en fjordtur:

| Avstand | Innsjø-/elvescore |
|---|---:|
| 0 m | 98 |
| 300 m | 86 |
| 800 m | 67 |
| 1 500 m | 45 |
| 3 000 m | 22 |
| 6 000 m eller mer | 0 |

Målet sier at det finnes tilgang, ikke at vannet er badbart eller har god vannkvalitet. Begge mål er første kalibreringer, ikke validert mot bruksdata.

## 6. Ro (vei- og banestøy)

Ro bruker strategisk støykartlegging etter EUs støydirektiv for to kilder: vei, og bane (jernbane, trikk og T-bane). Hver kilde har Lden (døgnmiddel med tillegg for kveld og natt) og Lnight (bare natt). Hver 250 m-befolkningsrute i ruta leses der den ligger, og innen hvert lag velges det høyeste båndet som dekker punktet (hull i støysonene respekteres: et punkt i et hull under terskelen teller som ikke kartlagt). Scoren per kilde og periode er snittet av rutenes score vektet etter antall innbyggere, og klassen som vises er den som ligger nærmest snittet. Roscoren er den laveste (dårligste) av de fire snittene. Kildenes desibelnivåer summeres eller gjennomsnittberegnes ikke; «verste relevante eksponering» er en konservativ og sporbar alfamodell.

| Lden-bånd | Roscore |
|---|---:|
| Ikke kartlagt (under kartets terskel på 50 dB) | 92 |
| 50–54 dB | 88 |
| 55–59 dB | 74 |
| 60–64 dB | 58 |
| 65–69 dB | 40 |
| 70–74 dB | 20 |
| Over 75 dB | 0 |

| Lnight-bånd | Roscore |
|---|---:|
| Ikke kartlagt (under kartets terskel på 50 dB) | 92 |
| 50–54 dB | 88 |
| 55–59 dB | 74 |
| 60–64 dB | 58 |
| 65–69 dB | 40 |
| Over 70 dB | 20 |
| Over 75 dB | 0 |

**Beboermetode (2026-10-10).** Tidligere ble støyen lest i ett punkt per rute, det befolkningsvektede midtpunktet, og veilaget ble lest uten å ta hensyn til hull i polygonene. Revisjonen i `SPATIAL-AUDIT.md` («Støy: ett punkt mot beboernes ruter») viste at punktet avvek med mer enn 20 poeng fra beboernes snitt i 6 til 20 % av rutene, og at hullene ble ignorert i en tredjedel av Askers og Oslos punkter. Støyen er nå snittet over rutens egne befolkningsruter (`scripts/build-resident-noise.mjs`, `npm run build:resident-noise -- <region>`, regneregelen i `residentNoise` i `scripts/noise-model.mjs`). Hver rute lagrer snittscorene og andelen innbyggere med Lden 60 dB eller mer i `rawMetrics.noise.resident`. Som kontroll mot spørreundersøkelsen om støyplage per delbydel (se under) steg korrelasjonen mellom roscore og plage fra −0,43 til −0,62 (Pearson r over 90 delbydeler). Støy for en enkelt kandidatadresse påvirkes ikke, den leses fortsatt ved selve koordinaten.

Vei-Lden er publisert ned til 50 dB, mens den rapporterte bane-Lden-flaten begynner på 55 dB; Lnight begynner på 50 dB. En rute uten polygon får 92, ikke 100: det betyr under lagets rapporteringsterskel, ikke målt stillhet. Fly-, nabo-, bygge-, industri- og utelivsstøy er ikke med i poenget.

Banestøy finnes også for Bærum, Lørenskog, Lillestrøm, Asker, Nordre Follo og Rælingen, hentet fra Miljødirektoratets strategiske støykart for bane (`scripts/fetch-and-build-akershus-rail-noise.mjs`, `npm run build:region -- <kommune> railnoise`). Den er fra situasjonen 2017 og omfatter bare bane med over 30 000 togpasseringer i året, mens Oslos banedata er situasjon 2021; de to er derfor ikke helt sammenlignbare, og datakilden oppgir referanseåret per kommune. Byområdelaget avgjør om «ingen flate» kan tolkes som under terskelen: innenfor Oslo-byområdet er kartleggingen fullstendig (`railCoverage: 'agglomeration'`), utenfor er bare hovedstrekninger kartlagt, og cellen merkes `railCoverage: 'mainLinesOnly'` og flagges i auditverktøyet i stedet for å regnes som verifisert stille. 13 av 411 Akershus-ruter fikk en endret roscore.

Bane NORs T-1442-soner er koblet til rutene som tilleggsevidens. Selv om WFS-tjenesten er oppdatert senere, oppgir alle Oslo-treffene `beregnetÅr=2016`; de er dessuten planleggingssoner, ikke en ny, sammenlignbar Lden/Lnight-måling. De påvirker derfor ikke tallet. Folkehelseundersøkelsen 2024 er på samme måte koblet via delbydelkode og brukes bare til aggregert validering. Den direkte innlemmes ikke per rute fordi den dekker all opplevd støy hjemme og ikke har 750 m presisjon. Etter baneintegrasjonen endret 5 av 321 ruter score; sammenhengen mellom befolkningsvektet delbydels-score og rapportert støyplage var omtrent uendret (Pearson r fra -0,431 for vei alene til -0,433 for vei + bane, 90 delbydeler med publisert estimat). Det er rimelig fordi få rutemidtpunkter fikk en strengere score fra bane enn fra vei. Dette er en diagnostisk kontroll, ikke en kalibreringsfasit.

## 7. Kollektivtilbud (modusbevisst tilgang)

Kollektivtilbud måler det generelle lokale nettet, uavhengig av brukerens reisemål. Reisemålsspesifikk Entur-ruting er fortsatt en separat reisekomponent. Byggesteget henter Entur-plattformer innen 1200 meter, teller unike påstigbare, ikke-kansellerte avganger 07:00–09:00 neste hverdag og dedupliserer samme daterte avgang på tvers av nærliggende plattformer. T-bane, trikk, tog og buss får hver sin observasjon med nærmeste gangavstand, avganger/time, plattformantall og distinkte linjer. Hvert Entur-svar valideres mot Journey Planner v3-skjemaet før noe skrives (`quayEdgesFor` i `scripts/entur-quays.mjs`): `errors` i svaret, en manglende eller tom alias, en plattform uten `id` eller uten `estimatedCalls` som liste, og en avgang uten `expectedDepartureTime`, `forBoarding`, `cancellation` eller `serviceJourney.id` stanser bygget. Bare en uttrykkelig tom liste teller som «ingen avganger». Koordinater, `journeyPattern`, `transportMode` og `datedServiceJourney` kan være null i skjemaet og kreves ikke.

Gangradiusene er buss 800 m, trikk 800 m, T-bane 1200 m og tog 1800 m. Innenfor kjerneradiusen (buss og trikk 600 m, T-bane 900 m, tog 1 200 m) telles alle holdeplasser og avganger med i frekvensen. Utenfor kjerneradiusen finnes en lang, grunn hale som bare brukes for ruter uten noen holdeplass av modusen innen kjerneradiusen, slik at fjerne linjer ikke øker avgangstallet til godt dekkede ruter. Buss og trikk hadde til 2026-10-04 en hard grense på 600 m der kurven falt bratt (buss 38 poeng ved 500 m, 0 ved 600 m), og T-bane og tog falt like bratt mot null i den ytre delen (T-bane 60 ved 700 m til 0 ved 900 m, tog 57 ved 900 m til 0 ved 1 200 m). Det ga hopp på opptil 97 poeng mellom naborater, for eksempel en holdeplass 25 m unna mot ingen innen 600 m. Kurvene er nå: buss 38 poeng ved 500 m og 0 ved 800 m, trikk 72 ved 400 m, 36 ved 600 m og 0 ved 800 m, T-bane 60 ved 700 m, 38 ved 900 m og 0 ved 1 200 m, tog 57 ved 900 m, 40 ved 1 200 m, 18 ved 1 500 m og 0 ved 1 800 m. Kurvene er uendret innenfor 500 m (buss), 400 m (trikk), 700 m (T-bane) og 900 m (tog). Det er en kalibrering mot kildene, ikke en målt gangterskel. Feltstudier av gang til jernbanestasjoner viser lengre gangavstander enn antatte 800 m: median rundt 1 200 m og mer enn 15 % over 1 500 m ved Aucklands togstasjoner (Auckland Transport, tr2012-023), og 85-persentilen er rundt 1 260 m for pendeltog i Montréal. Statens vegvesen regner om lag 1 000 m som influensområde for bane og om lag 500 m for buss, så buss og trikk har en kortere hale enn T-bane og tog. Walk Score bruker også en jevn avstandsavtagende vekt i stedet for en hard grense, og vekter tung bane tyngre enn buss. Dette er en transparent første kalibrering: Statens vegvesens kollektivveiledning viser 400 m gangdekning som planleggingseksempel, mens TØI rapport 858/2006 observerte lengre samlet gange på reiser med T-bane og tog enn med buss og trikk. Kildene dokumenterer retningen, ikke akkurat disse knekkpunktene; de må derfor revurderes mot bruksdata.

Frekvens får avtagende nytte og egne knekkpunkter per modus. Fire avganger/time er et felles viktig nivå, forankret i nasjonal reisevanepraksis for «godt kollektivtilbud». Togkurven når høy nytte ved færre avganger enn buss; bussmetning krever flere avganger slik at mange overlappende busslinjer ikke vinner på rå volum alene. Eksakte tabeller ligger i `data/band-score.js` og er foreløpige, ikke en påstand om at én modus subjektivt er bedre.

Modusscoren er det geometriske gjennomsnittet av avstands- og frekvensscoren: begge må være sterke, og ingen av dem kan fullt kompensere for den andre. Totalen sorterer de fire modusscorene og bruker 78 % av den sterkeste, 16 % av den nest sterkeste, 5 % av den tredje og 1 % av den fjerde. Vektene ble kontrollert mot alle 321 celler: median 71,7, p90 87,0, maksimum 96,6 og bare tre celler over 95. Dermed er et godt enkeltmodusområde konkurransedyktig, mens reelle knutepunkter får en avgrenset multimodal fordel uten krav om alle fire moduser.

Når brukeren valgfritt velger foretrukne moduser, består personlig kollektivverdi av 72 % generell kollektivscore og 28 % foretrukket-modus-signal. Ved flere valg teller sterkeste valgte modus 75 % av signalet og gjennomsnittet 25 %. Dette er en moderat rangeringshelning, aldri et filter; kollektivvekt 0 gjør modusvalgene virkningsløse. Også disse personlige koeffisientene er en første fordelingskalibrering.

Manglende eller frakoblet gangnett gir eksplisitt luftlinje-fallback. Det generelle målet dekker én hverdagsmorgen; kveld og helg er beskrevet under. Det dekker fortsatt ikke retninger, kapasitet, retur eller driftsstabilitet (forsinkelser og punktlighet krever et historisk arkiv som ikke finnes her).

### Kveld og helg

`scripts/fetch-and-build-transit-week.mjs` henter samme Entur-data (holdeplasser i gangavstand, samme modus- og avstandskurver) for tre vinduer til, lagret som `rawMetrics.transitFrequency.week`: hverdag kveld (18:00–22:00), lørdag dag (10:00–16:00) og søndag dag (10:00–16:00), pluss morgenvinduet for sammenligning. For hvert vindu lagres samlescore, score per modus og **lengste opphold** mellom påstigbare avganger (vindukantene teller med), fordi frekvens alene skjuler et langt hull. Alle vinduene er publiserte rutetider for én representativ dato hver, ikke faktisk drift: ingen forsinkelser, helligdager eller punktlighet.

Under kollektivvekten kan brukeren velge «Om kvelden» og/eller «I helgene» (`transitPeriods`). Da er den personlige kollektivscoren 60 % morgen- og modusscore som før og 40 % gjennomsnittet av de valgte periodene (helg er gjennomsnittet av lørdag og søndag). Uten valg er scoren uendret, og en rute uten ukedata endres ikke. Kortet viser scoren og lengste opphold for hvert vindu uansett. Fordelingen er en første kalibrering.

## 8. Restauranter/kafeer og hverdagstilbud

**Restauranter og kafeer** måler gangavstand til de tre nærmeste punktene fra OpenStreetMap (maks 2 500 m) fra rutens befolkningsvektede midtpunkt - langs det kartlagte gangnettet (fortau, gangveier, gågater og andre gåbare OpenStreetMap-veier), ikke luftlinje. Oslo er skåret opp av en fjord og åser, så et punkt som ligger nært i luftlinje kan kreve en lang omvei rundt en bukt eller en motorvei; å måle langs det faktiske gangnettet retter opp dette. Rutens midtpunkt og hvert OpenStreetMap-punkt kobles til nærmeste kartlagte gangvei innenfor 150 meter; en rute uten noen gangvei nær nok, eller der nærmeste gangvei er en kartlagt stubb uten reell forbindelse til det øvrige gangnettet, faller tilbake på luftlinjeavstand for denne beregningen (se `data/oslo-cells.js` for hvor mange ruter dette gjaldt ved siste bygg). Er den nærmeste gangveien en blindvei som bare når under 150 gangnoder innen 600 m (en stikkvei eller privat-liknende servicevei som først kobles til nettet etter en lang omvei), brukes i stedet den nærmeste gangveien innenfor samme 150 m som når minst 150 noder og minst fem ganger så mange (`nearestOriginNode` i `scripts/pedestrian-graph.mjs`, brukt av alle ruteopprinnelser). Skullerud (3 500 innbyggere) ble tidligere koblet til en 58 m unna stikkvei som trengte 1,4 km gange til en T-banestasjon 460 m unna, og fikk kollektiv 0; fem ruter (Skullerud, Loenga øst, Filipstad sør, Brunåsen øst, Kirkerud-Sollihøgda 8 vest) bytter opprinnelse, alle andre beholder nærmeste gangvei.

- **Restauranter og kafeer** (teller i scoren): `amenity` = restaurant eller cafe.
- **Uteliv** (kun rådata, påvirker ikke scoren): `amenity` = bar, pub eller fast_food. Beholdes som `rawMetrics.food.nightlifeCount`, fordi «Restauranter og kafeer» skal telle det navnet lover, ikke mer.

**Score (revidert 2026-10-04).** Tidligere ble antall punkter innen 500 m scoret (0, 2, 6, 15, 35). Det ga null for de fleste ruter utenfor indre Oslo (64 % av 1 090 ruter, 75–95 % i Akershus-kommunene), fordi målet bare skilte «noe i sentrum» fra «ingenting». Nå brukes gangavstanden til de tre nærmeste serveringsstedene (`rawMetrics.food.access.distancesMetres`, søkt til 2 500 m langs fotgjengernettet). Hver avstand scores på kurven for hverdagstilbud (tabellen under), og de tre scorene vektes etter rang: 50 % for nærmeste, 30 % for nest nærmeste og 20 % for tredje (`FOOD_ACCESS_WEIGHTS` i `data/band-score.js`). Én kafé ved døren er et reelt, men tynt tilbud; tre i nærheten er et valg. En rang uten sted innen 2 500 m teller 0. Scoren begrenses til 98.

Utformingen følger to etablerte mønstre: Walk Score veier de nærmeste stedene i kategorier der valgfrihet betyr noe (restauranter og kafeer) med fallende vekt og avstandsavtrapping, og 15-minuttersby-rammeverk skiller «minst ett» (grunnnivå) fra «minst tre» (optimalt nivå) per tilbudstype. Antall og kumulative tilgjengelighetsmål korrelerer over 0,9 med avstandsvektede mål i sammenlignende studier, så valget er et spørsmål om hva som skiller suburbane ruter, ikke om metodisk fasit. Vektene og rekkevidden er første kalibreringer, ikke estimerte koeffisienter, og kurven er den samme som for hverdagstilbud og barn i hverdagen.

Antallet innen 500 m beholdes som rådata (`rawMetrics.food.count`, vist på resultatkortet) og som reservescore for data bygget før `rawMetrics.food.access` fantes. Ruter uten gangnett-opprinnelse bruker luftlinjeavstand med merket `straightLineFallback`.

| Antall punkter (reserve for eldre data) | Restaurant-/kafescore |
|---:|---:|
| 0 | 0 |
| 2 | 29 |
| 5–6 | 54 |
| 10–15 | 76 |
| 18–35 eller mer | 98 |

Målet teller tilstedeværelse og avstand, ikke kvalitet, åpningstider eller antall plasser, og OpenStreetMap-dekningen av serveringssteder varierer mellom kommuner. En lav score utenfor Oslo kan delvis skyldes manglende kartlegging.


**Oppdatering av OpenStreetMap-delen.** Restaurant-, hverdagstilbud- og gangbarhetsmålene (`food`, `amenities`, `walkability`, `rawMetrics.namedAmenities`) kommer fra én felles implementasjon i `scripts/osm-slice.mjs`, brukt av regionbyggerne, Oslo-oppdateringen og `npm run refresh:osm -- <kommune>`. Kommandoen leser den eksisterende `data/<kommune>-cells.js`, henter bare Overpass-flisene for gangnett, mat og hverdagstilbud (samme mellomlager og `.key`-filer som regionbyggeren, i `tmp/model-cache/<kommune>`), regner om denne delen og avbryter hvis noe utenfor den endret seg. Bruk den når bare OSM-dataene skal friskes opp; `npm run build:region -- <kommune> model` kjører hele modellen og blanker mål som senere faser fyller inn. Oslo bruker `npm run build:amenities`. Koordinatene i de lagrede rutene er rundet til seks desimaler, så en oppdatering kan avvike fra et fullt regionbygg med opptil en meter i enkeltavstander (høyst 0,03 poeng i score). Kan ikke Geonorges grunnkretslag lastes ned, avleder `--plan-from-cells` flisplanen fra rutenes egen utstrekning i stedet.

**Hverdagstilbud** måler gangavstand til nærmeste kartlagte instans av tre kategorier - dagligvare, apotek, trening/idrett - med samme gangnett-metode som natur og fjordnærhet (avsnitt 4 og 5): flerkilde korteste vei til hver kartlagt kategori, ikke et antall punkter innenfor en fast radius. Bank og postkontor kartlegges og beholdes som `rawMetrics.amenities.retained`, men påvirker ikke scoren - norsk bankvirksomhet har i stor grad flyttet til mobilapper, og Posten har lagt ned de fleste frittstående postkontor til fordel for «Post i Butikk»-skranker inne i dagligvarebutikker, så en fysisk filial sier lite om hverdagen i et område i dag. Barnehage kartlegges fortsatt som rådata (`rawMetrics.amenities.categories.kindergarten`, brukt til navngitte steder og adressefakta), men inngår ikke i hverdagstilbudscoren: den er et husstandsspesifikt behov og scores under «Barn i hverdagen», så å telle den begge steder ville telle den to ganger.

| Avstand til nærmeste kategori | Hverdagstilbudscore |
|---:|---:|
| 0 m | 98 |
| 300 m | 86 |
| 600 m | 67 |
| 1000 m | 41 |
| 1600 m | 15 |
| 2500 m eller mer | 0 |

Brukeren kan under hverdagstilbud-vekten velge hvilke av de tre kategoriene som teller (`amenityCategories`, `personalAmenitiesScore` i `js/scoring.js`); sluttscoren og forklaringene bruker da bare de valgte kategoriene. Ingen valgt betyr alle tre. Delte lenker og lagrede svar med barnehage valgt under hverdagstilbud ignorerer det valget, og rangeringen av hverdagstilbud er endret fra tidligere modellversjoner fordi barnehage ikke lenger teller i snittet; en husstand som trenger barnehage velger den under «Barn i hverdagen». Sluttscoren er gjennomsnittet av de kategorienes egen avstandsscore, ikke bare den nærmeste eller en sum av antall - en rute som er sterk på noen kategorier og mangler andre, skårer deretter, i stedet for at hver kategori teller som et likestilt poeng i én sum. Mellom punktene interpoleres scoren lineært, som for de andre avstandsbaserte målene.

**Kjedepreferanse (valgfritt tredje nivå).** Etter at en kategori er valgt kan brukeren velge én eller flere kjeder i den (`amenityBrands`; dagligvare: Rema 1000, Kiwi, Coop Extra/Mega/Prix/Obs, Meny, Joker, Bunnpris, Spar; apotek: Apotek 1, Vitusapotek, Boots, Ditt Apotek; trening: SATS, EVO, Fresh Fitness, Fitness24Seven, Feelgood). Katalogen ligger i `data/amenity-brands.js` og er kuratert: bare kjeder med nok kartlagte butikker i regionen er med. Ingen valgt kjede betyr alle butikker, som før; en kjedepreferanse for en kategori brukeren ikke har valgt, gjør ingenting.

- **Kilde:** kjeden leses fra OSM-taggene `brand`, deretter `name` og `operator` (`detectAmenityBrand`). Dekning i rådata: dagligvare ca. 88 % og apotek ca. 93 % har kjede-tagg; for trening er bare ca. 21 % tagget, og navnematching henter inn noen flere. Butikker uten kjent kjede telles fortsatt uten kjedepreferanse, men aldri når en kjede er valgt. `data/candidate-poi.js` lagrer kjedeposisjonen per punkt (`candidatePoiBrands`).
- **Rutenivå (anslag):** gangnettgrafen lagres ikke, så kjedeavstanden er luftlinje til nærmeste butikk i kjeden ganger rutens egen omvei (målt gangavstand til nærmeste butikk av noe slag delt på luftlinje, begrenset til 1,05–1,8). Er kjedens nærmeste butikk også rutens nærmeste, brukes den målte gangavstanden uendret, og ingen kjedeavstand er kortere enn den. Flere valgte kjeder gir avstanden til den nærmeste av dem. Ingen butikk i kjeden innen 2 500 m regnes som reelt fravær og scorer 0 på kategorien; det faller ikke tilbake til en annen kjede. Verdiene ligger i `data/amenity-brand-access.js` (bygges av `scripts/build-amenity-brand-access.mjs`), lastes først når en kjede er valgt, og metoden merkes `brandEstimate`.
- **Kandidatbolig:** gangavstanden fra adressen (`js/address-facts.js`) rutes bare til butikker i valgt kjede.
- **Revisjon:** metrikken `amenityBrands` i `js/spatial-audit.js` viser anslått avstand per kjede og gir et rutekart over kjededekning. Den er ikke en scoret metrikk.


### Barn i hverdagen

«Barn i hverdagen» måler gangavstand langs fotgjengernettet til nærmeste aktive barnehage, nærmeste aktive grunnskole og nærmeste offentlige lekeplass. Barnehager og skoler kommer fra Utdanningsdirektoratets åpne nasjonale registre (NBR og NSR, `data-nbr.udir.no` og `data-nsr.udir.no`), som har offisiell aktivitetsstatus og koordinat: bare aktive enheter, og for skoler bare grunnskoler som ikke er spesialskoler. Lekeplasser kommer fra OpenStreetMap (`leisure=playground`, ikke privat). Hver kategori scores med kurven for hverdagstilbud, og scoren er gjennomsnittet av de valgte kategoriene (ingen valgt betyr alle tre; velges per husstand under prioriteringen, slik at en familie med tenåringer kan velge bort lekeplass):

| Avstand til nærmeste, per kategori | Barnescore |
|---:|---:|
| 0 m | 98 |
| 300 m | 86 |
| 600 m | 67 |
| 1000 m | 41 |
| 1600 m | 15 |
| 2500 m eller mer | 0 |

Begrensninger som fremgår av kortet: registrene oppgir ikke pålitelig trinnfordeling for de fleste skoler, så barneskole og ungdomsskole skilles ikke; skolekretser (opptaksområder) er ikke modellert, så nærhet betyr ikke at barnet har skoleplass der; og en nær barnehage betyr ikke at det er ledig plass. Det finnes ingen «skolekvalitet»-score, fordi resultatdata besvarer et annet og mer omstridt spørsmål enn tilgang.

## 9. Trygghet (opplevd trygghet)

Trygghet bruker det vektede gjennomsnittet på spørsmålet «Trygg i nærmiljøet» (skala 0–10) fra Folkehelseundersøkelsen i Oslo 2024. Oslo kommune og Folkehelseinstituttet publiserer resultatet for alle delbydeler. Dermed kan alle 321 ruter kobles til en observert delbydel via den offisielle delbydelskoden som allerede ligger i boligprisenes geografi, uten navnematching eller nøytral imputering. Trygghetsdata dekker 321 av 321 ruter.

| Trygg i nærmiljøet | Trygghetscore |
|---:|---:|
| 0 | 0 |
| 2 | 20 |
| 4 | 39 |
| 6 | 59 |
| 8 | 78 |
| 10 | 98 |

Omregningen er lineær og bevarer undersøkelsens egen 0–10-skala; scoren rangeres ikke relativt til det observerte spennet i Oslo. For hver delbydel beholdes den publiserte utvalgsstørrelsen og 95 % konfidensintervallet. Tallene er vektet, men særlig små delbydeler har større statistisk usikkerhet og mulig usikkerhet fra hvem som valgte å svare. Politiets trygghetsundersøkelse beholdes som tilleggsevidens for delbydelene der den finnes, med eget spørsmål, år og kilde, men den påvirker ikke trygghetsscoren.
 **Akershus (kommunenivå).** For Bærum, Asker, Lørenskog, Lillestrøm, Nordre Follo og Rælingen brukes kommunegjennomsnittet på samme 0–10-spørsmål fra Folkehelseundersøkelsen i Akershus 2025 (FHI, 2026, figur 251, avsnitt 3.46), avlest fra figuren med to desimaler: Asker 8,76, Bærum 8,67, Nordre Follo 8,48, Lillestrøm 8,05, Rælingen 8,27 og Lørenskog 7,43. Tallene er justert for kjønn, alder og utdanning, mens Oslos delbydeltall er vektede gjennomsnitt, så skalaen og spørsmålet er det samme, men ikke nøyaktig samme estimator. Rapporten oppgir ikke utvalgsstørrelse eller konfidensintervall per kommune som tall, så de lagres som `null` i stedet for å anslås. Hver rute er merket `rawMetrics.safety.resolution = 'municipality'`. Verdien er lik for alle ruter i en kommune: trygghet skiller derfor mellom kommuner, ikke mellom nabolag, og kortene og sidene merker den som kommunegjennomsnitt. Samme lineære omregning brukes (ingen egne terskler). Lisens for FHI-rapporten er ikke eksplisitt avklart (se DATA-LICENSES.md). Bygges med `npm run build:municipality-safety` / `node scripts/build-municipality-safety.mjs`.

## 10. Bebyggelsens alder (bipolar)

De åtte foregående metrikkene er ensrettede: brukeren sier hvor viktig «mer av dette» er, og et urørt valg (0) betyr ingen innflytelse. Bebyggelsens alder er derimot bipolar - brukeren velger en **retning** (eldre/historisk eller nyere/moderne), ikke bare en styrke, fordi det ikke finnes noen objektiv «riktig» side: en som ønsker nybygg skal ikke straffes fordi modellen antar at historisk bebyggelse er bedre, og omvendt. `BIPOLAR_METRICS` i `data/model-schema.js` markerer hvilke metrikker dette gjelder - foreløpig bare denne ene.

I brukerens svar lagres verdien som et fortegnet tall fra -4 til 4 (0 = ingen preferanse). Fortegnet er retningen, tallverdien er styrken, og styrken slås opp i akkurat samme vekttabell som avsnitt 2 (`preferenceWeights[|verdi|]`). To uavhengige, faktabaserte observasjoner ligger til grunn - ikke én kombinert skala:

- **Historisk preg:** antall SEFRAK-registrerte bygninger (Riksantikvarens åpne register over bygninger som i prinsippp er oppført før 1900) innenfor rutens egne 750 m-grenser, hentet direkte fra Riksantikvarens API per rute - ikke koblet via delbydel eller grunnkrets.
- **Nyere bebyggelse:** andelen av dagens boligmasse (Oslo kommunes BOL001, grunnkretsnivå) som er fullført siden 2010 (BOL008), med sterkere vekt på de siste årene (2010–14 × 0,4, 2015–19 × 0,7, 2020–24 × 1,0). Koblet til rutenettet via samme grunnkretskode som allerede ligger i boligprisenes geografi. Utenfor Oslo (der BOL001/BOL008 mangler) brukes SSBs åpne 250 m boligrutenett: netto tilvekst i boliger per femårsperiode 2010–2025 med de samme vektene, som andel av rutens boliger i 2025 og trukket mot kommunens eget tall (SSB 05940/06265) for små ruter. Det er en tilnærming (netto, ikke brutto tilvekst), og det boligvektede snittet stemmer med SSBs kommunetall.

| SEFRAK-bygninger i ruten | Historisk-score |
|---:|---:|
| 0 | 0 |
| 3 | 25 |
| 10 | 49 |
| 30 | 71 |
| 100 | 88 |
| 300 | 98 |

| Andel bygget siden 2010 | Nyere-score |
|---:|---:|
| 0 % | 0 |
| 5 % | 25 |
| 15 % | 49 |
| 35 % | 74 |
| 70 % | 90 |
| 100 % | 98 |

Bare den ene av de to observasjonene brukes til å score en gitt rute - hvilken, avgjøres av retningen brukeren har valgt. Historisk-tabellen er ikke rangert relativt til Oslos eget spenn (samme prinsipp som trygghet i avsnitt 9), men er heller ikke forankret i en ekstern standard slik kollektiv- og restaurantterskler er - det finnes ingen publisert skala for «historisk bygningstetthet» å anker mot, så tersklene er en første kalibrering mot det faktisk observerte spennet på tvers av 321 ruter, og bør revurderes etter bruk. Et fåtall grunnkretser mangler egen rad i gjeldende BOL001-utgave (omdøpt/slått sammen siden forrige inndeling); disse bruker et gjennomsnitt for nabogrunnkretser i samme delbydel, eller bydel om nødvendig, i stedet for å stå uten data - merket eksplisitt i rådataene (`geographyFallback`). Det samme gjelder grunnkretser med færre enn 50 boliger eller flere nye boliger enn boliger i alt (`MIN_DWELLING_STOCK` i `scripts/build-built-character-score.mjs`): Sognsvann hadde 9 boliger og 836 vektede nybygg og fikk 98 for «nyere bebyggelse»; med nabogrunnkretsene i delbydelen er det 55.

Denne metrikken måler historisk/etablert versus nylig utbygd bebyggelse - ikke arkitektonisk skjønnhet eller stil. Et 1890-tallsbygg, en funksjonalistisk 1930-blokk og et nytt 2020-tallsbygg kan ikke rangeres som «pent» til «stygt» ut fra byggeår alene, og modellen gjør ikke det forsøket.

### Bebyggelsesform (bipolar)

«Bebyggelsens alder» og «bebyggelsesform» er to forskjellige spørsmål: en nyere bydel kan være lav villabebyggelse, og et gammelt strøk kan være tette bygårder. Åpne data gir ikke byggeår (Kartverkets åpne Matrikkelen-bygningspunkt har bygningstype, status og antall bruksenheter, men ikke byggeår), så alderen kan ikke forbedres fra dem. Formen kan måles: bygningstypekoden skiller enebolig, tomannsbolig, rekkehus og lignende småhus (koder 111–136) fra store boligbygg, og for store boligbygg angir koden etasjeklassen (3–4 etasjer eller 5 og over: koder 142, 143, 145, 146). Andelene regnes over boliger (bruksenheter), ikke bygninger, fordi én blokk med 80 leiligheter rommer like mange hjem som 80 villaer. Garasjer, fritidsbygg og næringsbygg er utelatt, og bare bygg i bruk telles; bygg under oppføring telles separat som evidens for pågående utbygging (`underConstruction`).

Som bebyggelsens alder er dette en **retning**, ikke en styrke: brukeren velger «Villastrøk og småhus» eller «Tett bebyggelse» (fortegnet), og styrken bruker samme vekttabell. Bare faktaen som svarer til valgt retning scores:

| Andel boliger i småhus, % | Småhusscore |
|---:|---:|
| 0 | 0 |
| 20 | 25 |
| 50 | 54 |
| 75 | 80 |
| 90 eller mer | 98 |

| Andel boliger i store boligbygg (3+ etasjer), % | Tett-score |
|---:|---:|
| 0 | 0 |
| 10 | 25 |
| 30 | 54 |
| 55 | 80 |
| 80 eller mer | 98 |

Ruter med færre enn fem boligbygg får ingen målt verdi og behandles som ukjent (erstattet av gjennomsnittet uten å kunne forklare rangeringen). Terskelene er første kalibreringer. Å ønske en moderne leilighet betyr ikke nødvendigvis å ville bo i et nytt strøk, og omvendt: boligen selv og nabolaget er forskjellige ting.

## 11. Investeringspotensial (valgbare mål)

Metrikken har én viktighetsgrad og tre valg, med samme interaksjon som dagligvare, apotek og trening: **Inntekt fra utleie**, **Mulighet til å selge igjen** og **Prisvekst på lang sikt**. Bare valgte delmål inngår, med lik vekt; ingen valgte delmål betyr alle tre. Metrikken er av fra start. En aktiv metrikk med bare videresalg eller bare langsiktig prisvekst rangerer derfor etter akkurat den delscoren.

Utleie bruker brutto leieavkastning, videresalg årlige salg relativt til boligmasse, og langsiktig prisvekst gjennomsnittet av pris relativt til inntekt og framskrevet boligbalanse. Alle terskler er uendret fra tabellene nedenfor. Videresalg er en indikator for markedsaktivitet, ikke målt salgstid; vekst er indikatorer, ikke en estimert framtidig avkastning. Historisk prisvekst og nylig byggeaktivitet påvirker fortsatt ikke score.

`investmentGoalScore` i `data/band-score.js` er felles beregning for normalisering i `data/areas.js`, personlige scorer og audit. Den krever bare inndata til de valgte målene. Manglende valgt evidens gir ukjent score, ikke null eller et snitt over gjenværende mål. Kildegeografi og tynt utvalg vises separat; det brukes ingen krymping mot den gamle samlescorens median. `preferences.investmentGoals` renses og lagres som de øvrige kategoriutvalgene; delte resultatøyeblikksbilder inkluderer fortsatt ingen preferanser. Auditverktøyet har egne valg for alle tre delmål.

Oslo bruker BOL014-markedsleie for 2025 i utleiescoren. Leilighetsprisen fra BOL018 estimeres geometrisk: `w = lokale salg / (lokale salg + 10)` og `pris = exp(w × log(lokal pris) + (1 − w) × log(områdepris))`. Lokal grunnkretsområdepris må ha minst ett salg og positiv, endelig pris. Områdeprisen er nærmeste delbydel, bydel eller hele Oslo med minst ti salg og positiv, endelig pris. Uten brukbar lokal pris brukes områdeprisen direkte; uten brukbar områdepris finnes ikke estimatet. Faktiske lokale salg, begge priser, områdegeografi og vekt lagres som evidens; estimatet merkes i resultatkortet. Metoden gjelder bare Oslos leieavkastning. Verdsettelse, omsetning, Akershus-modeller, scoreterskler og målvekter er uendret. [Valideringen](research/investment-validation-2026-10-04.md) fant 6,9 % lavere relativ prisfeil (log-RMSE) i holdte testår; dette validerer ikke framtidig investeringsavkastning.

Den gamle 35:10:20-samlescoren beholdes i genererte kildefiler for reproduksjon, men brukes ikke i offentlig rangering eller visning.

**Liten befolkningsjustering i Oslo (2026-10-04).** I de 15 ordinære Oslo-bydelene justeres verdsettelsesscoren med ett poeng per standardavvik av treårig logvekst i fysisk bosatte 30–59 år (BEF001), før gjennomsnittet med boligbalansescoren. For beslutningsår 2026 brukes 2020–2023, samme tre års informasjonslag som i valideringen. Standardiseringen gir lik vekt til hver av de 15 bydelene; den bruker ikke nettstedets ruter, kommuner eller utvalg. Justert verdsettelse begrenses til 0–98. Ruten beholder sin offisielle bydels observasjon og kildegeografi. Akershus, Sentrum og Marka får ingen slik justering. Manglende verdsettelse eller boligbalanse forblir manglende.

Styrken ble redusert fra fem til ett etter kontroll av dagens rangering, før ett-poengsresultatene ble beregnet. Det er et forsiktig valg, ikke en optimalisert regresjonskoeffisient. Den historiske **verdsettelseskomponentens** femårige rangfeil falt 1,25 %; komplett vekstscore har fortsatt ikke en historisk tilbakeprøving. Syntetiske tester av ukjent boligbalanse støtter retningen, men er ikke målt prognoseevne. Justeringen finnes i 289 ruter; 281 vekstscorer endres −0,69 til +1,34 poeng, og åtte er uendret ved skalagrensene. Median absolutt endring blant de 289 er 0,21. De tre målene og alle båndgrenser er beholdt. [Kontroll og begrensninger](research/growth-combined-2026-10-04.md). BEF001-kilden, alder, antall, år og standardisert vekst beholdes i `data/investment-demographic-demand.js`, normaliserte rådata og audit; resultatkortet oppgir bydel og historisk periode.

### Historisk samlescore (ikke lenger aktiv)

Resten av dette avsnittet dokumenterer de beholdte kildefilene og tidligere beregning, ikke gjeldende rangering.


Investeringspotensial er en numerisk 0–98-score som samler tre delscorer: inntekt (brutto leieavkastning for en 2-roms blokkleilighet), likviditet (omsetning av boligmassen) og vekstutsikt (to indikatorer). Delscorene vises alltid hver for seg på resultatkortet. Scoren sier ingenting om bygningens stand eller risiko, og er ikke en prognose for prisvekst eller avkastning. For en bestemt bolig brukes Investeringssjekken i kandidatverktøyet, som regner netto avkastning, kontantstrøm og nødvendig prisvekst med brukerens egen finansiering. Historisk prisvekst påvirker ikke poengsummen; den eksisterende Oslo-backtesten fant tilnærmet null sammenheng med senere prisvekst (se INVESTMENT-PROFILE.md).

Tabellene under beskriver Oslos versjon (BOL014/BOL018/BOL001/INN003/BEF037, Oslo kommunes egne tabeller). Bærum, Lørenskog, Lillestrøm, Asker, Nordre Follo og Rælingen har samme score bygget fra nasjonale SSB-kilder (tabell 09895/14310/06265/06944/14746) med samme formel, vekter og terskler fra `data/band-score.js`, men med SSBs modellerte lokale pris (tabell 14737, skalert til kommunens observerte salg) og delområdeinntekt (tabell 06944) i stedet for observerte lokale salg, så inntekten og verdsettelsen varierer mellom rutene (evidensnivå «modellert lokal pris»). Likviditet og boligbalanse er kommunetall som deles av alle rutene i kommunen. Se INVESTMENT-PROFILE.md avsnitt «Akershus-kommunene».

| Delscore | Vekt | Datagrunnlag |
|---|---:|---|
| Inntekt | 35 | Brutto leieavkastning: BOL014-markedsleie / BOL018-kjøpspris for blokkleiligheter |
| Likviditet | 10 | Årlige salg av alle boligtyper / komplett boligmasse (BOL001) ved samme geografinivå; enheter med ufullstendig boligmasse hoppes over til neste grovere nivå |
| Vekstutsikt | 20 | Gjennomsnittet av to indikatorer: pris relativt til hva lokal inntekt predikerer, og framskrevet boligbalanse (BEF037) |

Vektene er faste startverdier (35 : 10 : 20), ikke empirisk estimerte koeffisienter. Alle fire inndata må være observert; en score fra færre ville belønne et område der de øvrige bevisene mangler. Hvor godt inndataene er underbygget rapporteres som evidensnivå, og scoren trekkes mot et referansepunkt etter evidensnivået (`shrinkInvestmentScore` i `data/band-score.js`): `score = 56 + tillit × (råscore − 56)`, der 56 er omtrent medianen av Oslos observerte grunnkretsscorer og tillit er 1 for observert pris med minst 20 salg, `salg / 20` (aldri under 0,5) for tynt utvalg, 0,7 for modellert lokal pris (SSB 14737 mot Oslos observerte priser: r 0,89) og 0,5 for ett kommunetall. Uten dette fylte modellerte Lillestrøm-ruter med median 100 innbyggere 27 av de 40 høyeste scorene; nå er det 6. Vektene er en første kalibrering, ikke estimerte koeffisienter. Råscoren ligger i `rawScore` og tilliten i `confidence`, og resultatkortets tre delscorer vises uendret. Vekstutsikten er uvaliderte indikatorer og har bevisst moderat vekt (om lag en tredjedel av scoren).

Evidensnivået beskriver prisgeografien bak avkastningen: `local` (prisen kommer fra områdets eget grunnkretsområde), `area` (fra delbydel eller bydel), `citywide` (hele Oslo) og `modelled` (SSBs modellerte lokale pris utenfor Oslo, skalert til kommunens observerte salg) og `municipality` (ett kommunetall). Leien er et sonetall i alle regioner (Oslo har fem leieområder). `thinSample` markerer en avkastningspris bygget på færre enn 20 leilighetssalg, og `resaleFromLargerArea` at omsetningen kommer fra et grovere geografinivå enn prisen. `thinSample` og evidensnivået inngår i tilliten over; `resaleFromLargerArea` endrer ikke scoren.

Brutto leieavkastning er årlig markedsleie per m² (BOL014, byområde, 2-roms) delt på kjøpspris per m² for blokkleiligheter (BOL018, boligtype «Blokkleilighet»), sistnevnte hentet på finest mulig geografi med minst 10 leilighetssalg.

| Brutto leieavkastning | Investeringsscore |
|---:|---:|
| 2 % | 5 |
| 3 % | 29 |
| 4 % | 54 |
| 5 % | 74 |
| 6 % | 86 |
| 9 % | 98 |

Terskelverdiene er en første kalibrering mot det faktisk observerte spennet (291 av 321 ruter dekket - Marka-bydelene har ingen leiesone, og Sentrum får leien fra SSB 09897), ikke en ekstern avkastningsstandard. Tallet er ikke justert for felleskostnader, vedlikehold, skatt eller andre kostnader.

Omsetning måler hvor stor andel av boligmassen som ble omsatt siste år ved samme geografiske nivå. Høyere verdi betyr mer dokumentert mulighet for videresalg, ikke forventet prisvekst. Den er ikke det samme som inventory-to-sales, siden åpne data mangler beholdningen av usolgte annonser.

| Omsatt andel av boligmasse | Likviditetsscore |
|---:|---:|
| 0 % | 0 |
| 1 % | 15 |
| 3 % | 39 |
| 5 % | 57 |
| 8 % | 74 |
| 12 % | 88 |
| 20 % | 98 |

Pris relativt til inntekt er prisen delt på prisen Oslos eget inntektsmønster predikerer for den lokale inntekten: `(lokal pris / Oslo-pris) / (eksp(a) · (lokal inntekt / Oslo-inntekt)^b)` med a og b fra en log-log-tilpasning over Oslos delbydeler (`data/investment-valuation-fit.js`, 90 delbydeler, elastisitet 0,64, R² 0,25). En enkel pris/inntekt-kvotient brukes ikke: med elastisitet under 1 ville den gjøre alle høyinntektsområder «billige». Tilpasningen forklarer bare om lag en fjerdedel av prisforskjellene (boligmiks og beliggenhet står for resten), så dette er en indikator, ikke en verdivurdering. Verdi under 1 betyr billigere enn inntekten tilsier.

| Pris / predikert pris | Verdsettelsesscore |
|---:|---:|
| 0,65 | 98 |
| 0,80 | 78 |
| 0,95 | 57 |
| 1,05 | 44 |
| 1,20 | 25 |
| 1,40 | 8 |
| 1,60 | 0 |

Framskrevet boligbalanse er prosentvis befolkningsvekst minus prosentvis vekst i boligmengden fra 2025 til 2030 i BEF037. Oslo kommunes befolkningsframskrivning er selv delvis betinget av det samme boligbyggingsscenarioet. Komponenten beskriver derfor balansen *innenfor kommunens scenario*, ikke en uavhengig prognose om udekket etterspørsel.

| Boligbalanse, prosentpoeng | Boligbalansescore |
|---:|---:|
| −15 | 5 |
| −7 | 25 |
| 0 | 49 |
| 5 | 71 |
| 10 | 86 |
| 20 | 98 |

Vekstutsikten er gjennomsnittet av verdsettelsesscoren og boligbalansescoren.

## 12. Kandidatboliger

En kandidatbolig beholder områdescoring fra nærmeste 750 m-analyserute for kontekstmetrikkene, men reisetiden erstattes med en ny Entur-beregning fra kandidatens eksakte koordinat til hvert personlig reisemål. Bytter og gange får samme dokumenterte belastning som i avsnitt 3. Kandidatreiser mellomlagres i nettleserfanen i to timer, og nøkkelen inkluderer kandidatkoordinat, reisemålets plass og posisjon, transportmåte, oppløst reisedato og grensene for reisetid, bytter og gange (`js/candidate-route-cache.js`); på en enhet der brukeren har valgt å huske adresser beholdes de i 14 døgn og vises som «Lagret anslag» med dato mens en ny reise hentes. Anslaget finnes på boligens koordinat og reisemålets plass, transportmåte, klokkeslett, dagtype, retur og grenser, men uten den oppløste datoen (`candidateRouteEstimateKey`): «08:30 på hverdager» peker på en ny dato hver morgen, og en nøkkel som fulgte den ville aldri funnet gårsdagens svar. Mens en reise hentes, vises en pulserende plassholder i kommuteradene i stedet for «–». Av de returnerte reisene brukes den som holder grensene (`js/journey-limits.js`), og den samme reisen vises i tabellen, i poengsummen og på kartet; først når ingen reise holder grensene faller boligen ut. En bolig hvis egne reiser ikke er bekreftet, utelukkes ikke av områdets prototypereisetid (`settleEstimatedElimination` i `js/candidate-commute.js`). Boligens egen reise er et eksakt svar for adressen, ikke et lagret anslag for området, så `applyCandidateJourneys` fjerner lagret-merket (`liveStale`) for boligens rute før poengberegningen, og en bekreftet reise over grensene utelukker boligen selv om områdets tid vises som lagret.

Når brukeren oppgir faktiske annonsetall, erstatter de områdets prisobservasjon i kandidatens prisgunstighetsbidrag. For kjøp brukes `(prisantydning + fellesgjeld) / oppgitt størrelse` mot den samme byreferansen og de samme forholdsbåndene som områdescoren. For leie brukes `månedlig leie + oppgitte tilleggskostnader` mot romtallets eksisterende byreferanse. Budsjettstatus sammenligner den faktiske totalprisen eller månedskostnaden direkte med brukerens budsjett uten områdedataenes usikkerhetsmargin. Er prisgunstighet ikke valgt som prioritet, vises økonomien fortsatt som eksakt fakta, men påvirker ikke totalscoren.

### Målt ved adressen

For kandidatboliger måles støy og gangavstand fra selve koordinaten i stedet for fra rutens midtpunkt (`js/address-facts.js`, `data/candidate-poi.js`, `scripts/build-candidate-poi.mjs`). **Støy** leses live fra samme strategiske støykartlegging som områdemodellen: veg fra Miljødirektoratet for alle, bane fra EEA for Oslo (situasjon 2021) og fra Miljødirektoratet for Akershus (situasjon 2017), med samme Lden-/Lnight-bånd og regelen om at det høyeste båndet teller. Kan ikke en av kildene leses, beregnes ingen stillhetsscore. **Gangavstand** til nærmeste dagligvare, apotek, treningssenter, barnehage, grunnskole, lekeplass, park, kyst, innsjø/elv og T-bane/trikk/tog: de to nærmeste punktene i hver kategori (luftlinje) sendes til Enturs gangeruting, og den korteste faktiske gangruten brukes. Feiler rutingen, vises luftlinje merket som anslag, aldri som gangavstand. Enturs gangnett og områdemodellens OpenStreetMap-nett er ikke identiske, så tall for en adresse og for cellen kan avvike også der adressen ligger midt i cellen.

Der alle nødvendige målinger finnes, erstatter de områdets verdi i kandidatens poengsum for ro, hverdagstilbud (valgte kategorier), barn i hverdagen, innsjø/elv og fjord (`addressMetricOverride` i `js/scoring.js`, samme kurver som områdemodellen); manglende målinger beholder områdeverdien. Grønt i hverdagen og natur beholder områdeverdien, siden områdets grønt også teller inngang til store friluftsområder som adresseoppslaget ikke har. Alt er merket «adressebasert» i sammenligningstabellen. Koordinaten sendes til Entur, Miljødirektoratet og EEA og ikke inn i delte lenker.

Alle kandidatverdier merkes med kilde, kildedato, geografisk oppløsning, eksakt/kontekstuell status og beregningsstatus. «Adressebasert» brukes bare for kandidatens koordinat eller brukerens egne annonsetall; modellrute, delbydel og bydel merkes eksplisitt som grovere kontekst.

Hver reisemålsrad i sammenligningstabellen viser i tillegg gangminutter og byttetall fra samme Entur-rute, med samme ordlyd som reisefakta ellers i appen. Er kandidaten ikke raskest til dette reisemålet, vises et omtrentlig ukentlig tidstap sammenlignet med raskeste kandidat: `(kandidatens minutter − raskeste minutter) × 2 × reiser per uke`, avrundet til nærmeste minutt. Faktoren 2 er tur-retur, ikke bare den enveis reisetiden appen ellers viser. Reiser per uke er et eget, dokumentert anslag (`TRIPS_PER_WEEK` i `js/scoring.js`) og må aldri forveksles med `frequencyWeights`, den relative vektingen reisefrekvensen ellers får i totalscoren:

| Oppgitt frekvens | Reiser per uke |
|---|---:|
| Daglig | 5 |
| Flere ganger i uken | 3 |
| Ukentlig | 1 |
| Av og til | Vises ikke - for sjelden til et pålitelig ukestall |

Daglig antar en vanlig femdagers arbeidsuke. Flere ganger i uken bruker midtpunktet av «mer enn én, men ikke hver dag» (2-4 ganger). Av og til utelates helt fra det ukentlige tidstapet, siden en reise som ikke nødvendigvis skjer de fleste uker ikke gir et pålitelig ukestall.

Kandidatboliger, reisemål, boligbehov og prioriteringer er som standard bare i nettleserfanen (samme mellomlagring som resten av arbeidsflyten). Et eget, avkrysset valg («Lagre denne boliglisten på denne enheten») lagrer i tillegg det samme feltsettet i `localStorage`, versjonert og renset med nøyaktig samme funksjon som fanelagringen (`encodeSessionState`/`parseSessionState` i `js/state.js`) - en skadet eller manipulert verdi kan derfor aldri gi noe utover ordinære standardverdier. Lagringen krysses aldri av automatisk; brukeren må aktivt slå den på, og et synlig «Glem lagret liste»-valg fjerner den igjen. Persistens er alltid til stede på denne enheten alene og forlater aldri nettleseren - ingen kontosynkronisering, ingen ekstern lagring.

En egen, atskilt lenke («Del sammenligning») kan dele selve sammenligningen mellom to eller flere kandidatboliger. Denne bruker et helt eget, versjonert format (`kind:'candidate-report'`, `encodeCandidateReport`/`parseCandidateReport` i `js/state.js`) og gjenbruker aldri det eksisterende områdesnapshotet (`kind:'result-snapshot'`). Boligene er anonymisert som «Bolig A», «Bolig B» osv. som standard; et eget avkrysningsvalg for å ta med de faktiske adressene må hukes av på nytt hver gang lenken lages, og starter alltid av. Reisetider og boligøkonomi er aldri med, uavhengig av dette valget: `encodeCandidateReport` fjerner selv alle bidrag av type `commute` og all kandidatøkonomi før noe annet - inkludert beslutningssammendraget i avsnitt 13 som gjenbrukes for den delte teksten - får se dem, i stedet for å stole på at kalleren har gjort det. Delte kandidatrapporter og selve kandidatarbeidsflaten er `noindex,follow` og ligger utenfor sitemap.xml, på samme måte som resten av arbeidsflyten (avsnitt «Kildeprivat» andre steder i dokumentasjonen).

## 13. Beslutningssammendrag for kandidatboliger

Sammenligningstabellen for kandidatboliger (avsnitt 12) viser rå tall. Over tabellen vises i tillegg et kort sammendrag - hvilken bolig som passer best samlet, hvem som vinner på reisetid, prisgunstighet og hver vektede prioritering, hovedkompromisset for de(n) ledende boligen(e), og om én bolig er svakere enn en annen på alle sammenlignbare forhold. `candidateDecisionSummary` i `js/scoring.js` beregner dette som ren data; selve setningene bygges i `js/app.js` via `candidateSummary`-ordboken.

Alle disse sammenligningene skjer på den samme 0-98/1-99-skalaen scoring allerede bruker for hver metrikk, reisescore og prisgunstighetsscore. Én terskel gjenbrukes derfor for alt sammendraget sammenligner, i stedet for at hver sammenligning finner opp sin egen: to boliger regnes som **omtrent likestilt** når forskjellen er under 10 poeng på denne skalaen - samme grense `resultHighlights` i `js/app.js` allerede bruker (`CANDIDATE_TIE_THRESHOLD` i `js/scoring.js`). Total reisetid (summen av bekreftede reisemål) bruker i stedet en egen grense på 3 minutter (`CANDIDATE_COMMUTE_TIE_MINUTES`), gjenbrukt fra samme fils reisetidsvarsel.

En kandidat regnes som **dominert** når en annen kandidat er minst like sterk (innenfor 10-poengsgrensen) på alle forhold de har til felles - reisemål, vektede prioriteringer og prisgunstighet - og klart sterkere (10 poeng eller mer) på minst ett av dem. Minst to felles, dokumenterte forhold må sammenlignes før noen kalles dominert; «alle sammenlignbare forhold» sier ingenting med bare ett.

Sammendraget arver de samme garantiene som resten av modellen:

- En kandidat uten beregnet resultat (uløst adresse, ingen nærmeste rute) holdes utenfor sammenligningen - manglende data behandles som ukjent, aldri som null eller svakest mulig.
- En bolig hvis reiser ennå ikke er hentet, eller som mislyktes, regnes som ubekreftet: den utelukkes ikke av områdets prototypereisetid, og ingen bolig kåres til best så lenge den finnes.
- Bare bidrag med `weight > 0` og `explains !== false` telles. En metrikk brukeren ikke har vektet, eller en implisitt nøytral verdi uten reelle observasjoner, kan aldri gjøre én kandidat til vinner eller «hovedkompromiss».
- Hovedkompromisset for en ledende kandidat er det svakeste vektede, dokumenterte bidraget for nettopp den kandidaten - aldri hentet fra en annen kandidats data.
- Er en ledende kandidats faktiske pris over det oppgitte budsjettet, vises dette alltid som eget varsel i sammendraget, uavhengig av samlet score.

## 14. Forklaringer

For hver kandidat beregnes bidraget som `(områdeverdi − 50) × vekt`. Når minst to faktorer er aktive og minst én er sterk, blir opptil tre bidrag over null «Hvorfor det passer», mens det svakeste bidraget under null kan bli «Viktigste kompromiss». Et kompromiss krever dermed en reell avveiing mellom valgte faktorer.

Sammenligningen «Sammenlignet med …» på resultatkortene (`compareAreas`) bruker de samme personlige bidragsverdiene som rangeringen, og reisetiden fra det hentede søket. En forskjell under 10 poeng gir ingen påstand, og det gjør heller ikke en verdi uten observasjon (`explains: false`).

Når bare én faktor er aktiv, vises den i stedet under «Hva rangeringen bygger på» med den konkrete kildefaktaen, uansett om verdien ligger over eller under 50. Den samme faktoren kan aldri kalles et kompromiss: hvis alle tilgjengelige områder er svake på brukerens eneste prioritering, er de fortsatt rangert etter denne prioriteringen. Når flere faktorer er aktive, men alle ligger under 50, vises den relativt sterkeste som rangeringsgrunnlag og den svakeste under «Viktig å vite». Samme bidrag kan aldri vises i begge rollene.

### Evidensdekning og nære resultater

Hvert resultat har `evidence` (`scoreAreas` i `js/scoring.js`). `coverage` er andelen av den samlede vekten (områdemetrikker og reiser) som hviler på faktiske observasjoner; en erstattet verdi (avsnitt 2, `explains: false`) holder rangeringen beregnelig, men er ikke evidens og teller ikke. Kortet viser «Målte data dekker X % av det du har vektet» når andelen er under 100 %. `low` og `high` er poengsummen dersom hver ukjent verdi i stedet lå på 10.- eller 90.-persentilen av metrikkens observerte scorer; uten ukjente verdier er intervallet ett punkt.

`leaderCloseCalls()` sammenligner ledende resultat med de ti neste. To grunner til at et resultat regnes som nært: poengforskjellen er under 10 (`CANDIDATE_TIE_THRESHOLD`, samme «omtrent likt»-grense som kandidatsammenligningen), eller utfordrerens beste utfall når lederens verste utfall fordi noe av grunnlaget mangler. Bare den andre grunnen gir en melding i resultatlisten, siden nabo­ruter ofte ligger innenfor 10 poeng av hverandre uten at dataene er svake. Intervallet er en enkel følsomhetsanalyse, ikke et statistisk konfidensintervall.

## Flom og kvikkleire (faktaopplysninger, ikke scoret)

Flom og kvikkleire påvirker ikke poengsummen. Det finnes ingen glidebryter, fordi et samlet «trygg mot flom»-tall kunne latt en god kafeplassering veie opp for en risiko brukeren ikke aksepterer. Dataene vises som faktaopplysninger med kilde (`js/hazards.js`, NVEs åpne kartkatalog `kart.nve.no/enterprise/rest/services`):

- **Flom, detaljert:** `Flomsoner2`, kartlagte flomsoner per gjentaksintervall (10–1000 år). Gjentaksintervallet hentes fra laget, og analyseområdelaget avgjør om stedet er kartlagt i det hele tatt.
- **Flom, aktsomhet:** `Flomaktsomhet`, en grov nasjonal screening basert på terrengmodell og FKB Vann. NVE oppgir at den viser potensielt utsatte områder og ikke sier noe om årlig sannsynlighet.
- **Kvikkleire, detaljert:** `SkredKvikkleire2`, kartlagte faresoner med faregrad (Ingen, Lav, Middels, Høy), konsekvens og risikoklasse.
- **Kvikkleire, aktsomhet:** `KvikkleireskredAktsomhet`, en grov screening for mulig marin leire og bratt terreng.

Tilstandene skilles bevisst: *innenfor kartlagt sone*, *kartlagt område, men utenfor sonene*, *ikke kartlagt* og *utilgjengelig*. Å ligge utenfor en kartlagt sone eller aktsomhetsflate betyr ikke at stedet er trygt, og «ikke kartlagt» betyr ikke fritt for fare. Aktsomhetsflater dekker mye av sentrale strøk (666 av 732 ruter berører flomaktsomhet), så de vises for ruter bare når de dekker minst en fjerdedel av ruten, og alltid med dekningsandelen. Terskelen er et visningsvalg, ikke en risikogrense.

Det er to oppløsninger: `data/hazard-flags.js` (bygget av `scripts/build-hazard-flags.mjs`) gir per 750 m-rute «noe av ruten berører laget» og andelen av ruten (16 × 16 punktnett) for aktsomhetslagene; ruter beskrives som «deler av ruten», aldri som en adresse. For en kandidatbolig gjør nettleseren i tillegg et direkte oppslag på selve koordinaten (fire forespørsler til `kart.nve.no`, ca. 150–400 ms), som vises i sammenligningstabellen med kilde og dato. Koordinaten sendes bare til NVE, ikke inn i delte lenker eller kandidatrapporter, og personvernsiden sier fra om det. Feiler en av tjenestene, får bare de flaggene status «utilgjengelig».

## 15. Testprofiler

Disse profilene brukes til regresjonstesting:

- **Urban pendler:** Adresse ved Oslo S daglig, maks 30 min; mat, hverdagstilbud og kollektiv svært viktig.
- **Rolig natur:** Adresse ved Nationaltheatret flere ganger i uken, maks 50 min; ro, natur og pris svært viktig.
- **To reisemål:** Adresser ved Skøyen og Helsfyr, begge maks 40 min; kollektiv og gange viktig.

Profilene skal gi tydelig forskjellige topplister. Automatiske regresjonstester krever dessuten minst 100 forskjellige totalscorer i hver profil, én tydelig toppscore og ingen score på 100. Enkeltprioritetene testes separat: de kontinuerlige eller fullt observerte målene skal ikke ha et kunstig topplatå, mens ekte båndbaserte likheter for natur og ro beholdes. Dersom profilene konvergerer eller scorefordelingen flater ut igjen, bør dataspredning, reisematrise og vekter vurderes før nye funksjoner legges til.

## 16. Faste profiler på guide-sider

De offentlige guide-sidene bruker fire faste, redaksjonelle profiler som startpunkt. De endrer ikke den personlige modellen og er ikke en universell fasit. Hver profil bruker de samme områdescoringene og svingfaktorene som ellers i Stedsvalg:

- **Balansert:** prisgunstighet, kollektiv, natur, ro, opplevd trygghet, servering og hverdagstilbud vektes likt.
- **Barnefamilie:** opplevd trygghet 2; natur, ro og hverdagstilbud 1,5; prisgunstighet 1; kollektiv 0,75.
- **Rimelig med kollektiv:** prisgunstighet 2; kollektiv 1,5; hverdagstilbud 0,75.
- **Ny i Oslo:** kollektiv 2; hverdagstilbud 1,5; servering 1; natur, opplevd trygghet og prisgunstighet 0,75.

Guide-rangeringene viser aggregerte, kjente stedsnavn. Når et offentlig sted består av flere analyseområder, vektes metrikkene etter befolkning på samme måte som råverdiene på stedssidene.

## Fargeklasser på resultatkartet

Kartet viser matchscoren i fire klasser (`scoreClassBreaks` i `js/scoring.js`). Scoren er et vektet snitt, så jo flere prioriteringer som er aktive, desto tettere samles scorene rundt midten (med 12 aktive metrikker er spennet mellom 10. og 90. persentil om lag 17 poeng og høyeste score om lag 77). Faste grenser på 68/78/88 ga da 80 til 90 % av kartet laveste klasse. Hver grense er derfor medianen, 75. og 90. persentil av de gjeldende, ikke-eliminerte rutene, men begrenset til et bånd: aldri over den gamle faste grensen (68/78/88) og aldri under en bunn (55/62/70). Bunnen gjør at et svakt resultatsett ikke får en mørk klasse bare fordi det er det beste av et dårlig utvalg. Er spennet mellom 10. og 90. persentil under 20 poeng, sier forklaringen at områdene ligner mye på hverandre. Forklaringen viser grensene mellom klassene. Fargene er en jevnt trappet turkis rampe (jevne steg i OKLab) valgt slik at fargene man faktisk ser med 0,68 fyllopasitet over kartbunnen er likt fordelt, og tegnforklaringens fargeruter har de blandede fargene. Bunn, tak og spenngrense er foreløpige valg, ikke estimerte verdier. Landingssidens eksempelkart bruker fortsatt de faste grensene. Rangering og poengsum påvirkes ikke.

## Dataproveniens

`data/oslo-cells.js` og `data/baerum-cells.js` lagrer hvert sitt kildegrunnlag, utgiver, lisens, referansedato, hentetidspunkt, oppløsning og metode. `data/areas.js` eksponerer det regionspesifikke registeret og normaliserer synlig oppløsning til `cell`, `subdistrict`, `municipality`, `regional` eller `unavailable`. Hver rute skiller mellom `derived` og `prototype` per metrikk og beholder rå observasjoner. Slik kan UI-et forklare en konkret score uten å dikte opp begrunnelser eller bruke en Oslo-kilde for en Bærum-rute.

## Kilder for reisekostnads- og naturmodellen

Bytte- og gangtidspenaltyen i avsnitt 3 er ikke egne antakelser. De bygger på:

- Litman, T. *Valuing Transit Service Quality Improvements*, Victoria Transport Policy Institute. <https://www.vtpi.org/traveltime.pdf>
- *An international time equivalency of the pure transfer penalty in urban transit trips*. <https://www.sciencedirect.com/science/article/abs/pii/S0967070X22001226>
- *Not All Transfers Are Created Equal: Towards a Framework Relating Transfer Connectivity to Travel Behaviour*, Transport Reviews, Vol. 29, No. 6. <https://www.tandfonline.com/doi/abs/10.1080/01441640902811304>

Naturmetrikkens 90 %-tak i avsnitt 4 er hentet fra:

- *Accessible Greenspace Standard*, Natural England. <https://designatedsites.naturalengland.org.uk/GreenInfrastructure/AccessibleGreenspaceStandard.aspx>

Kollektivkurvene i avsnitt 7 bruker:

- Statens vegvesen, *N-V123 Kollektivveiledning*. <https://store.vegnorm.vegvesen.no/n-v123>
- TØI rapport 858/2006, *Turer til fots og på sykkel*. <https://www.vegvesen.no/globalassets/fag/fokusomrader/nasjonal-transportplan-ntp/reisevaner/eldre/toi-rapport-858-2006-rvu-2005-turer-til-fots-og-pa-sykkel.pdf>

### Kommunebefolkning som grunnlag for investeringsvekst (2026-10-04)

Utenfor Oslo beregnes befolkningsvekst 2025–2030 fra kommunens offisielle folkemengde 1. januar 2025 (SSB tabell 07459) til kommunens framskrevne folkemengde i 2030 (tabell 14746, MMMM). Begge tall gjelder hele samme kommune. Summen av innbyggere i nettstedets dekkede ruter brukes ikke som nevner: den utelater innbyggere og ville overvurdert veksten. Rådata og detaljprofiler beholder begge folketallene, og kilderegisteret oppgir basistabell, år og kommunekode. Manglende grunnlagsobservasjoner stopper byggingen. Boligvekst, verdsettelse, scoreterskler og de tre aktive investeringsmålene beholder samme metode.
