fix(input): correct lon mapping

This commit is contained in:
gili8420 2026-08-04 13:40:50 +09:00
parent 19557f3a62
commit 84d1664b29
20 changed files with 1197 additions and 137 deletions

View file

@ -26,10 +26,13 @@ type EventSummary struct {
}
// EventSink collects events from models and the integrator, aggregating
// duplicate types into a single EventSummary. Safe for concurrent use.
// duplicate types into a single EventSummary. It also carries the run's first
// unrecoverable failure, which is a different thing from an event — see Fail.
// Safe for concurrent use.
type EventSink struct {
mu sync.Mutex
summaries map[string]*EventSummary
err error
}
// NewEventSink returns an empty sink.
@ -61,6 +64,42 @@ func (s *EventSink) Emit(typ string, t float64, state State, message string) {
}
}
// Fail records the run's first unrecoverable error. Nil-safe, like Emit.
//
// Deliberately not an event. An event is an observation the caller may choose to
// ignore: "above_model" means samples above the highest pressure level were
// extrapolated, which degrades the answer without invalidating it. A failure
// means the sampler had no data at all, so the trajectory from that point on is
// not a forecast and must not be returned as one.
//
// Routing both through Emit is how the second came to be treated like the first.
// WindTransport discarded the sampler's error and returned a zero rate, which is
// indistinguishable from calm air, so any launch past the dataset's horizon
// integrated with no wind and produced a balloon that took off and landed on the
// same spot — reported as a successful prediction.
//
// Only the first failure is kept: it is the one that explains the run.
func (s *EventSink) Fail(err error) {
if s == nil || err == nil {
return
}
s.mu.Lock()
defer s.mu.Unlock()
if s.err == nil {
s.err = err
}
}
// Err returns the first failure passed to Fail, or nil if the run was sound.
func (s *EventSink) Err() error {
if s == nil {
return nil
}
s.mu.Lock()
defer s.mu.Unlock()
return s.err
}
// Snapshot returns a stable copy of every summary in deterministic order
// (sorted by Type).
func (s *EventSink) Snapshot() []EventSummary {