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,128 @@
1
+ class RaceData < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :races do |t|
4
+ t.column :name, :string
5
+ t.column :slug, :string
6
+ t.column :description, :text
7
+ t.column :created_by_id, :integer
8
+ t.column :updated_by_id, :integer
9
+ t.column :created_at, :datetime
10
+ t.column :updated_at, :datetime
11
+ t.column :site_id, :integer
12
+ end
13
+ add_index :races, [:name, :site_id], :unique => true
14
+
15
+ create_table :race_instances do |t|
16
+ t.column :race_id, :integer
17
+ t.column :name, :string
18
+ t.column :slug, :string
19
+ t.column :results_file_name, :string
20
+ t.column :results_content_type, :string
21
+ t.column :results_file_size, :integer
22
+ t.column :started_at, :datetime
23
+ t.column :created_by_id, :integer
24
+ t.column :updated_by_id, :integer
25
+ t.column :created_at, :datetime
26
+ t.column :updated_at, :datetime
27
+ t.column :site_id, :integer
28
+ end
29
+ add_index :race_instances, [:site_id]
30
+ add_index :race_instances, [:slug, :race_id], :unique => true
31
+
32
+ # this ought to be suitable for score courses too
33
+
34
+ create_table :race_checkpoints do |t|
35
+ t.column :race_instance_id, :integer
36
+ t.column :position, :integer
37
+ t.column :name, :string
38
+ t.column :value, :integer
39
+ t.column :location, :string
40
+ t.column :description, :text
41
+ t.column :created_by_id, :integer
42
+ t.column :updated_by_id, :integer
43
+ t.column :created_at, :datetime
44
+ t.column :updated_at, :datetime
45
+ t.column :site_id, :integer
46
+ end
47
+ add_index :race_checkpoints, [:site_id]
48
+ add_index :race_checkpoints, [:race_instance_id]
49
+
50
+ # clubs, categories and competitors are global
51
+
52
+ create_table :race_categories do |t|
53
+ t.column :name, :string
54
+ t.column :created_by_id, :integer
55
+ t.column :updated_by_id, :integer
56
+ t.column :created_at, :datetime
57
+ t.column :updated_at, :datetime
58
+ end
59
+ add_index :race_categories, :name, :unique => true
60
+
61
+ create_table :race_clubs do |t|
62
+ t.column :name, :string
63
+ t.column :url, :string
64
+ t.column :created_by_id, :integer
65
+ t.column :updated_by_id, :integer
66
+ t.column :created_at, :datetime
67
+ t.column :updated_at, :datetime
68
+ end
69
+ add_index :race_clubs, :name, :unique => true
70
+
71
+ create_table :race_competitors do |t|
72
+ t.column :name, :string
73
+ t.column :email, :string
74
+ t.column :reader_id, :integer
75
+ t.column :race_club_id, :integer
76
+ t.column :created_by_id, :integer
77
+ t.column :updated_by_id, :integer
78
+ t.column :created_at, :datetime
79
+ t.column :updated_at, :datetime
80
+ end
81
+ add_index :race_competitors, [:name, :race_club_id]
82
+
83
+ create_table :race_performances do |t|
84
+ t.column :number, :integer
85
+ t.column :position, :integer
86
+ t.column :race_instance_id, :integer
87
+ t.column :race_competitor_id, :integer
88
+ t.column :race_category_id, :integer
89
+ t.column :race_club_id, :integer
90
+ t.column :dibber, :string
91
+ t.column :started_at, :datetime
92
+ t.column :elapsed_time, :integer
93
+ t.column :score, :integer
94
+ t.column :finished_at, :datetime
95
+ t.column :created_by_id, :integer
96
+ t.column :updated_by_id, :integer
97
+ t.column :created_at, :datetime
98
+ t.column :updated_at, :datetime
99
+ t.column :status_id, :integer
100
+ t.column :site_id, :integer
101
+ end
102
+ add_index :race_performances, [:site_id]
103
+ add_index :race_performances, [:race_instance_id, :race_competitor_id, :race_category_id], :name => 'performances_by_competitor_and_category'
104
+
105
+ create_table :race_checkpoint_times do |t|
106
+ t.column :race_performance_id,:integer
107
+ t.column :race_checkpoint_id, :integer
108
+ t.column :elapsed_time, :integer
109
+ t.column :created_by_id, :integer
110
+ t.column :updated_by_id, :integer
111
+ t.column :created_at, :datetime
112
+ t.column :updated_at, :datetime
113
+ t.column :site_id, :integer
114
+ end
115
+ add_index :race_checkpoint_times, [:site_id]
116
+ end
117
+
118
+ def self.down
119
+ drop_table :races
120
+ drop_table :race_checkpoints
121
+ drop_table :race_instances
122
+ drop_table :race_categories
123
+ drop_table :race_clubs
124
+ drop_table :race_competitors
125
+ drop_table :race_performances
126
+ drop_table :race_checkpoint_times
127
+ end
128
+ end
@@ -0,0 +1,9 @@
1
+ class CompetitorDetails < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :race_competitors, :dob, :datetime
4
+ add_column :race_competitors, :gender, :string
5
+ end
6
+
7
+ def self.down
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ class ClubAliases < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :race_club_aliases do |t|
4
+ t.column :race_club_id, :integer
5
+ t.column :name, :string
6
+ t.column :created_by_id, :integer
7
+ t.column :updated_by_id, :integer
8
+ t.column :created_at, :datetime
9
+ t.column :updated_at, :datetime
10
+ end
11
+ add_index :race_club_aliases, :race_club_id
12
+ end
13
+
14
+ def self.down
15
+ drop_table :race_club_aliases
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class InstanceDetails < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :race_instances, :notes, :text
4
+ add_column :race_instances, :report, :text
5
+ end
6
+
7
+ def self.down
8
+ remove_column :race_instances, :notes
9
+ remove_column :race_instances, :report
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class RaceDistance < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :races, :distance, :integer
4
+ add_column :races, :climb, :integer
5
+ end
6
+
7
+ def self.down
8
+ remove_column :races, :distance
9
+ remove_column :races, :climb
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ class RaceRecords < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :race_records do |t|
4
+ t.column :race_id, :integer
5
+ t.column :race_instance_id, :integer
6
+ t.column :race_competitor_id, :integer
7
+ t.column :race_category_id, :integer
8
+ t.column :race_performance_id, :integer
9
+ t.column :elapsed_time, :integer
10
+ t.column :site_id, :integer
11
+ end
12
+ add_index :race_records, :site_id
13
+ add_index :race_records, [:race_id, :race_category_id]
14
+ end
15
+
16
+ def self.down
17
+ drop_table :race_records
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ class CategoryDetails < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :race_categories, :gender, :string
4
+ add_column :race_categories, :age_above, :integer
5
+ add_column :race_categories, :age_below, :integer
6
+ end
7
+
8
+ def self.down
9
+ remove_column :race_categories, :gender
10
+ remove_column :race_categories, :age_above
11
+ remove_column :race_categories, :age_below
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ class Filters < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :races, :filter_id, :string
4
+ add_column :race_instances, :filter_id, :string
5
+ end
6
+
7
+ def self.down
8
+ remove_column :races, :filter_id
9
+ remove_column :race_instances, :filter_id
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class RecordHolder < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :race_records, :holder, :string
4
+ add_column :race_records, :year, :string
5
+ end
6
+
7
+ def self.down
8
+ remove_column :race_records, :holder
9
+ remove_column :race_records, :year
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ class RememberCalculations < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :race_performances, :prizes, :text
4
+ end
5
+
6
+ def self.down
7
+ remove_column :race_performances, :prizes
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ class RaceAttachments < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :races, :picture_asset_id, :integer
4
+ add_column :races, :map_asset_id, :integer
5
+ end
6
+
7
+ def self.down
8
+ remove_column :races, :picture_asset_id
9
+ remove_column :races, :map_asset_id
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ # Sets up the Rails environment for Cucumber
2
+ ENV["RAILS_ENV"] = "test"
3
+ # Extension root
4
+ extension_env = File.expand_path(File.dirname(__FILE__) + '/../../../../../config/environment')
5
+ require extension_env+'.rb'
6
+
7
+ Dir.glob(File.join(RADIANT_ROOT, "features", "**", "*.rb")).each {|step| require step}
8
+
9
+ Cucumber::Rails::World.class_eval do
10
+ include Dataset
11
+ datasets_directory "#{RADIANT_ROOT}/spec/datasets"
12
+ Dataset::Resolver.default = Dataset::DirectoryResolver.new("#{RADIANT_ROOT}/spec/datasets", File.dirname(__FILE__) + '/../../spec/datasets', File.dirname(__FILE__) + '/../datasets')
13
+ self.datasets_database_dump_path = "#{Rails.root}/tmp/dataset"
14
+
15
+ # dataset :race_results
16
+ end
@@ -0,0 +1,14 @@
1
+ def path_to(page_name)
2
+ case page_name
3
+
4
+ when /the homepage/i
5
+ root_path
6
+
7
+ when /login/i
8
+ login_path
9
+ # Add more page name => path mappings here
10
+
11
+ else
12
+ raise "Can't find mapping from \"#{page_name}\" to a path."
13
+ end
14
+ end
@@ -0,0 +1,61 @@
1
+ module DurationExtensions
2
+
3
+ # builds a duration object from a string like (but probably shorter than) dd:hh:mm:ss
4
+ # (or any other non-numeral delimiter will work)
5
+
6
+ def self.included(base)
7
+ base.class_eval {
8
+ extend ClassMethods
9
+ include InstanceMethods
10
+ }
11
+ end
12
+
13
+ module ClassMethods
14
+ def parse(timecode)
15
+ return timecode if timecode.is_a? Numeric
16
+ tokens = timecode.split(/\D+/).map(&:to_i).reverse
17
+ multipliers = [:seconds, :minutes, :hours, :days]
18
+ parts = []
19
+ seconds = tokens.inject(0) {|total, token|
20
+ unit = multipliers.shift
21
+ parts << [unit, token]
22
+ total += token.send(unit)
23
+ }
24
+ new(seconds, parts)
25
+ end
26
+ end
27
+
28
+ module InstanceMethods
29
+ def timecode
30
+ return '00:00:00' if value == 0
31
+ h = (value/3600).floor;
32
+ m = ((value % 3600)/60).floor;
33
+ s = value % 60;
34
+ sprintf("%d:%02d:%02d", h, m, s)
35
+ end
36
+ alias :to_timecode :timecode
37
+ end
38
+ end
39
+
40
+ module StringExtensions
41
+ def duration
42
+ ActiveSupport::Duration.parse(self)
43
+ end
44
+ alias :seconds :duration
45
+
46
+ def looks_like_duration?
47
+ delimiters = Radiant::Config['race_results.delimiters'] || ':,.'
48
+ true if self.match(/^[\d#{Regexp.escape(delimiters)}]+$/)
49
+ end
50
+ end
51
+
52
+ module NumericExtensions
53
+ def to_timecode
54
+ seconds.timecode
55
+ end
56
+ alias :timecode :to_timecode
57
+ end
58
+
59
+ ActiveSupport::Duration.send :include, DurationExtensions
60
+ String.send :include, StringExtensions
61
+ Numeric.send :include, NumericExtensions
@@ -0,0 +1,76 @@
1
+ module RaceResults
2
+ module AdminUI
3
+
4
+ def self.included(base)
5
+ base.class_eval do
6
+
7
+ attr_accessor :race
8
+ alias_method :races, :race
9
+ attr_accessor :race_instance
10
+ alias_method :race_instances, :race_instance
11
+ attr_accessor :race_club
12
+ alias_method :race_clubs, :race_club
13
+ attr_accessor :race_competitor
14
+ alias_method :race_competitors, :race_competitor
15
+
16
+ protected
17
+
18
+ def load_default_race_regions
19
+ returning OpenStruct.new do |race|
20
+ race.edit = Radiant::AdminUI::RegionSet.new do |edit|
21
+ edit.main.concat %w{edit_header edit_form}
22
+ edit.form.concat %w{edit_name edit_metadata edit_distance edit_description edit_attachments edit_records edit_checkpoints}
23
+ end
24
+ race.new = race.edit
25
+ race.index = Radiant::AdminUI::RegionSet.new do |index|
26
+ index.thead.concat %w{title_header instances_header}
27
+ index.tbody.concat %w{title_cell instances_cell}
28
+ index.bottom.concat %w{buttons}
29
+ end
30
+ end
31
+ end
32
+
33
+ def load_default_race_instance_regions
34
+ returning OpenStruct.new do |race_instance|
35
+ race_instance.edit = Radiant::AdminUI::RegionSet.new do |edit|
36
+ edit.main.concat %w{edit_header edit_form}
37
+ edit.form.concat %w{edit_name edit_metadata edit_start edit_notes edit_file edit_report}
38
+ end
39
+ race_instance.new = race_instance.edit
40
+ end
41
+ end
42
+
43
+ def load_default_race_club_regions
44
+ returning OpenStruct.new do |race_club|
45
+ race_club.edit = Radiant::AdminUI::RegionSet.new do |edit|
46
+ edit.main.concat %w{edit_header edit_form}
47
+ edit.form.concat %w{edit_name edit_aliases}
48
+ end
49
+ race_club.new = race_club.edit
50
+ race_club.index = Radiant::AdminUI::RegionSet.new do |index|
51
+ index.thead.concat %w{title_header members_header aliases_header}
52
+ index.tbody.concat %w{title_cell members_cell aliases_cell}
53
+ index.bottom.concat %w{buttons}
54
+ end
55
+ end
56
+ end
57
+
58
+ def load_default_race_competitor_regions
59
+ returning OpenStruct.new do |race_competitor|
60
+ race_competitor.edit = Radiant::AdminUI::RegionSet.new do |edit|
61
+ edit.main.concat %w{edit_header edit_form}
62
+ edit.form.concat %w{edit_name edit_club edit_person}
63
+ end
64
+ race_competitor.new = race_competitor.edit
65
+ race_competitor.index = Radiant::AdminUI::RegionSet.new do |index|
66
+ index.thead.concat %w{title_header club_header races_header}
67
+ index.tbody.concat %w{title_cell club_cell races_cell}
68
+ index.bottom.concat %w{buttons}
69
+ end
70
+ end
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+ end