| Class | RaceNumber |
| In: |
app/models/race_number.rb
|
| Parent: | ActiveRecord::Base |
Number used to identify a Person during a Race: bib number. RaceNumbers are issued from a NumberIssuer, which is usually a racing Association, but sometimes an Event.
In the past, RaceNumbers had to be unique for NumberIssuer, Discipline and year. But we allow duplicates now.
Value is the number on the physical number plate. RaceNumber values can have letters and numbers
This all may seem to be a case or over-modelling, but it refleccts how numbers are used by promoters and associations. PersonNumbers are also used to differentiate between People with the same name, and to identify person results with misspelled names.
Dupe of lousy code from Discipline
# File app/models/race_number.rb, line 45
45: def RaceNumber.discipline_id(discipline)
46: case Discipline[discipline]
47: when Discipline[:road], Discipline[:track], Discipline[:time_trial], Discipline[:circuit], Discipline[:criterium]
48: Discipline[:road].id
49: when Discipline[:cyclocross]
50: Discipline[:cyclocross].id
51: when Discipline[:mountain_bike], Discipline[:super_d]
52: Discipline[:mountain_bike].id
53: when Discipline[:downhill]
54: Discipline[:downhill].id
55: else
56: Discipline[:road].id
57: end
58: end
# File app/models/race_number.rb, line 27
27: def RaceNumber.find_all_by_value_and_event(value, _event)
28: return [] if _event.nil? || value.blank? || _event.number_issuer.nil?
29:
30: discipline_id = RaceNumber.discipline_id(_event.discipline)
31: return [] unless discipline_id
32:
33: race_numbers = RaceNumber.find(
34: :all,
35: :conditions => ['value=? and discipline_id = ? and number_issuer_id=? and year=?',
36: value,
37: discipline_id,
38: _event.number_issuer.id,
39: _event.date.year],
40: :include => :person
41: )
42: end
Different disciplines have different rules about what is a rental number
# File app/models/race_number.rb, line 61
61: def RaceNumber.rental?(number, discipline = Discipline[:road])
62: if RacingAssociation.current.rental_numbers.nil?
63: return false
64: end
65:
66: if number.blank?
67: return true
68: end
69:
70: if RacingAssociation.current.rental_numbers.nil? || discipline == Discipline[:mountain_bike] || discipline == Discipline[:downhill] || number.strip[/^\d+$/].nil?
71: return false
72: end
73:
74: numeric_value = number.to_i
75: if RacingAssociation.current.rental_numbers.include?(numeric_value)
76: return true
77: end
78:
79: false
80: end
# File app/models/race_number.rb, line 138
138: def <=>(other)
139: if other
140: value <=> other.value
141: else
142: -1
143: end
144: end
Default to Road, RacingAssociation.current, and current year
# File app/models/race_number.rb, line 83
83: def defaults
84: self.discipline = Discipline[:road] unless self.discipline
85: self.number_issuer = NumberIssuer.find_by_name(RacingAssociation.current.short_name) unless self.number_issuer
86: self.year = RacingAssociation.current.effective_year unless (self.year and self.year > 1800)
87: end
# File app/models/race_number.rb, line 89
89: def get_person_id
90: if person && (person.new_record? || person.changed?)
91: person.reload
92: end
93: end
# File app/models/race_number.rb, line 146
146: def to_s
147: "<RaceNumber (#{id}) (#{value}) (#{person_id}) (#{number_issuer_id}) (#{discipline_id}) (#{year})>"
148: end
Checks that Person doesn‘t already have this number.
Numbers are unique by value, Person, Discipline, NumberIssuer, and year.
Skips check if person is not set. Typically, this happens when importing a Result that has a number, but no person
OBRA rental numbers (11-99) are not valid
# File app/models/race_number.rb, line 107
107: def unique_number
108: _discipline = Discipline.find(self[:discipline_id])
109: if RaceNumber.rental?(self[:value], _discipline)
110: errors.add('value', "#{value} is a rental number. #{RacingAssociation.current.short_name} rental numbers: #{RacingAssociation.current.rental_numbers}")
111: person.errors.add('value', "#{value} is a rental number. #{RacingAssociation.current.short_name} rental numbers: #{RacingAssociation.current.rental_numbers}")
112: return false
113: end
114:
115: return true if person.nil?
116:
117: if new_record?
118: existing_numbers = RaceNumber.count(
119: :conditions => ['value=? and discipline_id=? and number_issuer_id=? and year=? and person_id = ?',
120: self[:value], self[:discipline_id], self[:number_issuer_id], self[:year], person.id])
121: else
122: existing_numbers = RaceNumber.count(
123: :conditions => ['value=? and discipline_id=? and number_issuer_id=? and year=? and id<>? and person_id = ?',
124: self[:value], self[:discipline_id], self[:number_issuer_id], self[:year], self.id, person.id])
125: end
126:
127: unless existing_numbers == 0
128: person_id = person.id
129: errors.add('value', "Number '#{value}' can't be used for #{person.name}. Already used as #{year} #{number_issuer.name} #{discipline.name.downcase} number.")
130: person.errors.add('value', "Number '#{value}' can't be used for #{person.name}. Already used as #{year} #{number_issuer.name} #{discipline.name.downcase} number.")
131: if existing_numbers.size > 1
132: logger.warn("Race number '#{value}' found #{existing_numbers} times for discipline #{discipline_id}, number issuer #{number_issuer_id}, year #{year}, person #{person_id}")
133: end
134: return false
135: end
136: end