| Class | Bar |
| In: |
app/models/competitions/bar.rb
|
| Parent: | Competition |
Best All-around Rider Competition. Assigns points for each top-15 placing in major Disciplines: road, track, etc. Calculates a BAR for each Discipline, and an Overall BAR that combines all the discipline BARs. Also calculates a team BAR. Recalculating the BAR at years-end can take nearly 30 minutes even on a fast server. Recalculation must be manually triggered. This class implements a number of OBRA-specific rules and should be generalized and simplified. The BAR categories and disciplines are all configured in the database. Race categories need to have a bar_category_id to show up in the BAR; disciplines must exist in the disciplines table and discipline_bar_categories.
# File app/models/competitions/bar.rb, line 11
11: def Bar.calculate!(year = Date.today.year)
12: benchmark(name, Logger::INFO, false) {
13: transaction do
14: year = year.to_i if year.is_a?(String)
15: date = Date.new(year, 1, 1)
16:
17: overall_bar = OverallBar.find_or_create_for_year(year)
18:
19: # Age Graded BAR, Team BAR and Overall BAR do their own calculations
20: Discipline.find_all_bar.reject { |discipline|
21: [ Discipline[:age_graded], Discipline[:overall], Discipline[:team] ].include?(discipline)
22: }.each do |discipline|
23: bar = Bar.find(:first, :conditions => { :date => date, :discipline => discipline.name })
24: unless bar
25: bar = Bar.create!(
26: :parent => overall_bar,
27: :name => "#{year} #{discipline.name} BAR",
28: :date => date,
29: :discipline => discipline.name
30: )
31: end
32: end
33:
34: Bar.find(:all, :conditions => { :date => date }).each do |bar|
35: bar.destroy_races
36: bar.create_races
37: # Could bulk load all Event and Races at this point, but hardly seems to matter
38: bar.calculate!
39: end
40: end
41: }
42: # Don't return the entire populated instance!
43: true
44: end
# File app/models/competitions/bar.rb, line 46
46: def Bar.find_by_year_and_discipline(year, discipline_name)
47: Bar.find(:first, :conditions => { :date => Date.new(year), :discipline => discipline_name })
48: end
# File app/models/competitions/bar.rb, line 119
119: def create_races
120: Discipline[discipline].bar_categories.each do |category|
121: races.create!(:category => category)
122: end
123: end
# File app/models/competitions/bar.rb, line 50
50: def point_schedule
51: [ 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
52: end
Apply points from point_schedule, and adjust for field size
# File app/models/competitions/bar.rb, line 105
105: def points_for(source_result, team_size = nil)
106: points = 0
107: Bar.benchmark('points_for') {
108: field_size = source_result.race.field_size
109:
110: team_size = team_size || Result.count(:conditions => ["race_id =? and place = ?", source_result.race.id, source_result.place])
111: points = point_schedule[source_result.place.to_i] * source_result.race.bar_points / team_size.to_f
112: if source_result.race.bar_points == 1 and field_size >= 75
113: points = points * 1.5
114: end
115: }
116: points
117: end
Source result = counts towards the BAR "race" and BAR results Example: Piece of Cake RR, 6th, Jon Knowlson
bar_result, bar_race = BAR itself and placing in the BAR Example: Senior Men BAR, 130th, Jon Knowlson, 45 points
BAR results add scoring results as scores Example: Senior Men BAR, 130th, Jon Knowlson, 18 points
- Piece of Cake RR, 6th, Jon Knowlson 10 points - Silverton RR, 8th, Jon Knowlson 8 points
# File app/models/competitions/bar.rb, line 65
65: def source_results(race)
66: race_disciplines = case race.discipline
67: when "Road"
68: "'Road', 'Circuit'"
69: when "Mountain Bike"
70: "'Mountain Bike', 'Downhill', 'Super D'"
71: else
72: "'#{race.discipline}'"
73: end
74:
75: # Cat 4/5 is a special case. Can't config in database because it's a circular relationship.
76: category_ids = category_ids_for(race)
77: category_4_5_men = Category.find_by_name("Category 4/5 Men")
78: category_4_men = Category.find_by_name("Category 4 Men")
79: if category_4_5_men && category_4_men && race.category == category_4_men
80: category_ids << ", #{category_4_5_men.id}"
81: end
82:
83: Result.find(:all,
84: :include => [:race, {:person => :team}, :team, {:race => [{:event => { :parent => :parent }}, :category]}],
85: :conditions => [%Q{
86: place between 1 AND #{point_schedule.size - 1}
87: and (events.type in ('Event', 'SingleDayEvent', 'MultiDayEvent', 'Series', 'WeeklySeries', 'TaborOverall') or events.type is NULL)
88: and bar = true
89: and events.sanctioned_by = "#{RacingAssociation.current.default_sanctioned_by}"
90: and categories.id in (#{category_ids})
91: and (events.discipline in (#{race_disciplines})
92: or (events.discipline is null and parents_events.discipline in (#{race_disciplines}))
93: or (events.discipline is null and parents_events.discipline is null and parents_events_2.discipline in (#{race_disciplines})))
94: and (races.bar_points > 0
95: or (races.bar_points is null and events.bar_points > 0)
96: or (races.bar_points is null and events.bar_points is null and parents_events.bar_points > 0)
97: or (races.bar_points is null and events.bar_points is null and parents_events.bar_points is null and parents_events_2.bar_points > 0))
98: and events.date between '#{date.year}-01-01' and '#{date.year}-12-31'
99: }],
100: :order => 'person_id'
101: )
102: end