nightglass

Method

How a score is produced

Engine 2026.1.0. One pure function, shared by the browser UI, the REST routes and the MCP tools. Same inputs, same numbers, forever.

The astronomy first

Everything positional is computed from J2000 coordinates with real ephemerides. Sidereal time uses the standard GMST series; the Sun uses the NOAA low-precision solar algorithm, accurate to about 0.01°; the Moon uses the truncated ELP series from Meeus chapter 47, accurate to roughly 0.3° in longitude. Atmospheric refraction follows Bennett’s formula.

The astronomical night is the longest run during which the Sun sits at or below −18°. The scan is coarse, then both edges are bisected onto the exact crossing, so the reported start and end of night are real twilight times rather than five-minute samples.

The tests assert properties rather than stored strings: that Polaris sits at your latitude to within its real 0.74° offset from the pole, that a full synodic month contains both a new and a full moon, and that the lunar elongation and the illuminated fraction agree with each other across a whole cycle.

Six factors, weights summing to 1.00

  1. horizon clearance

    weight 26%

    How long, and how high, the target stays above your local obstruction.

    The altitude curve is sampled every five minutes across the astronomical night. Each sample is lifted by atmospheric refraction, compared against the obstruction you entered, and the fraction of samples that clear it is combined with the peak altitude.

  2. sky darkness

    weight 20%

    Whether the sky is dark enough to see what you are pointing at.

    Sun altitude at mid-night, the naked-eye limiting magnitude implied by your Bortle class, and the Moon's illuminated fraction weighted by its angular separation from the target.

  3. instrument reach

    weight 20%

    Whether your aperture can actually show it.

    Limiting magnitude is 7.7 + 5·log₁₀(aperture in cm) under a class-6 sky, adjusted by the light-pollution penalty. Objects larger than three arcminutes are scored on surface brightness instead, weighted 0.7 against 0.3 for magnitude, because that is what actually limits visual detection of extended objects.

  4. transparency

    weight 16%

    How clear and clean the air is.

    Live from Open-Meteo: total and low cloud across the dark window combined with horizontal visibility. A clear hour after three cloudy hours does not make a clear night, so the whole window is averaged.

  5. seeing tolerance

    weight 10%

    Whether the target survives unsteady air.

    Angular size sets how much seeing costs the target. Modelled as a floor plus a power law rather than a product, because a plain product would make a large target swing harder than a small one, which is backwards.

  6. culmination

    weight 8%

    How high it can ever get from your latitude.

    The closed form 90° − |latitude − declination|. This is the theoretical maximum, independent of the night, so it is a genuinely separate signal from the sampled curve in the first factor.

Bands and the horizon gate

Score ≥ 78 prime, ≥ 60 good, ≥ 40 fair, ≥ 20 poor, below that blocked.

One hard gate overrides all of it: if a target never rises above your stated obstruction, the score is clamped into the blocked band and flagged gated. Without that, a beautifully clear night would still score a treeless target “fair” on the strength of transparency alone, which is the wrong answer for someone standing under a tree.

Integrity

Every create, update, decision, ranking, export and delete appends an audit event sealed with seal_n = SHA-384(UTF-8(prevSeal) || canonicalJson(event_n)), chained per entity from a genesis value of 96 zeros. Canonical JSON sorts object keys recursively so the byte representation does not depend on property insertion order.

Deletions are soft. A tombstone event is appended and the row is flagged, so the chain still replays cleanly after a delete. The verify route reports the first broken link if one exists.

What this does not do

  • It does not model local light pollution beyond the Bortle class you enter. Bortle is a coarse instrument and yours is the honest input.
  • Seeing is estimated from wind speed and low cloud, not measured. Turbulence at your specific site is the single biggest source of error in the transparency factors.
  • It does not know your horizon. It only knows the single obstruction angle you give it, which is why that control is the most important one on the page.
  • It is a planning aid. Computed altitudes are not a substitute for looking up, and nothing here should be used to aim equipment without checking the sky.

Engine version 2026.1.0 · read the source