lenex-parser 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +21 -0
- data/.yardopts +2 -0
- data/LICENSE +21 -0
- data/README.md +796 -0
- data/Rakefile +43 -0
- data/bin/console +8 -0
- data/bin/setup +5 -0
- data/lenex-parser.gemspec +35 -0
- data/lib/lenex/document/serializer.rb +191 -0
- data/lib/lenex/document.rb +163 -0
- data/lib/lenex/parser/objects/age_date.rb +53 -0
- data/lib/lenex/parser/objects/age_group.rb +86 -0
- data/lib/lenex/parser/objects/athlete.rb +93 -0
- data/lib/lenex/parser/objects/bank.rb +56 -0
- data/lib/lenex/parser/objects/club.rb +101 -0
- data/lib/lenex/parser/objects/constructor.rb +51 -0
- data/lib/lenex/parser/objects/contact.rb +55 -0
- data/lib/lenex/parser/objects/entry.rb +70 -0
- data/lib/lenex/parser/objects/entry_schedule.rb +40 -0
- data/lib/lenex/parser/objects/event.rb +114 -0
- data/lib/lenex/parser/objects/facility.rb +58 -0
- data/lib/lenex/parser/objects/fee.rb +54 -0
- data/lib/lenex/parser/objects/fee_schedule.rb +26 -0
- data/lib/lenex/parser/objects/handicap.rb +86 -0
- data/lib/lenex/parser/objects/heat.rb +58 -0
- data/lib/lenex/parser/objects/host_club.rb +34 -0
- data/lib/lenex/parser/objects/judge.rb +55 -0
- data/lib/lenex/parser/objects/lenex.rb +72 -0
- data/lib/lenex/parser/objects/meet.rb +175 -0
- data/lib/lenex/parser/objects/meet_info.rb +60 -0
- data/lib/lenex/parser/objects/official.rb +70 -0
- data/lib/lenex/parser/objects/organizer.rb +34 -0
- data/lib/lenex/parser/objects/point_table.rb +54 -0
- data/lib/lenex/parser/objects/pool.rb +44 -0
- data/lib/lenex/parser/objects/qualify.rb +55 -0
- data/lib/lenex/parser/objects/ranking.rb +54 -0
- data/lib/lenex/parser/objects/record.rb +107 -0
- data/lib/lenex/parser/objects/record_athlete.rb +92 -0
- data/lib/lenex/parser/objects/record_list.rb +106 -0
- data/lib/lenex/parser/objects/record_relay.rb +62 -0
- data/lib/lenex/parser/objects/record_relay_position.rb +62 -0
- data/lib/lenex/parser/objects/relay.rb +93 -0
- data/lib/lenex/parser/objects/relay_entry.rb +81 -0
- data/lib/lenex/parser/objects/relay_position.rb +74 -0
- data/lib/lenex/parser/objects/relay_result.rb +85 -0
- data/lib/lenex/parser/objects/result.rb +76 -0
- data/lib/lenex/parser/objects/session.rb +107 -0
- data/lib/lenex/parser/objects/split.rb +53 -0
- data/lib/lenex/parser/objects/swim_style.rb +58 -0
- data/lib/lenex/parser/objects/time_standard.rb +55 -0
- data/lib/lenex/parser/objects/time_standard_list.rb +98 -0
- data/lib/lenex/parser/objects/time_standard_ref.rb +63 -0
- data/lib/lenex/parser/objects.rb +52 -0
- data/lib/lenex/parser/sax/document_handler.rb +184 -0
- data/lib/lenex/parser/version.rb +8 -0
- data/lib/lenex/parser/zip_source.rb +111 -0
- data/lib/lenex/parser.rb +184 -0
- data/lib/lenex-parser.rb +16 -0
- metadata +132 -0
data/README.md
ADDED
|
@@ -0,0 +1,796 @@
|
|
|
1
|
+
# Lenex Parser
|
|
2
|
+
|
|
3
|
+
Lenex Parser is a streaming Lenex 3 parser built on Nokogiri's SAX interface. It incrementally assembles the object graph without materialising the full DOM, keeping memory usage low even for multi-megabyte swim meet exports.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'lenex-parser'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
bundle install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install it yourself as:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
gem install lenex-parser
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Loading the library
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
# Load the entire gem (parser, document builder, and value objects)
|
|
31
|
+
require 'lenex-parser'
|
|
32
|
+
|
|
33
|
+
# Load only the streaming parser API
|
|
34
|
+
require 'lenex/parser'
|
|
35
|
+
|
|
36
|
+
# Load just the document builder and value objects for manual construction flows
|
|
37
|
+
require 'lenex/document'
|
|
38
|
+
require 'lenex/parser/objects'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Requiring `lenex-parser` gives you access to the streaming parser, `Lenex::Document`, and all of the value objects used in the builder. The rest of the examples assume you have loaded the gem this way. If you prefer finer-grained requires, use the targeted options shown above.
|
|
42
|
+
|
|
43
|
+
### Parsing Lenex XML
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
require 'lenex-parser'
|
|
47
|
+
|
|
48
|
+
xml = File.read('meet.lenex')
|
|
49
|
+
|
|
50
|
+
lenex = Lenex::Parser.parse(xml)
|
|
51
|
+
|
|
52
|
+
puts "Lenex version: #{lenex.version}"
|
|
53
|
+
puts "Revision: #{lenex.revision}"
|
|
54
|
+
puts "Built by: #{lenex.constructor.name} (#{lenex.constructor.version})"
|
|
55
|
+
puts "Contact email: #{lenex.constructor.contact.email}"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`Lenex::Parser.parse` accepts any IO-like object (such as a `File` opened in binary mode) or a raw XML string. When given an IO it reads chunk-by-chunk, emitting SAX events into the builder so the full XML tree is never loaded at once. You can also hand it a filesystem path (as a `String` or `Pathname`) and the parser will open the file in binary mode for you before streaming. Strings that contain XML or ZIP bytes are always treated as in-memory payloads, even if a file with the same name exists on disk.
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
# Parse directly from a file path or Pathname
|
|
62
|
+
require 'pathname'
|
|
63
|
+
|
|
64
|
+
lenex = Lenex::Parser.parse('meet.lenex')
|
|
65
|
+
lenex = Lenex::Parser.parse(Pathname.new('meet.lenex.zip'))
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### Traversing deeply nested data
|
|
69
|
+
|
|
70
|
+
The parser returns a `Lenex::Parser::Objects::Lenex` instance whose child
|
|
71
|
+
collections expose plain Ruby arrays. You can use familiar Enumerable helpers to
|
|
72
|
+
drill into the object graph and extract the information you need—even when it
|
|
73
|
+
lives several levels deep in the document.
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
lenex = Lenex::Parser.parse('meet.lenex')
|
|
77
|
+
|
|
78
|
+
# Grab a specific session by number and inspect one of its events.
|
|
79
|
+
first_meet = lenex.meets.first
|
|
80
|
+
session_one = first_meet.sessions.detect { |session| session.number == '1' }
|
|
81
|
+
first_event = session_one.events.first
|
|
82
|
+
|
|
83
|
+
puts "Event ##{first_event.number} uses #{first_event.swim_style.stroke}"
|
|
84
|
+
|
|
85
|
+
# Walk from the meet down to a particular athlete entry.
|
|
86
|
+
clubs = first_meet.clubs
|
|
87
|
+
sprinter = clubs.flat_map(&:athletes).detect { |athlete| athlete.last_name == 'Phelps' }
|
|
88
|
+
entry = sprinter.entries.detect { |e| e.event_id == first_event.event_id }
|
|
89
|
+
|
|
90
|
+
puts "Lane #{entry.lane} entry time: #{entry.entry_time}"
|
|
91
|
+
|
|
92
|
+
# Pull the same athlete's official result if it exists.
|
|
93
|
+
result = sprinter.results.find { |r| r.event_id == first_event.event_id }
|
|
94
|
+
puts "Final time: #{result&.swim_time || 'not recorded'}"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Every object provides reader methods that mirror the Lenex schema. For example,
|
|
98
|
+
`Lenex::Parser::Objects::Club#athletes` returns an array of
|
|
99
|
+
`Lenex::Parser::Objects::Athlete`, and each athlete exposes `entries`, `results`,
|
|
100
|
+
and `handicap`. The nested arrays are regular Ruby collections, so idioms such
|
|
101
|
+
as `flat_map`, `detect`, or `group_by` work out of the box.
|
|
102
|
+
|
|
103
|
+
### Building documents incrementally
|
|
104
|
+
|
|
105
|
+
The gem also exposes a lightweight `Lenex::Document` model for callers that need to build Lenex payloads programmatically before exporting them. The class mirrors the `<LENEX>` root element and provides helpers for accumulating constructor metadata as well as meet, record list, and time-standard list entries.
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
require 'lenex/document'
|
|
109
|
+
require 'lenex/parser/objects'
|
|
110
|
+
|
|
111
|
+
document = Lenex::Document.new
|
|
112
|
+
|
|
113
|
+
document.constructor = Lenex::Parser::Objects::Constructor.new(
|
|
114
|
+
name: 'LENEX Builder',
|
|
115
|
+
registration: 'Example Org',
|
|
116
|
+
version: '1.2.3',
|
|
117
|
+
contact: Lenex::Parser::Objects::Contact.new(email: 'support@example.com')
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
meet = Lenex::Parser::Objects::Meet.new(
|
|
121
|
+
name: 'City Championships',
|
|
122
|
+
city: 'Berlin',
|
|
123
|
+
nation: 'GER'
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
document.add_meet(meet)
|
|
127
|
+
|
|
128
|
+
document.record_lists # => []
|
|
129
|
+
document.time_standard_lists # => []
|
|
130
|
+
|
|
131
|
+
# Export the document to Lenex XML
|
|
132
|
+
xml = document.to_xml
|
|
133
|
+
|
|
134
|
+
File.write('export.lenex', xml)
|
|
135
|
+
|
|
136
|
+
# See examples/build_and_export_document.rb for a complete script that
|
|
137
|
+
# assembles meets, record lists, and time standards before exporting.
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
If you have already required `lenex-parser`, the document builder and object model are loaded and you can omit the more granular requires shown above. `Lenex::Document::ConstructorMetadata` normalizes all keys to symbols so you can pass either strings or symbols when writing attributes (e.g., `constructor['contact'] = contact_details`). Each helper method returns the object you passed in, making it easy to chain builder flows.
|
|
141
|
+
|
|
142
|
+
#### Building a larger document
|
|
143
|
+
|
|
144
|
+
The value objects under `Lenex::Parser::Objects` accept keyword arguments that
|
|
145
|
+
mirror their XML attributes. You can compose them to build fully fledged Lenex
|
|
146
|
+
payloads before streaming them back out of your application. The following
|
|
147
|
+
example assembles a meet with one session, one event, and a single athlete
|
|
148
|
+
entry.
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
require 'lenex/document'
|
|
152
|
+
require 'lenex/parser/objects'
|
|
153
|
+
require 'nokogiri'
|
|
154
|
+
|
|
155
|
+
document = Lenex::Document.new(version: '3.0', revision: '2024.1')
|
|
156
|
+
|
|
157
|
+
contact = Lenex::Parser::Objects::Contact.new(
|
|
158
|
+
name: 'Jane Doe',
|
|
159
|
+
email: 'jane.doe@example.com',
|
|
160
|
+
phone: '+49 30 1234567'
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
constructor = Lenex::Parser::Objects::Constructor.new(
|
|
164
|
+
name: 'My Meet Manager',
|
|
165
|
+
registration: 'City Aquatics',
|
|
166
|
+
version: '2.5.0',
|
|
167
|
+
contact: contact
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
document.constructor = constructor
|
|
171
|
+
|
|
172
|
+
swim_style = Lenex::Parser::Objects::SwimStyle.new(
|
|
173
|
+
distance: '100',
|
|
174
|
+
relay_count: '1',
|
|
175
|
+
stroke: 'FREE'
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
event = Lenex::Parser::Objects::Event.new(
|
|
179
|
+
event_id: 'E1',
|
|
180
|
+
number: '1',
|
|
181
|
+
round: 'PRE',
|
|
182
|
+
swim_style: swim_style
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
session = Lenex::Parser::Objects::Session.new(
|
|
186
|
+
number: '1',
|
|
187
|
+
date: '2024-05-18',
|
|
188
|
+
name: 'Morning Heats',
|
|
189
|
+
events: [event]
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
athlete = Lenex::Parser::Objects::Athlete.new(
|
|
193
|
+
athlete_id: 'A1',
|
|
194
|
+
first_name: 'Lena',
|
|
195
|
+
last_name: 'Schmidt',
|
|
196
|
+
gender: 'F',
|
|
197
|
+
birthdate: '2006-02-14',
|
|
198
|
+
entries: [
|
|
199
|
+
Lenex::Parser::Objects::Entry.new(
|
|
200
|
+
event_id: event.event_id,
|
|
201
|
+
entry_time: '00:57.34',
|
|
202
|
+
lane: '4'
|
|
203
|
+
)
|
|
204
|
+
]
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
club = Lenex::Parser::Objects::Club.new(
|
|
208
|
+
name: 'City Aquatics',
|
|
209
|
+
nation: 'GER',
|
|
210
|
+
athletes: [athlete]
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
meet = Lenex::Parser::Objects::Meet.new(
|
|
214
|
+
name: 'City Championships',
|
|
215
|
+
city: 'Berlin',
|
|
216
|
+
nation: 'GER',
|
|
217
|
+
sessions: [session],
|
|
218
|
+
clubs: [club]
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
document.add_meet(meet)
|
|
222
|
+
|
|
223
|
+
lenex = document.build_lenex
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
At this point `lenex` is a `Lenex::Parser::Objects::Lenex` instance populated
|
|
227
|
+
with your meet, ready to be serialised or further enriched.
|
|
228
|
+
|
|
229
|
+
#### Exporting to XML and saving to disk
|
|
230
|
+
|
|
231
|
+
The gem focuses on parsing and provides the document builder for convenience;
|
|
232
|
+
it does not ship with a dedicated serializer. Because the value objects expose
|
|
233
|
+
plain Ruby readers, you can use `Nokogiri::XML::Builder` (already a dependency
|
|
234
|
+
of the gem) to convert the object graph back into Lenex XML and write it to
|
|
235
|
+
disk:
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
lenex = document.build_lenex
|
|
239
|
+
|
|
240
|
+
xml = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |builder|
|
|
241
|
+
builder.LENEX(version: lenex.version, revision: lenex.revision) do
|
|
242
|
+
builder.CONSTRUCTOR(name: lenex.constructor.name,
|
|
243
|
+
registration: lenex.constructor.registration,
|
|
244
|
+
version: lenex.constructor.version) do
|
|
245
|
+
builder.CONTACT(email: lenex.constructor.contact.email)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
builder.MEETS do
|
|
249
|
+
lenex.meets.each do |m|
|
|
250
|
+
builder.MEET(name: m.name, city: m.city, nation: m.nation) do
|
|
251
|
+
builder.SESSIONS do
|
|
252
|
+
m.sessions.each do |s|
|
|
253
|
+
builder.SESSION(number: s.number, date: s.date) do
|
|
254
|
+
builder.EVENTS do
|
|
255
|
+
s.events.each do |e|
|
|
256
|
+
builder.EVENT(eventid: e.event_id, number: e.number) do
|
|
257
|
+
style = e.swim_style
|
|
258
|
+
builder.SWIMSTYLE(distance: style.distance,
|
|
259
|
+
relaycount: style.relay_count,
|
|
260
|
+
stroke: style.stroke)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
builder.CLUBS do
|
|
269
|
+
m.clubs.each do |club|
|
|
270
|
+
builder.CLUB(name: club.name, nation: club.nation) do
|
|
271
|
+
builder.ATHLETES do
|
|
272
|
+
club.athletes.each do |athlete|
|
|
273
|
+
builder.ATHLETE(athleteid: athlete.athlete_id,
|
|
274
|
+
firstname: athlete.first_name,
|
|
275
|
+
lastname: athlete.last_name,
|
|
276
|
+
gender: athlete.gender,
|
|
277
|
+
birthdate: athlete.birthdate) do
|
|
278
|
+
builder.ENTRIES do
|
|
279
|
+
athlete.entries.each do |entry|
|
|
280
|
+
builder.ENTRY(eventid: entry.event_id,
|
|
281
|
+
entrytime: entry.entry_time,
|
|
282
|
+
lane: entry.lane)
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end.to_xml
|
|
296
|
+
|
|
297
|
+
File.binwrite('city-championships.lenex', xml)
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Feel free to expand the builder logic with the additional optional attributes
|
|
301
|
+
your workflow requires. Because all nested collections are plain arrays, you can
|
|
302
|
+
reuse the same patterns shown in the traversal examples to iterate over record
|
|
303
|
+
lists, time standards, relay teams, or any other Lenex section you need to
|
|
304
|
+
render.
|
|
305
|
+
If you have already required `lenex-parser`, the document builder and object model are loaded and you can omit the more granular requires shown above. `Lenex::Document::ConstructorMetadata` normalizes all keys to symbols so you can inspect parsed metadata prior to replacing it with a full `Lenex::Parser::Objects::Constructor`. When exporting, assign a constructor object as shown above to satisfy the Lenex schema requirements. Each helper method returns the object you passed in, making it easy to chain builder flows.
|
|
306
|
+
### Parsing zipped Lenex files
|
|
307
|
+
|
|
308
|
+
`Lenex::Parser.parse` also recognises ZIP archives that contain a `.lef` or `.xml` payload and automatically extracts the first matching file. This makes it easy to work with the compressed exports that many federation systems produce:
|
|
309
|
+
|
|
310
|
+
```ruby
|
|
311
|
+
require 'lenex/parser'
|
|
312
|
+
require 'lenex/document'
|
|
313
|
+
|
|
314
|
+
zip_data = File.binread('meet.lenex.zip')
|
|
315
|
+
|
|
316
|
+
lenex = Lenex::Parser.parse(zip_data)
|
|
317
|
+
puts lenex.constructor.name
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
`zip_data` can come from anywhere—an HTTP response body, a database blob, or any other in-memory string. The parser inspects the leading bytes to decide whether to unzip or stream the XML directly, so no extra branching is required at the call site.
|
|
321
|
+
|
|
322
|
+
The parser lazily loads the optional `rubyzip` dependency the first time a ZIP archive is encountered. Install it ahead of time with `gem install rubyzip` (or add it to your Gemfile) to keep parsing seamless in production environments.
|
|
323
|
+
|
|
324
|
+
### Example scripts
|
|
325
|
+
|
|
326
|
+
Run `bundle exec ruby examples/builder_and_parser.rb` to see a standalone script that constructs a `Lenex::Document` and parses a minimal Lenex XML payload. The script lives in the `examples` directory alongside a README that describes how to run it from a checked-out repository.
|
|
327
|
+
|
|
328
|
+
### Object model overview
|
|
329
|
+
|
|
330
|
+
The parser returns a `Lenex::Parser::Objects::Lenex` instance that exposes the top-level metadata of the Lenex file:
|
|
331
|
+
|
|
332
|
+
- `version` – Lenex schema version string declared in the `<LENEX>` root element.
|
|
333
|
+
- `revision` – Revision identifier provided by the source system.
|
|
334
|
+
- `constructor` – A `Lenex::Parser::Objects::Constructor` with information about who produced the file.
|
|
335
|
+
- `meets` – Array of `Lenex::Parser::Objects::Meet` describing meet level information found under `<MEETS>`.
|
|
336
|
+
- `record_lists` – Array of `Lenex::Parser::Objects::RecordList` objects representing the `<RECORDLISTS>` section when present.
|
|
337
|
+
- `time_standard_lists` – Array of `Lenex::Parser::Objects::TimeStandardList` objects representing `<TIMESTANDARDLISTS>` when supplied.
|
|
338
|
+
|
|
339
|
+
The constructor object provides these accessors:
|
|
340
|
+
|
|
341
|
+
- `name` – Application or organisation name responsible for generating the export.
|
|
342
|
+
- `registration` – Registration number reported in the `<CONSTRUCTOR>` element.
|
|
343
|
+
- `version` – Constructor application version string.
|
|
344
|
+
- `contact` – A `Lenex::Parser::Objects::Contact` containing communication details for the file creator.
|
|
345
|
+
|
|
346
|
+
The contact object yields:
|
|
347
|
+
|
|
348
|
+
- `email` – Email address for follow-up questions.
|
|
349
|
+
- `phone` – Optional phone number if available.
|
|
350
|
+
- `fax` – Optional fax number.
|
|
351
|
+
- `name` – Contact person's full name when supplied.
|
|
352
|
+
|
|
353
|
+
The meet object exposes:
|
|
354
|
+
|
|
355
|
+
- `name` – Required meet name taken from the `<MEET>` element.
|
|
356
|
+
- `name_en` – Optional English representation of the meet name.
|
|
357
|
+
- `city` – Required meet city name.
|
|
358
|
+
- `city_en` – Optional English representation of the meet city.
|
|
359
|
+
- `nation` – Required meet nation code.
|
|
360
|
+
- `course` – Optional course attribute describing the pool length.
|
|
361
|
+
- `entry_type` – Optional classification describing whether the meet accepts open or invitation-only entries.
|
|
362
|
+
- `max_entries_athlete` – Optional limit on individual entries per athlete for the entire meet.
|
|
363
|
+
- `max_entries_relay` – Optional limit on relay entries per club for the entire meet.
|
|
364
|
+
- `reserve_count` – Optional number of reserve swimmers tracked for finals.
|
|
365
|
+
- `start_method` – Optional start method flag (`1` for one-start, `2` for two-start procedures).
|
|
366
|
+
- `timing` – Optional timing system information recorded at the meet level.
|
|
367
|
+
- `touchpad_mode` – Optional description of the touchpad installation.
|
|
368
|
+
- `type` – Optional meet classification supplied by the federation.
|
|
369
|
+
- `altitude` – Optional venue altitude in metres above sea level.
|
|
370
|
+
- `swrid` – Optional SwimRankings.net identifier for the meet.
|
|
371
|
+
- `result_url` – Optional URL pointing to published meet results.
|
|
372
|
+
- `contact` – Optional `Lenex::Parser::Objects::Contact` for the meet organiser when provided.
|
|
373
|
+
- `age_date` – Optional `Lenex::Parser::Objects::AgeDate` describing how to calculate athlete ages for the meet.
|
|
374
|
+
- `bank` – Optional `Lenex::Parser::Objects::Bank` containing payment instructions for entry fees.
|
|
375
|
+
- `facility` – Optional `Lenex::Parser::Objects::Facility` describing the venue address.
|
|
376
|
+
- `point_table` – Optional `Lenex::Parser::Objects::PointTable` identifying the scoring system in use.
|
|
377
|
+
- `qualify` – Optional `Lenex::Parser::Objects::Qualify` outlining qualification period and conversion rules.
|
|
378
|
+
- `pool` – Optional `Lenex::Parser::Objects::Pool` describing lane configuration when the meet defines a default pool.
|
|
379
|
+
- `fee_schedule` – Optional `Lenex::Parser::Objects::FeeSchedule` containing global meet fee definitions.
|
|
380
|
+
- `host_club` – Optional `Lenex::Parser::Objects::HostClub` with information about the executing organisation.
|
|
381
|
+
- `organizer` – Optional `Lenex::Parser::Objects::Organizer` describing the promoting body.
|
|
382
|
+
- `entry_schedule` – Optional `Lenex::Parser::Objects::EntrySchedule` capturing entry start dates, deadlines, and withdrawal cut-offs.
|
|
383
|
+
- `clubs` – Array of `Lenex::Parser::Objects::Club` objects describing participating clubs.
|
|
384
|
+
- `sessions` – Array of `Lenex::Parser::Objects::Session` objects capturing the meet schedule.
|
|
385
|
+
|
|
386
|
+
The age date object exposes:
|
|
387
|
+
|
|
388
|
+
- `type` – Required strategy for calculating ages (e.g., `YEAR`, `DATE`).
|
|
389
|
+
- `value` – Optional reference date when the calculation requires a specific day.
|
|
390
|
+
|
|
391
|
+
The bank object exposes:
|
|
392
|
+
|
|
393
|
+
- `account_holder` – Optional name attached to the bank account.
|
|
394
|
+
- `bic` – Optional bank identifier code.
|
|
395
|
+
- `iban` – Required IBAN for the receiving account.
|
|
396
|
+
- `name` – Optional bank name.
|
|
397
|
+
- `note` – Optional payment note or reference instructions.
|
|
398
|
+
|
|
399
|
+
The facility object exposes:
|
|
400
|
+
|
|
401
|
+
- `city` – Required city containing the venue.
|
|
402
|
+
- `nation` – Required nation code for the facility location.
|
|
403
|
+
- `name` – Optional display name of the venue.
|
|
404
|
+
- `state` – Optional state, province, or region for the venue.
|
|
405
|
+
- `street` / `street2` – Optional address lines.
|
|
406
|
+
- `zip` – Optional postal code for the facility.
|
|
407
|
+
|
|
408
|
+
The point table object exposes:
|
|
409
|
+
|
|
410
|
+
- `name` – Required name of the scoring system.
|
|
411
|
+
- `point_table_id` – Optional identifier for well-known point tables.
|
|
412
|
+
- `version` – Required edition or year of the scoring system.
|
|
413
|
+
|
|
414
|
+
The qualify object exposes:
|
|
415
|
+
|
|
416
|
+
- `conversion` – Optional conversion method applied to entry times.
|
|
417
|
+
- `from` – Required start date of the qualification window.
|
|
418
|
+
- `percent` – Optional percentage used when conversion requires it.
|
|
419
|
+
- `until` – Optional end date of the qualification window.
|
|
420
|
+
|
|
421
|
+
The host club object exposes:
|
|
422
|
+
|
|
423
|
+
- `name` – Host club name responsible for executing the meet.
|
|
424
|
+
- `url` – Optional URL pointing to the host club's website.
|
|
425
|
+
|
|
426
|
+
The organizer object exposes:
|
|
427
|
+
|
|
428
|
+
- `name` – Organization that promotes the meet.
|
|
429
|
+
- `url` – Optional URL with more details about the organizer.
|
|
430
|
+
|
|
431
|
+
The entry schedule object exposes:
|
|
432
|
+
|
|
433
|
+
- `entry_start_date` – Optional date when entries open.
|
|
434
|
+
- `withdraw_until` – Optional date by which withdrawals must be submitted.
|
|
435
|
+
- `deadline_date` – Optional entry deadline date.
|
|
436
|
+
- `deadline_time` – Optional entry deadline time.
|
|
437
|
+
|
|
438
|
+
The club object exposes:
|
|
439
|
+
|
|
440
|
+
- `name` – Full club name when provided (required unless the club type is `UNATTACHED`).
|
|
441
|
+
- `name_en` – Optional English representation of the club name.
|
|
442
|
+
- `shortname` / `shortname_en` – Optional abbreviated names for local and English contexts.
|
|
443
|
+
- `code` – Optional national federation club code.
|
|
444
|
+
- `nation` – Optional federation nation code for the club.
|
|
445
|
+
- `number` – Optional differentiator used when a club fields multiple teams.
|
|
446
|
+
- `region` – Optional code for the regional swimming committee.
|
|
447
|
+
- `swrid` – Optional SwimRankings.net identifier.
|
|
448
|
+
- `type` – Optional classification such as `CLUB`, `NATIONALTEAM`, `REGIONALTEAM`, or `UNATTACHED`.
|
|
449
|
+
- `contact` – Optional `Lenex::Parser::Objects::Contact` with meet-specific club contact details.
|
|
450
|
+
|
|
451
|
+
The session object exposes:
|
|
452
|
+
|
|
453
|
+
- `number` – Required session number unique within a meet.
|
|
454
|
+
- `date` – Required session date in `YYYY-MM-DD` format.
|
|
455
|
+
- `course` – Optional pool length overriding the meet-wide course.
|
|
456
|
+
- `daytime` – Optional start time for the session.
|
|
457
|
+
- `endtime` – Optional time the session finished.
|
|
458
|
+
- `fee_schedule` – Optional `Lenex::Parser::Objects::FeeSchedule` containing session-specific fee overrides.
|
|
459
|
+
- `max_entries_athlete` – Optional limit on individual entries per athlete for the session.
|
|
460
|
+
- `max_entries_relay` – Optional limit on relay entries per club for the session.
|
|
461
|
+
- `name` – Optional descriptive session name (e.g., "Day 1 – Prelims").
|
|
462
|
+
- `official_meeting` – Optional meeting time for officials.
|
|
463
|
+
- `remarks_judge` – Optional referee remarks.
|
|
464
|
+
- `team_leader_meeting` – Optional meeting time for team leaders.
|
|
465
|
+
- `timing` – Optional timing system information for the session.
|
|
466
|
+
- `touchpad_mode` – Optional touchpad mode description.
|
|
467
|
+
- `warmup_from` / `warmup_until` – Optional warm-up window times.
|
|
468
|
+
- `pool` – Optional `Lenex::Parser::Objects::Pool` describing the lane configuration and environment of the competition pool.
|
|
469
|
+
- `judges` – Array of `Lenex::Parser::Objects::Judge` objects covering the meet officials attached to the session.
|
|
470
|
+
- `events` – Array of `Lenex::Parser::Objects::Event` objects with the events contested in the session.
|
|
471
|
+
|
|
472
|
+
The event object exposes:
|
|
473
|
+
|
|
474
|
+
- `event_id` – Required identifier unique across all events in a meet (sourced from the `eventid` attribute).
|
|
475
|
+
- `number` – Required event number within the meet program.
|
|
476
|
+
- `gender` – Optional gender designator (`A`, `M`, `F`, or `X`).
|
|
477
|
+
- `round` – Optional round identifier such as `PRE`, `SEM`, or `FIN`.
|
|
478
|
+
- `daytime` – Optional scheduled start time for the event.
|
|
479
|
+
- `max_entries` – Optional maximum number of entries per club for the event.
|
|
480
|
+
- `order` – Optional event order overriding the numeric sequence when necessary.
|
|
481
|
+
- `previous_event_id` – Optional identifier of the preceding round for finals progression.
|
|
482
|
+
- `run` – Optional swim-off run counter.
|
|
483
|
+
- `timing` – Optional timing type overriding the session defaults.
|
|
484
|
+
- `type` – Optional event classification (e.g., `MASTERS`).
|
|
485
|
+
- `fee` – Optional `Lenex::Parser::Objects::Fee` representing the event specific entry fee.
|
|
486
|
+
- `swim_style` – `Lenex::Parser::Objects::SwimStyle` describing the stroke, distance, and relay composition of the event.
|
|
487
|
+
- `age_groups` – Array of `Lenex::Parser::Objects::AgeGroup` objects defining eligible age ranges.
|
|
488
|
+
- `heats` – Array of `Lenex::Parser::Objects::Heat` objects describing detailed start lists.
|
|
489
|
+
- `time_standard_refs` – Array of `Lenex::Parser::Objects::TimeStandardRef` objects referencing applicable time standard lists and optional fines.
|
|
490
|
+
|
|
491
|
+
The heat object exposes:
|
|
492
|
+
|
|
493
|
+
- `heat_id` – Required identifier unique across all heats within a meet (from the `heatid` attribute).
|
|
494
|
+
- `number` – Required heat number unique within an event.
|
|
495
|
+
- `age_group_id` – Optional reference to an age group that the heat belongs to.
|
|
496
|
+
- `daytime` – Optional scheduled start time for the heat.
|
|
497
|
+
- `final` – Optional final designator (`A`, `B`, `C`, or `D`).
|
|
498
|
+
- `order` – Optional order override when heats do not run sequentially.
|
|
499
|
+
- `status` – Optional heat status such as `SCHEDULED`, `SEEDED`, `INOFFICIAL`, or `OFFICIAL`.
|
|
500
|
+
|
|
501
|
+
The age group object exposes:
|
|
502
|
+
|
|
503
|
+
- `age_group_id` – Required identifier unique within the event, referenced by entries.
|
|
504
|
+
- `age_max` – Required upper bound of the age range (`-1` indicates no upper bound).
|
|
505
|
+
- `age_min` – Required lower bound of the age range (`-1` indicates no lower bound).
|
|
506
|
+
- `calculate` – Optional calculation mode for relay totals (`SINGLE` or `TOTAL`).
|
|
507
|
+
- `gender` – Optional gender limitation for the age group (`A`, `M`, `F`, or `X`).
|
|
508
|
+
- `handicap` – Optional para-swimming handicap class grouping.
|
|
509
|
+
- `level_max` / `level_min` – Optional bounds restricting athlete levels.
|
|
510
|
+
- `levels` – Optional comma-separated list of explicitly allowed athlete levels.
|
|
511
|
+
- `name` – Optional display name for the age group (e.g., "Juniors").
|
|
512
|
+
- `rankings` – Array of `Lenex::Parser::Objects::Ranking` objects capturing the final placements for the age group within the event.
|
|
513
|
+
|
|
514
|
+
The swim style object exposes:
|
|
515
|
+
|
|
516
|
+
- `distance` – Required event distance in meters for each competitor (per-leg distance for relays).
|
|
517
|
+
- `relay_count` – Required number of swimmers per entry (use `1` for individual events).
|
|
518
|
+
- `stroke` – Required stroke enumeration for the event (e.g., `FREE`, `BACK`, `MEDLEY`).
|
|
519
|
+
- `code` – Optional short code to distinguish custom swim styles when the stroke is `UNKNOWN`.
|
|
520
|
+
- `name` – Optional descriptive name for unusual swim styles.
|
|
521
|
+
- `swim_style_id` – Optional identifier to uniquely track special swim styles across the meet.
|
|
522
|
+
- `technique` – Optional technique modifier (e.g., `KICK`, `TURN`) for skill-specific events.
|
|
523
|
+
|
|
524
|
+
The fee object exposes:
|
|
525
|
+
|
|
526
|
+
- `currency` – Optional three-letter currency code describing the fee currency.
|
|
527
|
+
- `type` – Optional fee classification (e.g., `ATHLETE`, `RELAY`, `CLUB`) used in the context of fee collections.
|
|
528
|
+
- `value` – Required monetary value expressed in cents.
|
|
529
|
+
|
|
530
|
+
The fee schedule object exposes:
|
|
531
|
+
|
|
532
|
+
- `fees` – Array of `Lenex::Parser::Objects::Fee` instances contained in the surrounding `<FEES>` collection.
|
|
533
|
+
|
|
534
|
+
The ranking object exposes:
|
|
535
|
+
|
|
536
|
+
- `place` – Required final place within the rankings list.
|
|
537
|
+
- `result_id` – Required identifier referencing the associated result entry.
|
|
538
|
+
- `order` – Optional explicit ordering override for ranking presentation.
|
|
539
|
+
|
|
540
|
+
The pool object exposes:
|
|
541
|
+
|
|
542
|
+
- `lane_min` – Optional first lane number used during the meet or session.
|
|
543
|
+
- `lane_max` – Optional last lane number available for competition.
|
|
544
|
+
- `temperature` – Optional reported water temperature.
|
|
545
|
+
- `type` – Optional venue type (e.g., `INDOOR`, `OUTDOOR`, `LAKE`, `OCEAN`).
|
|
546
|
+
|
|
547
|
+
The judge object exposes:
|
|
548
|
+
|
|
549
|
+
- `official_id` – Required identifier referencing the official in the meet's official list.
|
|
550
|
+
- `number` – Optional sequencing or lane assignment for the judge.
|
|
551
|
+
- `role` – Optional role descriptor reflecting the official's duties (e.g., `REF`, `TIK`).
|
|
552
|
+
- `remarks` – Optional free-form remarks about the assignment.
|
|
553
|
+
|
|
554
|
+
The time standard reference object exposes:
|
|
555
|
+
|
|
556
|
+
- `time_standard_list_id` – Required identifier pointing to the referenced time standard list.
|
|
557
|
+
- `marker` – Optional string used to annotate results that met or missed the referenced time standard.
|
|
558
|
+
- `fee` – Optional `Lenex::Parser::Objects::Fee` describing fines or penalties linked to the time standard reference.
|
|
559
|
+
|
|
560
|
+
The athlete object exposes:
|
|
561
|
+
|
|
562
|
+
- `athlete_id` – Required identifier unique to the athlete within the meet.
|
|
563
|
+
- `birthdate` – Required birth date of the athlete in `YYYY-MM-DD` format.
|
|
564
|
+
- `first_name` / `first_name_en` – Required first name and optional English variant.
|
|
565
|
+
- `last_name` / `last_name_en` – Required last name and optional English variant.
|
|
566
|
+
- `gender` – Required gender flag (`M` or `F`).
|
|
567
|
+
- `level` – Optional athlete level string.
|
|
568
|
+
- `license` / `license_ipc` – Optional federation and IPC license identifiers.
|
|
569
|
+
- `name_prefix` – Optional surname prefix (e.g., "van den").
|
|
570
|
+
- `nation` – Optional athlete nation code.
|
|
571
|
+
- `passport` – Optional passport number.
|
|
572
|
+
- `status` – Optional status flag such as `ROOKIE`, `FOREIGNER`, or `EXHIBITION`.
|
|
573
|
+
- `swrid` – Optional SwimRankings.net identifier.
|
|
574
|
+
- `handicap` – Optional `Lenex::Parser::Objects::Handicap` detailing para-swimming classifications for the athlete.
|
|
575
|
+
- `entries` – Array of `Lenex::Parser::Objects::Entry` representing the athlete's entries.
|
|
576
|
+
- `results` – Array of `Lenex::Parser::Objects::Result` representing the athlete's results.
|
|
577
|
+
|
|
578
|
+
The entry object exposes:
|
|
579
|
+
|
|
580
|
+
- `event_id` – Required reference to the event the entry belongs to.
|
|
581
|
+
- `entry_time` – Optional entry time string.
|
|
582
|
+
- `status` – Optional status flag such as `SICK` or `WDR`.
|
|
583
|
+
- `lane` – Optional assigned lane number.
|
|
584
|
+
- `heat_id` – Optional reference to the scheduled heat.
|
|
585
|
+
- `age_group_id` – Optional reference to the event age group.
|
|
586
|
+
- `entry_course` – Optional pool length for the entry time.
|
|
587
|
+
- `entry_distance` – Optional entry distance in centimetres for fin-swimming events.
|
|
588
|
+
- `handicap` – Optional para-swimming sport class override.
|
|
589
|
+
- `meet_info` – Optional `Lenex::Parser::Objects::MeetInfo` describing when the entry time was achieved.
|
|
590
|
+
|
|
591
|
+
The handicap object exposes:
|
|
592
|
+
|
|
593
|
+
- `breast` – Required breaststroke sport class (matching SB codes).
|
|
594
|
+
- `breast_status` – Optional confirmation status for the breaststroke class.
|
|
595
|
+
- `exception` – Optional comma-separated exception codes as defined by WPS rules.
|
|
596
|
+
- `free` – Required freestyle/backstroke/fly sport class (matching S codes).
|
|
597
|
+
- `free_status` – Optional confirmation status for the freestyle/backstroke/fly class.
|
|
598
|
+
- `medley` – Required individual medley sport class (matching SM codes).
|
|
599
|
+
- `medley_status` – Optional confirmation status for the individual medley class.
|
|
600
|
+
|
|
601
|
+
The meet info object exposes:
|
|
602
|
+
|
|
603
|
+
- `approved` – Optional approving organisation code (e.g., `AQUA`, `LEN`).
|
|
604
|
+
- `city` / `state` – Optional city and state where the time was achieved.
|
|
605
|
+
- `course` – Optional pool length used for the entry or record.
|
|
606
|
+
- `date` – Optional date when the time was achieved.
|
|
607
|
+
- `daytime` – Optional time of day when the swim occurred.
|
|
608
|
+
- `name` – Optional meet name.
|
|
609
|
+
- `nation` – Optional nation code for the city.
|
|
610
|
+
- `qualification_time` – Optional qualifying time differing from the entry time.
|
|
611
|
+
- `timing` – Optional timing system used for the swim.
|
|
612
|
+
- `pool` – Optional `Lenex::Parser::Objects::Pool` describing the pool where the time was achieved.
|
|
613
|
+
|
|
614
|
+
The result object exposes:
|
|
615
|
+
|
|
616
|
+
- `result_id` – Required identifier unique to the result within the meet.
|
|
617
|
+
- `swim_time` – Required final swim time string or `NT`.
|
|
618
|
+
- `status` – Optional status flag such as `DSQ`, `DNS`, or `EXH`.
|
|
619
|
+
- `comment` – Optional free-text comment (e.g., new record remarks).
|
|
620
|
+
- `event_id` – Optional reference to the event.
|
|
621
|
+
- `heat_id` – Optional reference to the heat.
|
|
622
|
+
- `lane` – Optional lane number.
|
|
623
|
+
- `points` – Optional points scored for the swim.
|
|
624
|
+
- `reaction_time` – Optional start reaction time for the swim.
|
|
625
|
+
- `handicap` – Optional para-swimming sport class override.
|
|
626
|
+
- `swim_distance` – Optional distance in centimetres for fin-swimming events.
|
|
627
|
+
- `splits` – Array of `Lenex::Parser::Objects::Split` describing split times.
|
|
628
|
+
|
|
629
|
+
The split object exposes:
|
|
630
|
+
|
|
631
|
+
- `distance` – Required split distance in meters.
|
|
632
|
+
- `swim_time` – Required split time for the distance in swim-time format.
|
|
633
|
+
|
|
634
|
+
The relay object exposes:
|
|
635
|
+
|
|
636
|
+
- `age_max` – Required maximum age for the oldest swimmer on the relay team.
|
|
637
|
+
- `age_min` – Required minimum age for the youngest swimmer on the relay team.
|
|
638
|
+
- `age_total_max` – Required maximum combined age for all swimmers on the team.
|
|
639
|
+
- `age_total_min` – Required minimum combined age for all swimmers on the team.
|
|
640
|
+
- `gender` – Required gender classification for the relay (`M`, `F`, or `X`).
|
|
641
|
+
- `handicap` – Optional para-swimming relay handicap classification.
|
|
642
|
+
- `name` – Optional descriptive team name (e.g., "Mixed Medley A").
|
|
643
|
+
- `number` – Optional team number used when clubs field multiple relays in the same age group.
|
|
644
|
+
- `relay_positions` – Array of `Lenex::Parser::Objects::RelayPosition` describing the swimmers ordered within the relay.
|
|
645
|
+
- `entries` – Array of `Lenex::Parser::Objects::RelayEntry` with the relay's scheduled starts.
|
|
646
|
+
- `results` – Array of `Lenex::Parser::Objects::RelayResult` summarising the relay's outcomes.
|
|
647
|
+
|
|
648
|
+
The relay entry object exposes:
|
|
649
|
+
|
|
650
|
+
- `event_id` – Required reference to the event contested by the relay team.
|
|
651
|
+
- `entry_time` – Optional entry time string for seeding.
|
|
652
|
+
- `status` – Optional status flag describing the relay entry (`EXH`, `RJC`, `SICK`, or `WDR`).
|
|
653
|
+
- `lane` – Optional assigned lane number.
|
|
654
|
+
- `heat_id` – Optional reference to the scheduled heat.
|
|
655
|
+
- `age_group_id` – Optional reference to the event age group.
|
|
656
|
+
- `entry_course` – Optional pool length for the entry time.
|
|
657
|
+
- `entry_distance` – Optional entry distance in centimetres for fin-swimming events.
|
|
658
|
+
- `handicap` – Optional relay sport-class override.
|
|
659
|
+
- `meet_info` – Optional `Lenex::Parser::Objects::MeetInfo` describing where the qualifying swim occurred.
|
|
660
|
+
- `relay_positions` – Array of `Lenex::Parser::Objects::RelayPosition` representing the swimmers declared for the entry.
|
|
661
|
+
|
|
662
|
+
The relay result object exposes:
|
|
663
|
+
|
|
664
|
+
- `result_id` – Required identifier for the relay result within the meet.
|
|
665
|
+
- `swim_time` – Required final relay time string (or `NT`).
|
|
666
|
+
- `status` – Optional status flag such as `DSQ`, `DNS`, `DNF`, `SICK`, `WDR`, or `EXH`.
|
|
667
|
+
- `comment` – Optional free-text comment (e.g., new record notes).
|
|
668
|
+
- `event_id` – Optional reference to the event contested.
|
|
669
|
+
- `heat_id` – Optional reference to the heat.
|
|
670
|
+
- `lane` – Optional lane number.
|
|
671
|
+
- `points` – Optional points earned for the swim.
|
|
672
|
+
- `reaction_time` – Optional reaction time of the lead-off swimmer.
|
|
673
|
+
- `handicap` – Optional relay sport-class override.
|
|
674
|
+
- `swim_distance` – Optional distance in centimetres for fin-swimming events.
|
|
675
|
+
- `splits` – Array of `Lenex::Parser::Objects::Split` objects for the relay's split times.
|
|
676
|
+
- `relay_positions` – Array of `Lenex::Parser::Objects::RelayPosition` representing the swimmers who swam the race.
|
|
677
|
+
|
|
678
|
+
The relay position object exposes:
|
|
679
|
+
|
|
680
|
+
- `athlete_id` – Optional reference to the athlete representing a leg of the relay.
|
|
681
|
+
- `number` – Required leg number (1 for lead-off; `-1` for alternates).
|
|
682
|
+
- `reaction_time` – Optional reaction or takeover time for the leg.
|
|
683
|
+
- `status` – Optional status flag such as `DSQ` or `DNF` for the swimmer.
|
|
684
|
+
- `athlete` – Optional embedded `Lenex::Parser::Objects::Athlete` used when relay swimmers are inlined (e.g., records).
|
|
685
|
+
- `meet_info` – Optional `Lenex::Parser::Objects::MeetInfo` with the qualification details for the swimmer.
|
|
686
|
+
|
|
687
|
+
The official object exposes:
|
|
688
|
+
|
|
689
|
+
- `official_id` – Required identifier unique to the official within the meet.
|
|
690
|
+
- `first_name` – Required first name of the official.
|
|
691
|
+
- `last_name` – Required last name of the official.
|
|
692
|
+
- `gender` – Optional gender marker (`M` or `F`).
|
|
693
|
+
- `grade` – Optional certification grade supplied by the federation.
|
|
694
|
+
- `license` – Optional federation-issued license number.
|
|
695
|
+
- `name_prefix` – Optional surname prefix (e.g., "van den").
|
|
696
|
+
- `nation` – Optional nation code of the official.
|
|
697
|
+
- `passport` – Optional passport identifier.
|
|
698
|
+
- `contact` – Optional `Lenex::Parser::Objects::Contact` describing how to reach the official.
|
|
699
|
+
|
|
700
|
+
The record list object exposes:
|
|
701
|
+
|
|
702
|
+
- `course` – Required pool length for records in the list.
|
|
703
|
+
- `gender` – Required gender classification for the contained records.
|
|
704
|
+
- `handicap` – Optional handicap classification for para records.
|
|
705
|
+
- `name` – Required human readable list name (e.g., "World Records").
|
|
706
|
+
- `nation` – Optional federation nation code for the records.
|
|
707
|
+
- `order` – Optional ordering hint when multiple lists appear.
|
|
708
|
+
- `region` – Optional region code for regional record lists.
|
|
709
|
+
- `type` – Optional record type identifier such as `WR` or `ER`.
|
|
710
|
+
- `updated` – Optional date the record list was last updated.
|
|
711
|
+
- `age_group` – Optional `Lenex::Parser::Objects::AgeGroup` describing the age category covered by the list.
|
|
712
|
+
- `records` – Array of `Lenex::Parser::Objects::Record` entries within the list.
|
|
713
|
+
|
|
714
|
+
The record object exposes:
|
|
715
|
+
|
|
716
|
+
- `swim_time` – Required record time string.
|
|
717
|
+
- `status` – Optional approval status such as `APPROVED` or `PENDING`.
|
|
718
|
+
- `comment` – Optional free-text comment about the record.
|
|
719
|
+
- `meet_info` – Optional `Lenex::Parser::Objects::MeetInfo` describing where the performance occurred.
|
|
720
|
+
- `swim_style` – Optional `Lenex::Parser::Objects::SwimStyle` describing the stroke and distance.
|
|
721
|
+
- `athlete` – Optional `Lenex::Parser::Objects::RecordAthlete` when the record is held by an individual.
|
|
722
|
+
- `relay` – Optional `Lenex::Parser::Objects::RecordRelay` when the record is held by a relay team.
|
|
723
|
+
- `splits` – Array of `Lenex::Parser::Objects::Split` objects containing available split times.
|
|
724
|
+
|
|
725
|
+
The record athlete object exposes:
|
|
726
|
+
|
|
727
|
+
- `athlete_id` – Optional identifier supplied when the record references a meet athlete id.
|
|
728
|
+
- `birthdate` – Required birth date of the athlete in `YYYY-MM-DD` format.
|
|
729
|
+
- `first_name` / `first_name_en` – Required first name and optional English variant.
|
|
730
|
+
- `last_name` / `last_name_en` – Required last name and optional English variant.
|
|
731
|
+
- `gender` – Required gender flag (`M` or `F`).
|
|
732
|
+
- `level` – Optional athlete level string.
|
|
733
|
+
- `license` / `license_ipc` – Optional federation and IPC license identifiers.
|
|
734
|
+
- `name_prefix` – Optional surname prefix (e.g., "van den").
|
|
735
|
+
- `nation` – Optional nation code.
|
|
736
|
+
- `passport` – Optional passport number.
|
|
737
|
+
- `status` – Optional status flag such as `ROOKIE` or `FOREIGNER`.
|
|
738
|
+
- `swrid` – Optional SwimRankings.net identifier.
|
|
739
|
+
- `club` – Optional `Lenex::Parser::Objects::Club` describing the athlete's club when the export provides it.
|
|
740
|
+
|
|
741
|
+
The record relay object exposes:
|
|
742
|
+
|
|
743
|
+
- `name` – Optional descriptive relay name.
|
|
744
|
+
- `club` – Optional `Lenex::Parser::Objects::Club` representing the relay's club affiliation.
|
|
745
|
+
- `relay_positions` – Array of `Lenex::Parser::Objects::RecordRelayPosition` describing the swimmers listed with the record.
|
|
746
|
+
|
|
747
|
+
The record relay position object exposes:
|
|
748
|
+
|
|
749
|
+
- `number` – Required swimmer order within the relay (1 for the first swimmer).
|
|
750
|
+
- `reaction_time` – Optional reaction or takeover time for the swimmer.
|
|
751
|
+
- `status` – Optional status such as `DSQ` for the swimmer's leg.
|
|
752
|
+
- `athlete` – Required `Lenex::Parser::Objects::RecordAthlete` describing the swimmer attached to the record.
|
|
753
|
+
|
|
754
|
+
The time standard list object exposes:
|
|
755
|
+
|
|
756
|
+
- `time_standard_list_id` – Required identifier unique to the time standard list.
|
|
757
|
+
- `name` – Required descriptive label for the list (e.g., "Olympic A").
|
|
758
|
+
- `course` – Required course designation matching the covered pool length.
|
|
759
|
+
- `gender` – Required gender classification (`M`, `F`, or `X`).
|
|
760
|
+
- `handicap` – Optional handicap classification when the list targets para swimmers.
|
|
761
|
+
- `type` – Optional behaviour flag indicating whether entries must be faster (`MAXIMUM`), slower (`MINIMUM`), or use the list as a fallback (`DEFAULT`).
|
|
762
|
+
- `age_group` – Optional `Lenex::Parser::Objects::AgeGroup` specifying the eligible ages.
|
|
763
|
+
- `time_standards` – Array of `Lenex::Parser::Objects::TimeStandard` entries contained in the list.
|
|
764
|
+
|
|
765
|
+
The time standard object exposes:
|
|
766
|
+
|
|
767
|
+
- `swim_time` – Required benchmark time string to compare entries against.
|
|
768
|
+
- `swim_style` – `Lenex::Parser::Objects::SwimStyle` describing the distance, stroke, and relay composition tied to the standard.
|
|
769
|
+
|
|
770
|
+
### Error handling
|
|
771
|
+
|
|
772
|
+
Parsing issues raise `Lenex::Parser::ParseError`. This includes missing required elements or attributes, as well as XML syntax errors encountered while reading the document.
|
|
773
|
+
|
|
774
|
+
## Development
|
|
775
|
+
|
|
776
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
|
|
777
|
+
|
|
778
|
+
To run RuboCop:
|
|
779
|
+
|
|
780
|
+
```sh
|
|
781
|
+
bundle exec rubocop
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
To run tests with coverage:
|
|
785
|
+
|
|
786
|
+
```sh
|
|
787
|
+
bundle exec rake test:coverage
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
## Contributing
|
|
791
|
+
|
|
792
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/your_username/lenex-parser.
|
|
793
|
+
|
|
794
|
+
## License
|
|
795
|
+
|
|
796
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|