Class: Eymiha::Units

Inherits:
Object show all
Extended by:
ForwardReferencing
Defined in:
lib/eymiha/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.



105
106
107
# File 'lib/eymiha/units/units.rb', line 105

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

.add_unit(unit, unit_identifier = nil) ⇒ Object

:nodoc:



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/eymiha/units/units.rb', line 120

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.



92
93
94
95
96
97
# File 'lib/eymiha/units/units.rb', line 92

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

.convert(numeric, unit_identifier) ⇒ Object

:nodoc:



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
189
190
191
# File 'lib/eymiha/units/units.rb', line 150

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.



43
44
45
46
47
# File 'lib/eymiha/units/units.rb', line 43

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

.debug=(value) ⇒ Object



25
26
27
# File 'lib/eymiha/units/units.rb', line 25

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

.defining(measure) ⇒ Object

:nodoc:



146
147
148
# File 'lib/eymiha/units/units.rb', line 146

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)


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

def Units.defining?
  @@defining
end

.delete(name) ⇒ Object

Removes the named UnitsMeasure from the Units framework.



87
88
89
# File 'lib/eymiha/units/units.rb', line 87

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

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

Creates or extends a UnitsMeasure derived from other UnitsMeasures.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/eymiha/units/units.rb', line 50

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:



209
210
211
# File 'lib/eymiha/units/units.rb', line 209

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

.find_by_derivation(derivation) ⇒ Object

Returns the UnitsMeasure with the given derivation.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/eymiha/units/units.rb', line 67

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,
            "Multiple UnitsMeasures with same derivation found"
  end
end

.hold_forward_reference(hold = true) ⇒ Object

:nodoc:



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

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

.holding_forward_reference?Boolean

:nodoc:

Returns:

  • (Boolean)


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

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.



136
137
138
# File 'lib/eymiha/units/units.rb', line 136

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

.make_forward_reference(method, context) ⇒ Object

:nodoc:



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

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

.method_missing(method, *args) ⇒ Object

:nodoc:

Raises:



109
110
111
112
113
# File 'lib/eymiha/units/units.rb', line 109

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.



116
117
118
# File 'lib/eymiha/units/units.rb', line 116

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.



218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/eymiha/units/units.rb', line 218

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:



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

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

.sizeObject

Returns the number of defined UnitsMeasures.



100
101
102
# File 'lib/eymiha/units/units.rb', line 100

def Units.size
  @@measures.size
end

.units_measuresObject

Returns an Array of the defined UnitsMeasures.



38
39
40
# File 'lib/eymiha/units/units.rb', line 38

def Units.units_measures
  @@measures.keys
end