Pipeline view — how inputs become the score

The score is a chain of 9 functions. Each stage takes 1-2 inputs and produces an intermediate value (y₁, y₂, …). The output of one stage feeds the next. Drag a slider — every chart's dot moves, and downstream charts also reshape because they depend on the value you changed.

Back to interactive explorer

Legend — what the abbreviations mean
T
daily-high temperature, °C
RH
relative humidity (daytime mean), %
v
mean wind speed, m/s (= wind_kmh × 0.6 / 3.6)
e
vapour pressure (function of T & RH)
AT
apparent temperature ("feels-like"), °C — Steadman/BoM
hf
humidity comfort factor, 0.55–1 — penalises high or low RH
tc_raw
Thermal Comfort (raw) sub-index BEFORE humidity factor, 0–10
TC
Thermal Comfort sub-index AFTER humidity factor, 0–10 = tc_raw × hf
A
Aesthetic sub-index, 0–10 — sunshine, capped by rain
P
Precipitation sub-index, 0–10 — blend of rain days & hours
W
Wind sub-index, 0–10 — ideal at ~10 km/h mean
w_tc, w_a, w_p, w_w
weights for each sub-index, sum to 10 (profile-dependent)
HCI_raw
Holiday Climate Index BEFORE override gate, 0–100
gate
override-gate multiplier, 0.3–1 — caps extreme heat/cold
HCI
final Holiday Climate Index, 0–100 = HCI_raw × gate
score
displayed 1–10 = round(HCI / 10)
dial
user-set upper edge of thermal comfort plateau, 22–32°C
① AT(T) — apparent temperature
y = T + 0.33·e − 0.70·v − 4
shape varies with: RH, wind
-20
T=29.1°C → AT=31.0°C

"Feels-like" temperature. Above ~25°C the humidity term dominates — a wet 30°C feels much hotter than a dry 30°C. Wind shaves a small amount off via evaporative cooling.

② hf(RH) — humidity factor
y = clamp(1 − |RH − 50|·0.011, 0.55, 1)
shape is fixed (pure function)
0.5
RH=61% → hf=

Inverted-U around 50% RH. Both bone-dry (dehydration) and muggy (sweat can't evaporate) reduce comfort. Multiplies tc_raw downstream — capped at 0.55 so even extremes don't zero-out thermal.

③ tc_raw(AT) — thermal curve
piecewise (plateau, falloff)
shape varies with: profile, dial
0
AT=31.0°C → tc_raw=

Plateau at max (10) inside the comfort zone. Falls off asymmetrically — faster on the heat side (quadratic) because humid heat is inescapable; gentler on the cold side because layering helps.

④ TC = tc_raw × hf
linear scaling — slope depends on hf
shape varies with: RH (sets slope)
0
tc_raw= × hf= → TC=

Straight line through origin with slope = hf. A perfect-thermal day (tc_raw=10) still loses 12-45% of its score if humidity is extreme. This is how humidity quietly drags down Mediterranean-coastal summers.

⑤ A(sun) — sky sub-index
y = clamp(sun·0.75/21), then capped by rain_h
shape varies with: rain_h (caps the curve)
0
sun=379.5h → A=

Linear rise with sunshine until ~280h/month, then plateaus at 10. A heavy-rain month caps the value regardless of sunshine — drizzly skies can't claim a clear-sky score.

⑥ P(rain_h) — precip sub-index
0.4·day_score + 0.6·hour_score
shape varies with: rain_d (shifts baseline)
0
rain_h=67 → P=

Blends two angles: rain DAYS (frequency of disruption, ~40% weight) and rain HOURS (cumulative wet-time, ~60%). Lets us distinguish brief intense storms from drizzle-all-day patterns.

⑦ W(wind) — wind sub-index
piecewise around ideal ~10 km/h mean
shape is fixed (pure function)
0
wind=19 → W=

Sweet spot is a light ~10 km/h breeze. Dead calm is mildly worse (stuffy); strong wind is penalised hard (above ~30 km/h sand/dust/hair/umbrellas all become a problem).

⑧ HCI_raw
weighted sum of 4 sub-indices, shown as a stacked bar
0 TC A P W
=

Weighted sum to 0–100. Weights depend on profile: urban (4,2,3,1) — thermal dominates; beach (2,4,3,1) — sky dominates because swimmers can offset heat. The stacked bar shows each factor's actual contribution length.

⑨ gate(AT) — override gate
caps composite past heat / cold threshold
shape varies with: profile, dial
0.3
AT=31.0°C → gate=

Multiplier that caps the score when apparent temperature crosses a deal-breaker. Stays at 1.0 in the safe range; drops sharply above the heat threshold or below the cold threshold. Floor is 0.3 — Dubai July still scores something.

× →
⑩ Final = HCI_raw × gate → score
gate caps the raw HCI; final ÷10 rounded gives the displayed 1–10
0 HCI=— HCI_raw=—
HCI =   score =

Multiply HCI_raw by the gate, divide by 10, round to integer 1–10. That's the colored cell you see on every city page. The bar shows pale-yellow = uncapped raw score, green = what survives after the gate.