Skip to content
Swellread

swellread-engine/2026.10.1

Everything the engine does, written down

One function, one set of weights, one code path shared by the pages, the REST API and the agent tools. If you disagree with a factor, you can change it here and the same change applies everywhere.

Weights

Nominal weights, renormalised over what exists

FactorNominal weightDropped when
Swell power0.22no swell height or period from the source
Peel speed0.20no verified tide value for this break
Wind quality0.20wind speed, wind bearing or swell bearing missing
Tide window0.18no verified tide value for this break
Direction match0.12no swell bearing from the source
Period cleanliness0.08no swell height or period from the source

The nominal weights sum to exactly 1. When a factor has no real data behind it, its weight is removed and the rest are divided by what is left, so the score is always an average of comparable quantities rather than a quietly penalised score. A dropped factor shows as not scored in the interface, with the reason in its own words.

The six factors

What each one computes and why

Physics

The two formulas that carry most of the weight

Green's law on the reef face

Hb = Hs₀ · (γ · tanβ)^¼

with γ = 0.78, the solitary-wave breaking index. The result is the height at which the swell trips on the face. It is then capped by the water you actually have, Hb = min(Hb, γ·depth), because a wave in water shallower than Hb/γ has already broken further out and is closing rather than standing up.

Shallow-water celerity

c = √(g · depth)

This is why tide matters more than most forecasts admit. The same 1.2 m swell over a 0.6 m take-off peels at about 10 km/h and is unridable; over 2 m it peels at 19 km/h and is the best thing on the coast. The drag control on every break page exists to make that relationship visible.

Gates

The hard rules that override the weighted sum

Tide windows by break type

Break typeIdeal bandMinimum safeReads
reef pass0.9–2 m0.60 mneeds the pass covered
reef0.6–1.4 m0.40 mwants the reef just covered
point0.5–1.2 m0.30 mprefers a filling tide
beachbreak0.8–2.2 m0.30 mworks across the tide
river mouth0.7–1.6 m0.40 mneeds the bar swept

Bands

Score to verdict

The day's window is the longest contiguous run of hours at or above 0.50, ties broken on mean score. If nothing clears 0.50 the app still returns the single best hour rather than shrugging.

Integrity

How the chain is built

seal_n = SHA-384( UTF-8(prevSeal) || canonicalJson(event_n) )

genesis prevSeal = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Canonical JSON sorts object keys recursively by UTF-16 code unit, preserves array order, drops undefined and normalises non-finite numbers. seal and prevSeal are stored beside the event, never inside it, so the body that gets hashed is exactly the body in the table.

Deleting a session is a soft delete that keeps a tombstone, so the chain stays replayable forever. The replay tool recomputes every link and names the first broken one.

genesis = 000000000000000000000000…

Data

Sources, and what happens when they fail

NOAA CO-OPS

Hourly tide predictions, MLLW datum, keyless. The observed water_level product is deliberately not used for forecasts because it stops at "now".

Open-Meteo

Marine for swell height, period and bearing; Forecast for wind, air temperature, cloud and rain. Both keyless, both CC BY 4.0.

Failure

If every upstream fails, a sealed dated synthetic profile is shown and labelled fallback. It never replaces anything a user created, and it never invents a tide for a break with no station.

Break coordinates describe real coastlines. Peel orientation, reef slope and take-off depth are this project's editorial estimates and are labelled as such wherever they appear. Repository https://github.com/aniruddhaadak80/swellread.