Class Overall
In: app/models/competitions/overall.rb
Parent: Competition

Common superclass for Omniums and Series standings. Easy to miss override: Overall results only include members

Methods

Public Class methods

[Source]

    # File app/models/competitions/overall.rb, line 7
 7:   def Overall.calculate!(year = Date.today.year)
 8:     benchmark("#{name} calculate!", Logger::INFO, false) {
 9:       transaction do
10:         parent = MultiDayEvent.find(
11:                         :first, 
12:                         :conditions => ["name = ? and date between ? and ?", parent_name, Date.new(year, 1, 1), Date.new(year, 12, 31)])
13:                         
14:         if parent && parent.has_results_including_children?(true)
15:           unless parent.overall
16:             # parent.create_overall will create an instance of Overall, which is probably not what we want
17:             parent.overall = self.new(:parent_id => parent.id)
18:             parent.overall.save!
19:           end
20:           parent.overall.destroy_races
21:           parent.overall.create_races
22:           parent.overall.calculate!
23:         end
24:       end
25:     }
26:     true
27:   end

Public Instance methods

[Source]

    # File app/models/competitions/overall.rb, line 29
29:   def add_source_events
30:     parent.children.each do |source_event|
31:       source_events << source_event
32:     end
33:   end

By default, does nothing. Useful to apply rule like:

  • Any results after the first four only get 50-point bonus
  • Drop lowest-scoring result

[Source]

     # File app/models/competitions/overall.rb, line 111
111:   def after_create_competition_results_for(race)
112:     race.results.each do |result|
113:       # Don't bother sorting scores unless we need to drop some
114:       if result.scores.size > 6
115:         result.scores.sort! { |x, y| y.points <=> x.points }
116:         lowest_scores = result.scores[6, 2]
117:         lowest_scores.each do |lowest_score|
118:           result.scores.destroy(lowest_score)
119:         end
120:         # Rails destroys Score in database, but doesn't update the current association
121:         result.scores(true)
122:       end
123:     
124:       if preliminary?(result)
125:         result.preliminary = true       
126:       end    
127:     end
128:   end

If same rider places twice in same race, only highest result counts

[Source]

     # File app/models/competitions/overall.rb, line 68
 68:   def create_competition_results_for(results, race)
 69:     competition_result = nil
 70:     results.each_with_index do |source_result, index|
 71:       logger.debug("#{self.class.name} scoring result: #{source_result.date} race: #{source_result.race.name} pl: #{source_result.place} mem pl: #{source_result.members_only_place if place_members_only?} #{source_result.last_name} #{source_result.team_name}") if logger.debug?
 72: 
 73:       person = source_result.person
 74:       points = points_for(source_result)
 75:       
 76:       # We repeat some calculations here if a person is disallowed
 77:       if points > 0.0 && 
 78:          (!parent.completed? || (parent.completed? && raced_minimum_events?(person, race))) && 
 79:            (!members_only? || member?(person, source_result.date))
 80: 
 81:         if first_result_for_person(source_result, competition_result)
 82:           # Intentionally not using results association create method. No need to hang on to all competition results.
 83:           # In fact, this could cause serious memory issues with the Ironman
 84:           competition_result = Result.create!(
 85:              :person => person, 
 86:              :team => (person ? person.team : nil),
 87:              :race => race)
 88:         end
 89: 
 90:         competition_result.scores.create_if_best_result_for_race(
 91:           :source_result => source_result, 
 92:           :competition_result => competition_result, 
 93:           :points => points
 94:         )
 95:       end
 96: 
 97:       # Aggressive memory management. If competition has a race with many results, 
 98:       # the results array can become a large, uneeded, structure
 99:       results[index] = nil
100:       if index > 0 && index % 1000 == 0
101:         logger.debug("GC start after record #{index}")
102:         GC.start
103:       end
104: 
105:     end
106:   end

[Source]

     # File app/models/competitions/overall.rb, line 166
166:   def date
167:     if source_events.any?
168:       source_events.sort.first.date
169:     else
170:       parent.start_date
171:     end
172:   end

Last day of year for date

[Source]

     # File app/models/competitions/overall.rb, line 180
180:   def end_date
181:     if source_events.any?
182:       source_events.sort.last.date
183:     else
184:       parent.end_date
185:     end
186:   end

Only members can score points?

[Source]

     # File app/models/competitions/overall.rb, line 131
131:   def members_only?
132:     false 
133:   end

[Source]

     # File app/models/competitions/overall.rb, line 135
135:   def minimum_events
136:     nil
137:   end

[Source]

     # File app/models/competitions/overall.rb, line 159
159:   def preliminary?(result)
160:     minimum_events && 
161:     parent.children_with_results.size > minimum_events && 
162:     !parent.completed? && 
163:     !raced_minimum_events?(result.person, result.race)
164:   end

[Source]

     # File app/models/competitions/overall.rb, line 139
139:   def raced_minimum_events?(person, race)
140:     return true if minimum_events.nil?
141:     return false if parent.children.empty? || person.nil?
142: 
143:     event_ids = parent.children.collect(&:id).join(", ")
144:     category_ids = category_ids_for(race)
145: 
146:     count = Result.count_by_sql(
147:       %Q{ SELECT count(*) FROM results  
148:           JOIN races ON races.id = results.race_id 
149:           JOIN categories ON categories.id = races.category_id 
150:           JOIN events ON races.event_id = events.id 
151:           WHERE categories.id in (#{category_ids})
152:               and events.id in (#{event_ids})
153:               and results.person_id = #{person.id}
154:        }
155:     )
156:     count >= minimum_events
157:   end

source_results must be in person-order

[Source]

    # File app/models/competitions/overall.rb, line 45
45:   def source_results(race)
46:     return [] if parent.children.empty?
47:     
48:     event_ids = parent.children.collect do |event|
49:       event.id
50:     end
51:     event_ids = event_ids.join(', ')
52:     category_ids = category_ids_for(race)
53:     
54:     Result.find_by_sql(
55:       %Q{ SELECT results.* FROM results  
56:           JOIN races ON races.id = results.race_id 
57:           JOIN categories ON categories.id = races.category_id 
58:           JOIN events ON races.event_id = events.id 
59:           WHERE place between 1 and #{point_schedule.size - 1}
60:               and categories.id in (#{category_ids})
61:               and events.id in (#{event_ids})
62:           order by person_id
63:        }
64:     )
65:   end

[Source]

    # File app/models/competitions/overall.rb, line 35
35:   def source_results_with_benchmark(race)
36:     results = []
37:     Overall.benchmark("#{self.class.name} source_results", Logger::DEBUG, false) {
38:       results = source_results(race)
39:     }
40:     logger.debug("#{self.class.name} Found #{results.size} source results for '#{race.name}'") if logger.debug?
41:     results
42:   end

Same as date. Should always be January 1st

[Source]

     # File app/models/competitions/overall.rb, line 175
175:   def start_date
176:     date
177:   end

[Validate]