radiant-race_results-extension 1.0.1

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