Skip to content

feat(hy3): keep each entry's own distance, stroke, course and column-96 flag - #32

Open
fsalum wants to merge 2 commits into
SwimComm:masterfrom
fsalum:feat/entry-distance
Open

fsalum wants to merge 2 commits into
SwimComm:masterfrom
fsalum:feat/entry-distance

Conversation

@fsalum

@fsalum fsalum commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Keep each entry's own distance, stroke, course and column-96 flag on EventEntry, read from its E1/F1 line.

Why

Meet.get_or_create_event keys events by event number alone, so when one event number carries more than one distance the Event holds only the first distance it saw, and every later entry's own distance is lost. Two real Meet Manager export shapes do this:

  • Combined-distance events: swimmers in one event number choose between distances (400 or 500, 1000 or 1650, 25 or 100). Every entry after the first is reported at the wrong distance.
  • Split-request entries: Meet Manager can record an intermediate split as its own official time. It writes a second E1 for the same event number with the shorter distance, fee 0.00, seed 0.00 and an S (sometimes T) in column 96, followed by an E2 carrying the split time. Read through Event.distance, a 500 split of a 1000 free comes out as "a 1000 free" in the split's time.

Example from a real export (names shortened):

E1F  916SmithFG  1000A 13 14  0S  4.25  7A  715.47Y  715.47Y ...   NN               N
E2F  707.50Y ...
G1F ... F40  351.55 ... F80  707.50
E1F  916SmithFG   500A 13 18  0A  0.00  7A    0.00     0.00   ...   NN              SN
E2F  351.55Y ...

Across one corpus of ~34,000 hy3 files (55.4 million E1 lines) this affects 292 entries in 32 files; small, but each one is a wrong distance on a real swim.

What changes

  • EventEntry gains distance: Optional[float], stroke: Optional[Stroke], course: Optional[Course] and entry_flag: Optional[str] (column 96; observed S/T on split-request entries, blank otherwise). e1_parser and f1_parser populate them from the entry's own line.
  • The entry's distance joins the individual identity in same_swimmer_entry_as, so a split-request entry is never folded into the swimmer's main entry for that event. A prelim + finals re-listing of one swim (same distance) still merges exactly as before.
  • Event is unchanged. Consumers that only read Event.distance see no difference; consumers that want the entry's actual distance read entry.distance.

All new fields default to None, so entries constructed elsewhere keep working.

Tests

  • an entry carries its own distance/stroke/course and no flag on an ordinary line;
  • a split-request E1/E2 pair lands as a second entry at its own distance with the S flag, while the event keeps the distance it was created with;
  • prelim + finals of one swim still merge into one entry;
  • a combined-distance event keeps each entry's distance.

Existing suite: 129 passed.

…96 flag

An Event is keyed by event number alone, so when one number carries more
than one distance the Event holds only the first distance seen and every
later entry loses its own. Two real export shapes do this:

- a combined-distance event, where swimmers in one event number choose
  between distances (400 or 500, 1000 or 1650, 25 or 100); and
- a split-request entry: Meet Manager records an intermediate split as its
  own official time by writing a second E1 for the same event number with
  the shorter distance, fee 0.00, seed 0.00 and an "S" (sometimes "T") in
  column 96, followed by an E2 carrying the split time.

EventEntry now carries `distance`, `stroke`, `course` and `entry_flag`
read from its own E1/F1 line, and the entry's distance joins the
same-swimmer identity so a split-request entry is never folded into the
swimmer's main entry for that event (prelim + finals of one swim still
merge as before). Event fields are unchanged; consumers that only read
Event.distance see no difference.
The G1 split index is a two-character field and wraps at 100. A swim with
more than 49 split slots -- a 1500 LCM or 1650 SCY recorded every 25 --
continues "...F96 ... F00 ... F04 ..." on the next G1 line; read literally,
the wrapped indexes (0, 4, 8, ...) collide with the early ones and overwrite
them, so such a swim kept 13 of its 30 splits and its finish landed under
key 20. Indexes are monotonic within an entry, so a value at or below the
highest already seen for that slot is taken as wrapped and advanced by 100.
Swims that never reach index 100 are unaffected.
@fsalum

fsalum commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a second commit, 1536479: the G1 split index is a two-character field and wraps at 100, so a swim recorded every 25 over 1500 m / 1650 yd (more than 49 slots) had its wrapped indexes collide with and overwrite the early ones — such a swim kept 13 of 30 splits. Indexes are monotonic within an entry, so a value at or below the highest already seen is advanced by 100. Two tests added (the wrapped shape recovers all 30; an unwrapped swim is unchanged). Suite: 131 passed.

@egelja

egelja commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Is a "combined distance event" one where prelims are SCY and finals LCM (or similar)? If that happens, is the event flag set?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants