Introduces two convenience methods on TimePoint that step by one resolution
unit rather than a hard-coded millisecond:
TimePoint plusResolution() == plus(getResolution())
TimePoint minusResolution() == minus(getResolution())
They are implemented once in AbstractTimePoint and saturate at EndOfTime /
BeginningOfTime just like plus/minus do. Expressing "the next/previous
representable instant" through getResolution() keeps these sites correct
should a finer-resolution TimePoint ever be introduced, instead of assuming
one-millisecond granularity.
All plus(1)/minus(1) call sites whose receiver is a TimePoint and whose intent
is a single resolution tick were converted to plusResolution()/minusResolution()
across production and tests. Deliberately left unchanged:
- plus(1)/minus(1) on Duration receivers (not TimePoints)
- TimePointTest overflow/saturation tests that exercise plus(long)/minus(long)
with the literal 1 on purpose
Assisted-By: Claude Opus 4.8 (claude-opus-5)
RegattaLogDeviceMappingEvent.getToInclusive() is an inclusive end, but
TimeRange.to() is exclusive. TopLevelMasterData.addRangeIfMappingEvent
built TimeRange.create(from, toInclusive); for a single-instant PING
mapping (from == toInclusive, e.g. a pinged mark) this is an empty range,
which MultiTimeRange silently discards. The device is then never streamed
and its single fix never reaches the importing instance.
Convert the inclusive end to an exclusive one by adding one TimePoint
resolution unit (currently 1ms), so [t, t] becomes the non-empty range
[t, t+1ms), and load the corresponding fixes with toIsInclusive == false
in MasterDataResource.writeRaceLogTrackingFixes. Update the related
Javadoc on both sides accordingly.
Adds MasterDataImportTest.testMasterDataImportPingedMarkSingleInstantFix,
which reproduces the drop (single-instant inclusive mapping with one
stored fix) and now passes.
Assisted-By: Claude Opus 4.8 (claude-opus-5)
they capture the liveURI/storedURI as taken from the connection
configuration, and not the expanded, calculated versions after looking
at the params file