radiant-race_results-extension 1.4.0 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,74 @@
1
+ module RaceAdminUI
2
+
3
+ def self.included(base)
4
+ base.class_eval do
5
+
6
+ attr_accessor :race
7
+ alias_method :races, :race
8
+ attr_accessor :race_instance
9
+ alias_method :race_instances, :race_instance
10
+ attr_accessor :race_club
11
+ alias_method :race_clubs, :race_club
12
+ attr_accessor :race_competitor
13
+ alias_method :race_competitors, :race_competitor
14
+
15
+ protected
16
+
17
+ def load_default_race_regions
18
+ OpenStruct.new.tap do |race|
19
+ race.edit = Radiant::AdminUI::RegionSet.new do |edit|
20
+ edit.main.concat %w{edit_header edit_form}
21
+ edit.form.concat %w{edit_name edit_metadata edit_distance edit_description edit_attachments edit_records edit_checkpoints}
22
+ end
23
+ race.new = race.edit
24
+ race.index = Radiant::AdminUI::RegionSet.new do |index|
25
+ index.thead.concat %w{title_header instances_header}
26
+ index.tbody.concat %w{title_cell instances_cell}
27
+ index.bottom.concat %w{buttons}
28
+ end
29
+ end
30
+ end
31
+
32
+ def load_default_race_instance_regions
33
+ OpenStruct.new.tap do |race_instance|
34
+ race_instance.edit = Radiant::AdminUI::RegionSet.new do |edit|
35
+ edit.main.concat %w{edit_header edit_form}
36
+ edit.form.concat %w{edit_name edit_metadata edit_start edit_notes edit_file edit_report}
37
+ end
38
+ race_instance.new = race_instance.edit
39
+ end
40
+ end
41
+
42
+ def load_default_race_club_regions
43
+ OpenStruct.new.tap do |race_club|
44
+ race_club.edit = Radiant::AdminUI::RegionSet.new do |edit|
45
+ edit.main.concat %w{edit_header edit_form}
46
+ edit.form.concat %w{edit_name edit_aliases}
47
+ end
48
+ race_club.new = race_club.edit
49
+ race_club.index = Radiant::AdminUI::RegionSet.new do |index|
50
+ index.thead.concat %w{title_header members_header aliases_header}
51
+ index.tbody.concat %w{title_cell members_cell aliases_cell}
52
+ index.bottom.concat %w{buttons}
53
+ end
54
+ end
55
+ end
56
+
57
+ def load_default_race_competitor_regions
58
+ OpenStruct.new.tap do |race_competitor|
59
+ race_competitor.edit = Radiant::AdminUI::RegionSet.new do |edit|
60
+ edit.main.concat %w{edit_header edit_form}
61
+ edit.form.concat %w{edit_name edit_club edit_person}
62
+ end
63
+ race_competitor.new = race_competitor.edit
64
+ race_competitor.index = Radiant::AdminUI::RegionSet.new do |index|
65
+ index.thead.concat %w{title_header club_header races_header}
66
+ index.tbody.concat %w{title_cell club_cell races_cell}
67
+ index.bottom.concat %w{buttons}
68
+ end
69
+ end
70
+ end
71
+
72
+ end
73
+ end
74
+ end
data/lib/race_tags.rb ADDED
@@ -0,0 +1,720 @@
1
+ module RaceTags
2
+ include Radiant::Taggable
3
+ include ActionView::Helpers::TextHelper
4
+ # include ActionView::Helpers::TagHelper
5
+
6
+ class TagError < StandardError; end
7
+
8
+ ####### race list
9
+
10
+ desc %{
11
+ Loops through the list of races we know about. Takes the usual by and order parameters.
12
+
13
+ *Usage:*
14
+ <pre><code><r:races:each>...</r:races:each></code></pre>
15
+ }
16
+ tag 'races' do |tag|
17
+ _get_races(tag)
18
+ tag.expand
19
+ end
20
+ tag 'races:each' do |tag|
21
+ result = []
22
+ tag.locals.races.each do |race|
23
+ tag.locals.race = race
24
+ result << tag.expand
25
+ end
26
+ result
27
+ end
28
+
29
+ ####### races
30
+
31
+ desc %{
32
+ Retreives a single race from the name or id you supply or (on a RacePage) from the url or parameters.
33
+ All the r:race:* tags will follow the same retrieval rules.
34
+
35
+ *Usage:*
36
+ <pre><code><r:race [name="dunnerdale"] [id="1"]>...</r:race></code></pre>
37
+ }
38
+ tag 'race' do |tag|
39
+ _get_race(tag)
40
+ raise TagError, "No such race" unless tag.locals.race
41
+ tag.expand
42
+ end
43
+
44
+ desc %{
45
+ Expands if a race is available. Most useful on a RacePage.
46
+
47
+ *Usage:*
48
+ <pre><code><r:if_race>...</r:if_race></code></pre>
49
+ }
50
+ tag 'if_race' do |tag|
51
+ _get_race(tag)
52
+ tag.expand if tag.locals.race
53
+ end
54
+
55
+ desc %{
56
+ Expands if no race is available. Most useful on a RacePage.
57
+
58
+ *Usage:*
59
+ <pre><code><r:unless_race>...</r:unless_race></code></pre>
60
+ }
61
+ tag 'unless_race' do |tag|
62
+ _get_race(tag)
63
+ tag.expand unless tag.locals.race
64
+ end
65
+
66
+ desc %{
67
+ Displays the formatted description of the currently selected race.
68
+
69
+ *Usage:*
70
+ <pre><code><r:race:description /></code></pre>
71
+ }
72
+ tag "race:description" do |tag|
73
+ _get_race(tag)
74
+ tag.locals.race.filter.filter(tag.locals.race.description)
75
+ end
76
+
77
+
78
+ [:id, :name, :slug, :distance, :climb].each do |field|
79
+ desc %{
80
+ Displays the #{field} of the currently selected race.
81
+
82
+ *Usage:*
83
+ <pre><code><r:race:#{field} /></code></pre>
84
+ }
85
+ tag "race:#{field}" do |tag|
86
+ _get_race(tag)
87
+ tag.locals.race.send(field) if tag.locals.race
88
+ end
89
+ end
90
+
91
+ desc %{
92
+ Loops through the list of instances of the present race, retrieving the set of results
93
+ for each and making them available to any contained r:results tags.
94
+
95
+ *Usage:*
96
+ <pre><code><r:race:instances:each>...</r:race:instances:each></code></pre>
97
+ }
98
+ tag 'race:results' do |tag|
99
+ _get_race(tag)
100
+ raise TagError, "No race to show results of" unless tag.locals.race
101
+ tag.expand
102
+ end
103
+ tag 'race:results:each' do |tag|
104
+ result = []
105
+ tag.locals.race.instances.each do |instance|
106
+ tag.locals.race_instance = instance
107
+ result << tag.expand
108
+ end
109
+ result
110
+ end
111
+
112
+ ####### race instances (required for most other tags)
113
+
114
+ desc %{
115
+ Retrieves a set of results from the specified race and instance or (on a RacePage) from the url or parameters.
116
+
117
+ *Usage:*
118
+ <pre><code>
119
+ <r:results race="dunnerdale" instance="2009">
120
+ <ol>
121
+ <r:performances:each>
122
+ <li><r:performance:name />: <r:performance:elapsed_time /></li>
123
+ </r:performances:each>
124
+ </ol>
125
+ </r:results>
126
+ </code></pre>
127
+ }
128
+ tag 'results' do |tag|
129
+ _get_race_instance(tag)
130
+ raise TagError, "No race instance whose results to show" unless tag.locals.race_instance
131
+ tag.expand
132
+ end
133
+
134
+ desc %{
135
+ Expands if a race instance is available. Most useful on a RacePage.
136
+
137
+ *Usage:*
138
+ <pre><code><r:if_results>...</r:if_results></code></pre>
139
+ }
140
+ tag 'if_results' do |tag|
141
+ _get_race_instance(tag)
142
+ tag.expand if tag.locals.race_instance
143
+ end
144
+
145
+ desc %{
146
+ Expands if no race instance is available. Most useful on a RacePage.
147
+
148
+ *Usage:*
149
+ <pre><code><r:unless_results>...</r:unless_results></code></pre>
150
+ }
151
+ tag 'unless_results' do |tag|
152
+ _get_race_instance(tag)
153
+ tag.expand unless tag.locals.race_instance
154
+ end
155
+
156
+ desc %{
157
+ Expands if results are available for this race instance.
158
+
159
+ *Usage:*
160
+ <pre><code><r:if_results_uploaded>...</r:if_results_uploaded></code></pre>
161
+ }
162
+ tag 'if_results_uploaded' do |tag|
163
+ _get_race_instance(tag)
164
+ raise TagError, "No race instance to check for results" unless tag.locals.race_instance
165
+ tag.expand if tag.locals.race_instance.has_results?
166
+ end
167
+
168
+ desc %{
169
+ Expands if results are not available for this race instance.
170
+
171
+ *Usage:*
172
+ <pre><code><r:r:unless_results_uploaded>...</r:r:unless_results_uploaded></code></pre>
173
+ }
174
+ tag 'unless_results_uploaded' do |tag|
175
+ _get_race_instance(tag)
176
+ raise TagError, "No race instance to check for results" unless tag.locals.race_instance
177
+ tag.expand unless tag.locals.race_instance.has_results?
178
+ end
179
+
180
+
181
+ [:id, :name, :full_name, :slug, :path, :notes, :report].each do |field|
182
+ desc %{
183
+ Displays the #{field} column of the currently selected race instance.
184
+
185
+ *Usage:*
186
+ <pre><code><r:results:#{field} /></code></pre>
187
+ }
188
+ tag "results:#{field}" do |tag|
189
+ _get_race_instance(tag)
190
+ raise TagError, "No race instance to show #{field} of" unless tag.locals.race_instance
191
+ tag.locals.race_instance.send(field)
192
+ end
193
+ end
194
+
195
+ [:notes, :report].each do |field|
196
+ desc %{
197
+ Displays the formatted #{field} column of the currently selected race instance.
198
+
199
+ *Usage:*
200
+ <pre><code><r:results:#{field} /></code></pre>
201
+ }
202
+ tag "results:#{field}" do |tag|
203
+ _get_race_instance(tag)
204
+ raise TagError, "No race instance whose #{field} to show" unless tag.locals.race_instance
205
+ tag.locals.race_instance.filter.filter(tag.locals.race_instance.send(field))
206
+ end
207
+ end
208
+
209
+ desc %{
210
+ Displays the start of the current race instance as a date.
211
+
212
+ *Usage:*
213
+ <pre><code><r:results:start_date /></code></pre>
214
+ }
215
+ tag "results:start_date" do |tag|
216
+ _get_race_instance(tag)
217
+ raise TagError, "No race instance whose date to show" unless tag.locals.race_instance
218
+ tag.locals.race_instance.nice_start_date
219
+ end
220
+
221
+ desc %{
222
+ Displays the start of the current race instance as a time of day.
223
+
224
+ *Usage:*
225
+ <pre><code><r:results:start_time /></code></pre>
226
+ }
227
+ tag "results:start_time" do |tag|
228
+ _get_race_instance(tag)
229
+ raise TagError, "No race instance whose start time to show" unless tag.locals.race_instance
230
+ tag.locals.race_instance.nice_start_time
231
+ end
232
+
233
+ [:checkpoints, :categories, :competitors, :performances, :finishers, :non_finishers].each do |collection|
234
+ desc %{
235
+ Loops through the list of #{collection} in the current results set.
236
+
237
+ *Usage:*
238
+ <pre><code><r:#{collection}:each [limit="10"]>...</r:#{collection}:each></code></pre>
239
+ }
240
+ tag "#{collection}" do |tag|
241
+ _get_race_instance(tag)
242
+ raise TagError, "No race instance in which to show #{collection}" unless tag.locals.race_instance
243
+ tag.expand
244
+ end
245
+ tag "#{collection}:each" do |tag|
246
+ _get_race_instance(tag)
247
+ result = []
248
+ tag.locals.race_instance.send(collection).each do |member|
249
+ setter = [:performances, :finishers, :non_finishers].include?(collection) ? 'performance=' : "#{collection.to_s.singularize}="
250
+ tag.locals.send(setter, member)
251
+ result << tag.expand
252
+ end
253
+ result
254
+ end
255
+ end
256
+
257
+
258
+ ####### performances
259
+
260
+ desc %{
261
+ Retrieves a single performance from the result set, based on the race number or position that you supply.
262
+
263
+ *Usage:*
264
+ <pre><code><r:performance [number="1"] [position="1"]>...</r:performance></code></pre>
265
+ }
266
+ tag 'performance' do |tag|
267
+ raise TagError, "No race instance available within which to find a performance" unless tag.locals.race_instance
268
+ _get_race_performance(tag)
269
+ raise TagError, "No race performance found" unless tag.locals.performance
270
+ tag.expand
271
+ end
272
+
273
+ [:position, :name, :number, :elapsed_time, :position, :status].each do |field|
274
+ desc %{
275
+ Displays the #{field} column of the performance currently in the foreground.
276
+
277
+ *Usage:*
278
+ <pre><code><r:performance:#{field} /></code></pre>
279
+ }
280
+ tag "performance:#{field}" do |tag|
281
+ _get_race_performance(tag)
282
+ tag.locals.performance.send(field) if tag.locals.performance
283
+ end
284
+ end
285
+
286
+ [:club, :category, :competitor, :race_instance].each do |association|
287
+ desc %{
288
+ Retrieves the #{association} associated with the performance currently in the foreground
289
+
290
+ If double, we expand and make the #{association} available to any contained r:#{association} tags.
291
+
292
+ If single, we just display the name of the #{association}.
293
+
294
+ <pre><code>
295
+ <r:performance:#{association} />
296
+ <r:performance:#{association}>...</r:performance:#{association}></code></pre>
297
+ </code></pre>
298
+ }
299
+ tag "performance:#{association}" do |tag|
300
+ _get_race_performance(tag)
301
+ if tag.double?
302
+ tag.locals.send("#{association}=".intern, tag.locals.performance.send(association))
303
+ tag.expand
304
+ else
305
+ associate = tag.locals.performance.send(association)
306
+ associate.name if associate
307
+ end
308
+ end
309
+ end
310
+
311
+ tag "performance:if_finished" do |tag|
312
+ _get_race_performance(tag)
313
+ tag.expand if tag.locals.performance.finished?
314
+ end
315
+ tag "performance:unless_finished" do |tag|
316
+ _get_race_performance(tag)
317
+ tag.expand unless tag.locals.performance.finished?
318
+ end
319
+
320
+ tag "performance:if_prize" do |tag|
321
+ _get_race_performance(tag)
322
+ tag.expand if tag.locals.performance.prized?
323
+ end
324
+ tag "performance:unless_prize" do |tag|
325
+ _get_race_performance(tag)
326
+ tag.expand unless tag.locals.performance.prized?
327
+ end
328
+
329
+ tag "performance:prize" do |tag|
330
+ _get_race_performance(tag)
331
+ tag.locals.performance.prize
332
+ end
333
+
334
+ desc %{
335
+ Loops through the list of checkpoint times associated with the present performance. Within this tag
336
+ you can use r:checkpoint_time singly just to show the split time, or a clause like this to show more detail:
337
+
338
+ *Usage:*
339
+ <pre><code>
340
+ <r:performance:checkpoint_times:each>
341
+ <strong><r:checkpoint_time:elapsed_time /><strong><br />
342
+ pos: <r:checkpoint_time:position /> (<r:checkpoint_time:gain />)
343
+ </r:performance:checkpoint_times:each>
344
+ </code></pre>
345
+ }
346
+ tag 'performance:checkpoint_times' do |tag|
347
+ _get_race_performance(tag)
348
+ raise TagError, "No performance to find times for" unless tag.locals.performance
349
+ tag.expand
350
+ end
351
+ tag 'performance:checkpoint_times:each' do |tag|
352
+ _get_race_performance(tag)
353
+ result = []
354
+ tag.locals.performance.checkpoint_times.each do |time|
355
+ tag.locals.checkpoint_time = time
356
+ result << tag.expand
357
+ end
358
+ result
359
+ end
360
+
361
+
362
+ ####### categories
363
+
364
+ desc %{
365
+ Retrieves a single category from the result set, based on the name that you supply.
366
+
367
+ *Usage:*
368
+ <pre><code><r:category name="MV40">...</r:category></code></pre>
369
+ }
370
+ tag 'category' do |tag|
371
+ _get_race_category(tag)
372
+ raise TagError, "No race category found" unless tag.locals.category
373
+ tag.expand
374
+ end
375
+
376
+ [:id, :name, :record, :entries, :finishers].each do |field|
377
+ desc %{
378
+ Displays the #{field} column of the race category currently in the foreground.
379
+
380
+ *Usage:*
381
+ <pre><code><r:category:#{field} /></code></pre>
382
+ }
383
+ tag "category:#{field}" do |tag|
384
+ _get_race_category(tag)
385
+ tag.locals.category.send(field) if tag.locals.category
386
+ end
387
+ end
388
+
389
+ desc %{
390
+ Loops through the list of performances in the present racea category, making them available
391
+ to the usual r:performance tags.
392
+
393
+ Supply a @limit@ attribute to limit the size of the list returned.
394
+
395
+ *Usage:*
396
+ <pre><code><r:category:performances:each [limit="10"]>...</r:category:performances:each></code></pre>
397
+ }
398
+ tag 'category:performances' do |tag|
399
+ _get_race_category(tag)
400
+ raise TagError, "No category to draw performances from" unless tag.locals.category
401
+ tag.expand
402
+ end
403
+ tag 'category:performances:each' do |tag|
404
+ _get_race_category(tag)
405
+ result = []
406
+ tag.locals.category.performances.each do |performance|
407
+ tag.locals.performance = performance
408
+ result << tag.expand
409
+ end
410
+ result
411
+ end
412
+
413
+ ####### clubs
414
+
415
+ desc %{
416
+ Retrieves a single club from the result set, based on the name that you supply.
417
+
418
+ *Usage:*
419
+ <pre><code><r:club name="Black Combe Runners">...</r:club></code></pre>
420
+ }
421
+ tag 'club' do |tag|
422
+ _get_club(tag)
423
+ # raise TagError, "No club found" unless tag.locals.club
424
+ tag.expand if tag.locals.club
425
+ end
426
+ [:id, :name, :url].each do |field|
427
+ desc %{
428
+ Displays the #{field} column of the club currently in the foreground.
429
+
430
+ *Usage:*
431
+ <pre><code><r:club:#{field} /></code></pre>
432
+ }
433
+ tag "club:#{field}" do |tag|
434
+ _get_club(tag)
435
+ tag.locals.club ||= _get_club(tag)
436
+ tag.locals.club.send(field) if tag.locals.club
437
+ end
438
+ end
439
+
440
+ desc %{
441
+ Renders a link to the club currently in the foreground. Attributes and link text are passed through as usual.
442
+
443
+ *Usage:*
444
+ <pre><code><r:club:link class="cssclass" /></code></pre>
445
+ }
446
+ tag "club:link" do |tag|
447
+ _get_club(tag)
448
+ raise TagError, "No club to link to" unless tag.locals.club
449
+ options = tag.attr.dup
450
+ anchor = options['anchor'] ? "##{options.delete('anchor')}" : ''
451
+ attributes = options.inject(' ') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
452
+ text = tag.double? ? tag.expand : tag.render('club:name')
453
+ %{<a href="#{tag.render('club:url')}#{anchor}"#{attributes}>#{text}</a>}
454
+ end
455
+
456
+ ####### checkpoints
457
+
458
+ desc %{
459
+ Retrieves a single checkpoint from the result set, based on the name that you supply.
460
+
461
+ *Usage:*
462
+ <pre><code><r:checkpoint name="Raven Crag">...</r:checkpoint></code></pre>
463
+ }
464
+ tag 'checkpoint' do |tag|
465
+ _get_race_checkpoint(tag)
466
+ raise TagError, "No checkpoint found" unless tag.locals.checkpoint
467
+ tag.expand
468
+ end
469
+ [:id, :name, :location].each do |field|
470
+ desc %{
471
+ Displays the #{field} column of the checkpoint currently in the foreground.
472
+
473
+ *Usage:*
474
+ <pre><code><r:checkpoint:#{field} /></code></pre>
475
+ }
476
+ tag "checkpoint:#{field}" do |tag|
477
+ _get_race_checkpoint(tag)
478
+ tag.locals.checkpoint.send(field) if tag.locals.club
479
+ end
480
+ end
481
+
482
+ desc %{
483
+ Loops through the list of checkpoint times associated with the present checkpoint.
484
+
485
+ Supply a @limit@ attribute to limit the size of the list returned.
486
+
487
+ *Usage:*
488
+ <pre><code><r:checkpoint:times:each [limit="10"]>...</r:checkpoint:times:each></code></pre>
489
+ }
490
+ tag 'checkpoint:times' do |tag|
491
+ _get_race_checkpoint(tag)
492
+ raise TagError, "No checkpoint to find times for" unless tag.locals.checkpoint
493
+ tag.expand
494
+ end
495
+ tag 'checkpoint:times:each' do |tag|
496
+ _get_race_checkpoint(tag)
497
+ result = []
498
+ tag.locals.checkpoint.times.each do |time|
499
+ tag.locals.checkpoint_time = time
500
+ result << tag.expand
501
+ end
502
+ result
503
+ end
504
+
505
+ ####### checkpoint times are only shown in lists
506
+
507
+ desc %{
508
+ Retrieves a single checkpoint from the result set, based on the name that you supply.
509
+
510
+ Used singly: it just displays the time at that checkpoint.
511
+
512
+ If double, it expands in the usual way. You can use r:performance:* tags within this tag if you want to display
513
+ a list of arrivals at this point, and r:checkpoint_time:* tags to display the time, position and gain data.
514
+ This is only likely to happen when you're displaying an individual performance but it is also possible to build
515
+ a complete splits table this way.
516
+
517
+ }
518
+ tag 'checkpoint_time' do |tag|
519
+ raise TagError, "checkpoint_time tag can only be used in a results list" unless tag.locals.checkpoint_time
520
+ if tag.double?
521
+ tag.locals.performance = tag.locals.checkpoint_time.performance
522
+ tag.expand
523
+ else
524
+ tag.locals.checkpoint_time.elapsed_time
525
+ end
526
+ end
527
+
528
+ [:elapsed_time, :position, :gain].each do |field|
529
+ desc %{
530
+ Displays the #{field} of the checkpoint arrival time currently in the foreground.
531
+
532
+ *Usage:*
533
+ <pre><code><r:checkpoint_time:#{field} /></code></pre>
534
+ }
535
+ tag "checkpoint_time:#{field}" do |tag|
536
+ raise TagError, "checkpoint_time:* tags can only be used in a results list" unless tag.locals.checkpoint_time
537
+ tag.locals.checkpoint_time.send(field)
538
+ end
539
+ end
540
+
541
+ ####### standard display blocks
542
+
543
+ desc %{
544
+ Displays a complete table of race results in a simple standard format.
545
+ }
546
+ tag 'results:table' do |tag|
547
+ _get_race_instance
548
+ raise TagError, "No race instance to list" unless tag.locals.race_instance
549
+ result = []
550
+ result << %{<table class="results">}
551
+ result << tag.render('results:header')
552
+ tag.locals.performances = tag.locals.race_instance.performances
553
+ result << tag.render('performances:table')
554
+ result << %{</table>}
555
+ result.flatten
556
+ end
557
+
558
+ desc %{
559
+ Displays a standard list of performances. This is here to support the results:table and category:table but you can
560
+ use it directly if you like. A list of perfomances must be available.
561
+ }
562
+ tag 'performances:table' do |tag|
563
+ raise TagError, "No performances to display" unless tag.locals.performances
564
+ result = []
565
+ result << %{<tbody>}
566
+ if tag.locals.performances.any?
567
+ tag.locals.performances.each do |performance|
568
+ tag.locals.performance = performance
569
+ result << %{
570
+ <tr>
571
+ <td>#{tag.render('performance:position')}</td>
572
+ <td>#{tag.render('performance:name')}</td>
573
+ <td>#{tag.render('performance:club')}</td>
574
+ <td>#{tag.render('performance:category')}</td>
575
+ <td>#{tag.render('performance:time')}</td>
576
+ </tr>
577
+ }
578
+ end
579
+ else
580
+ result << %{<tr><td colspan="5" class="nodata">No results to display</td></tr>}
581
+ end
582
+ result << %{</tbody>}
583
+ result
584
+ end
585
+
586
+ desc %{
587
+ Displays standard column headings suitable for use in any of the results tables
588
+ }
589
+ tag 'results:header' do |tag|
590
+ %{<thead><tr><th>Pos</th><th>Name</th><th>Club</th><th>Cat</th><th>Time</th></tr></thead>}
591
+ end
592
+
593
+ desc %{
594
+ Displays a complete table of splits for the current race.
595
+ }
596
+ tag 'results:splits' do |tag|
597
+
598
+ end
599
+
600
+ desc %{
601
+ Displays a complete table of results in the current category, in a simple standard format.
602
+ }
603
+ tag 'category:list' do |tag|
604
+
605
+ end
606
+
607
+ desc %{
608
+ Displays a table of the prize-winning performances suitable for use on a summary page.
609
+ }
610
+ tag 'results:prizes' do |tag|
611
+
612
+ end
613
+
614
+ desc %{
615
+ Displays a table of the category-prize-winning performances suitable for use on a summary page.
616
+ }
617
+ tag 'category:prizes' do |tag|
618
+
619
+ end
620
+
621
+ ####### page furniture
622
+
623
+
624
+ desc %{
625
+ Renders a trail of breadcrumbs to the current page. On a race_results page this tag is
626
+ overridden to show the name and instance of the race being displayed
627
+
628
+ *Usage:*
629
+
630
+ <pre><code><r:breadcrumbs [separator="separator_string"] [nolinks="true"] /></code></pre>
631
+ }
632
+ tag 'breadcrumbs' do |tag|
633
+ page = tag.locals.page
634
+ nolinks = (tag.attr['nolinks'] == 'true')
635
+
636
+ if race
637
+ crumbs = nolinks ? [page.breadcrumb] : [%{<a href="#{url}">#{tag.render('breadcrumb')}</a>}]
638
+ if race_instance
639
+ crumbs << (nolinks ? race : %{<a href="#{url}/#{race.slug}">#{race.name}</a>})
640
+ crumbs << race_instance.name
641
+ else
642
+ crumbs << race.name
643
+ end
644
+ else
645
+ crumbs = [page.breadcrumb]
646
+ end
647
+ page.ancestors.each do |ancestor|
648
+ tag.locals.page = ancestor
649
+ if nolinks
650
+ crumbs.unshift tag.render('breadcrumb')
651
+ else
652
+ crumbs.unshift %{<a href="#{tag.render('url')}">#{tag.render('breadcrumb')}</a>}
653
+ end
654
+ end
655
+ separator = tag.attr['separator'] || ' &gt; '
656
+ crumbs.join(separator)
657
+ end
658
+
659
+
660
+
661
+
662
+
663
+
664
+
665
+
666
+ private
667
+
668
+ def _get_races(tag)
669
+ return tag.locals.races if tag.locals.races
670
+ tag.locals.races = Race.all
671
+ end
672
+
673
+ def _get_race(tag)
674
+ tag.locals.race ||= tag.locals.page.race if tag.locals.page.is_a? RacePage
675
+ return tag.locals.race if tag.locals.race
676
+ tag.locals.race = Race.find_by_name(tag.attr['name']) if tag.attr['name']
677
+ end
678
+
679
+ def _get_race_instance(tag)
680
+ tag.locals.race_instance ||= tag.locals.page.race_instance if tag.locals.page.is_a? RacePage
681
+ return tag.locals.race_instance if tag.locals.race_instance
682
+ _get_race(tag)
683
+ return unless tag.locals.race && tag.attr['instance']
684
+ tag.locals.race_instance = tag.locals.race.in(tag.attr['instance'])
685
+ end
686
+
687
+ def _get_race_category(tag)
688
+ return tag.locals.category if tag.locals.category
689
+ raise TagError, "No race instance available within which to find a category" unless tag.locals.race_instance
690
+ raise TagError, "No category name supplied" unless tag.attr['name']
691
+ tag.locals.category = tag.locals.race_instance.categories.find_by_name(tag.attr['name'])
692
+ end
693
+
694
+ def _get_race_performance(tag)
695
+ return tag.locals.performance if tag.locals.performance
696
+ raise TagError, "No race instance available within which to find a peformance" unless tag.locals.race_instance
697
+ if name = tag.attr['name']
698
+ tag.locals.performance = tag.locals.race_instance.performance_by(tag.locals.race_instance.competitors.find_by_name(name))
699
+ elsif position = tag.attr['position']
700
+ tag.locals.performance = tag.locals.race_instance.performance_at(position)
701
+ elsif number = tag.attr['number']
702
+ tag.locals.performance = tag.locals.race_instance.performance.find_by_number(number)
703
+ else
704
+ raise TagError, "Performance name, number or position is required"
705
+ end
706
+ end
707
+
708
+ def _get_race_checkpoint(tag)
709
+ return tag.locals.checkpoint if tag.locals.checkpoint
710
+ raise TagError, "No race instance available within which to find a checkpoint" unless tag.locals.race_instance
711
+ raise TagError, "No checkpoint name supplied" unless tag.attr['name']
712
+ tag.locals.checkpoint = tag.locals.race_instance.checkpoints.find_by_name(tag.attr['name'])
713
+ end
714
+
715
+ def _get_club(tag)
716
+ return tag.locals.club if tag.locals.club
717
+ tag.locals.club = RaceClub.find_by_name(tag.attr['name']) if tag.attr['name']
718
+ end
719
+
720
+ end