Class: Units

Inherits:
Object show all
Extended by:
ForwardReferencing
Defined in:
lib/units/units.rb

Overview

The Units framework

Units is the top level that you’ll typically never have to deal with directly. While it provides a few chunks of general functionality such as getting defined units and ranking, most of its guts are devoted to defining new UnitsMeasures - unless you’re setting up your own sets of specialized units, you will hardly know it’s here.

Constant Summary collapse

@@debug =
false
@@measures =
{}
@@units =
{}
@@defining =
nil
@@holding =
nil

Class Method Summary collapse

Class Method Details

.[](name) ⇒ Object

Returns the named UnitsMeasure.



102
103
104
# File 'lib/units/units.rb', line 102

def Units.[](name)
  @@measures[name.to_s]
end

.add_unit(unit, unit_identifier = nil) ⇒ Object

:nodoc:



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/units/units.rb', line 117

def Units.add_unit(unit,unit_identifier=nil) # :nodoc:
  if unit_identifier
    if (element = @@units[unit_identifier])
      @@units[unit_identifier] += [ unit ] unless element.index(unit)
    else
      @@units[unit_identifier] = [ unit ]
    end
  else
    add_unit unit, unit.name
    add_unit unit, unit.plural
    unit.abbrevs.each { |abbrev| add_unit unit, abbrev }
  end
end

.clearObject

Clears the Units framework of all defined elements.



89
90
91
92
93
94
# File 'lib/units/units.rb', line 89

def Units.clear
  @@measures.clear
  @@units.clear
  forward_references_clear
  self
end

.convert(numeric, unit_identifier) ⇒ Object

:nodoc:



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/units/units.rb', line 147

def Units.convert(numeric,unit_identifier) # :nodoc:
  puts "Units:convert #{numeric} #{unit_identifier}" if @@debug
  if (candidates = lookup(unit_identifier)).size == 0
    puts @@units.keys.sort.join(" ") if @@debug
    puts "  no candidates!" if @@debug
    raise MissingUnitsException.new(unit_identifier.to_s)
  elsif !defining?
    if candidates.size > 1
      raise AmbiguousUnitsException.new(unit_identifier.to_s)
    else
      unit = candidates[0]
      NumericWithUnits.new(numeric,unit)
    end
  else
    if candidates.size == 1
      units = candidates
    else
      units = candidates.select { |candidate|
        @@defining == candidate.units_system.units_measure }
      units = candidates.select { |candidate|
        @@defining.derived[candidate.units_measure] } if units.size == 0
    end
    case units.size
      when 0 then
        raise MissingUnitsException.new(unit_identifier.to_s)
      when 1 then 
        unit = units[0]
 if unit.equals.kind_of? Array
   element = unit.equals[0]
   value = NumericWithUnits.
            new(numeric*element.numeric,element.unit)
 else
   value = NumericWithUnits.
            new(numeric*unit.equals.numeric,unit.equals.unit)
 end
        value.original = numeric.unite(unit)
        value
      else
        raise AmbiguousUnitsException.new(unit_identifier.to_s)
    end
  end
end

.create(name, &block) ⇒ Object

Creates or extends a UnitsMeasure.



41
42
43
44
45
# File 'lib/units/units.rb', line 41

def Units.create(name, &block)
  measure = (@@measures[name.to_s] ||= UnitsMeasure.new)
  block.call measure if block_given?
  measure
end

.debug=(value) ⇒ Object



23
24
25
# File 'lib/units/units.rb', line 23

def self.debug=(value)
  @@debug = value
end

.defining(measure) ⇒ Object

:nodoc:



143
144
145
# File 'lib/units/units.rb', line 143

def Units.defining(measure) # :nodoc:
  @@defining = measure
end

.defining?Boolean

Answers the question of whether a UnitsMeasure is being defined with the instance if true, or nil if false.

Returns:

  • (Boolean)


139
140
141
# File 'lib/units/units.rb', line 139

def Units.defining?
  @@defining
end

.delete(name) ⇒ Object

Removes the named UnitsMeasure from the Units framework.



84
85
86
# File 'lib/units/units.rb', line 84

def Units.delete(name)
  @@measures.delete name.to_s
end

.derive(name, target, &block) ⇒ Object

Creates or extends a UnitsMeasure derived from other UnitsMeasures.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/units/units.rb', line 48

def Units.derive(name, target, &block)
  measure = ( @@measures[name.to_s] =
    if target.kind_of? UnitsMeasure
      if target.derived && (derived = find_by_derivation target.derived)
        derived
      else
        target
      end
    else
      Units.create(target.to_s)
    end )
  block.call measure if block_given?
  measure
end

.establish_forward_reference_context(context) ⇒ Object

:nodoc:



206
207
208
# File 'lib/units/units.rb', line 206

def Units.establish_forward_reference_context(context) # :nodoc:
  defining context
end

.find_by_derivation(derivation) ⇒ Object

Returns the UnitsMeasure with the given derivation.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/units/units.rb', line 64

def Units.find_by_derivation(derivation)
  matches = @@measures.values.uniq.select { |measure|
    if measure.derived
      measure == derivation
    elsif derivation.size == 1
      a = derivation.to_a[0]
      a[0] == measure and a[1] == 1
    else
      false
    end
  }
  case matches.size
    when 0 then nil
    when 1 then matches[0]
    else raise UnitsException.new(
        "Multiple UnitsMeasures with same derivation found")
  end
end

.hold_forward_reference(hold = true) ⇒ Object

:nodoc:



198
199
200
# File 'lib/units/units.rb', line 198

def Units.hold_forward_reference(hold = true) # :nodoc:
  @@holding = hold
end

.holding_forward_reference?Boolean

:nodoc:

Returns:

  • (Boolean)


202
203
204
# File 'lib/units/units.rb', line 202

def Units.holding_forward_reference? # :nodoc:
  @@holding
end

.lookup(unit_identifier) ⇒ Object

Returns an Array of UnitsUnit associated with a singular, plural or abbreviated name.



133
134
135
# File 'lib/units/units.rb', line 133

def Units.lookup(unit_identifier)
  @@units[unit_identifier.to_s] || [ ]
end

.make_forward_reference(method, context) ⇒ Object

:nodoc:



190
191
192
# File 'lib/units/units.rb', line 190

def Units.make_forward_reference(method,context) # :nodoc:
  @@holding ? nil : create_forward_reference(method,context)
end

.method_missing(method, *args) ⇒ Object

:nodoc:

Raises:



106
107
108
109
110
# File 'lib/units/units.rb', line 106

def Units.method_missing(method,*args) # :nodoc:
  measure = self[method]
  raise UnitsException.new("UnitsMeasure '#{method}' undefined") if !measure
  measure
end

.names_of(units_measure) ⇒ Object

Returns an Array containing the names of a given UnitsMeasure.



113
114
115
# File 'lib/units/units.rb', line 113

def Units.names_of(units_measure)
  @@measures.keys.select { |name| @@measures[name].equal? units_measure }
end

.rank(unit_choices = {}, samples = [], &numeric_ranker) ⇒ Object

Given a Hash of units to raking weights, a set of samples, and optionally a block that returns rankings, returns an Array of units ordered by best weighted fit over the samples. Like golf, low scores rank best. In absence of a block, ranking is based on the number of unit values whose magnitudes are between 1 and 10.



215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/units/units.rb', line 215

def Units.rank(unit_choices = {}, samples = [], &numeric_ranker) # :yields: n
  if block_given?
    scores = {}
    samples.each {|s|
      unit_choices.each {|uc,w|
        scores[uc] = (scores[uc] || 0) + w*(yield s.convert(uc).numeric) } }
    scores.sort {|e1,e2| -(e1[1] <=> e2[1])}.collect {|s| s[0]}
  else
    rank(unit_choices,samples) { |n|
      e = ((((n.abs)-5.5).abs-4.5).at_least(0))
      (e == 0) ? 0 : (e == 1)? 0 : -(e + 1/(1-e)) }
  end
end

.release_forward_reference(reference = nil) ⇒ Object

:nodoc:



194
195
196
# File 'lib/units/units.rb', line 194

def Units.release_forward_reference(reference = nil) # :nodoc:
  remove_forward_reference(reference) if reference != nil
end

.sizeObject

Returns the number of defined UnitsMeasures.



97
98
99
# File 'lib/units/units.rb', line 97

def Units.size
  @@measures.size
end

.units_measuresObject

Returns an Array of the defined UnitsMeasures.



36
37
38
# File 'lib/units/units.rb', line 36

def Units.units_measures
  @@measures.keys
end