m9t 0.1.12 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +38 -0
- data/Rakefile +12 -27
- data/lib/m9t.rb +1 -8
- data/lib/m9t/base.rb +78 -16
- data/lib/m9t/direction.rb +16 -10
- data/lib/m9t/distance.rb +6 -65
- data/lib/m9t/pressure.rb +7 -31
- data/lib/m9t/speed.rb +9 -75
- data/lib/m9t/temperature.rb +9 -15
- data/lib/m9t/version.rb +11 -0
- data/test/direction_test.rb +26 -18
- data/test/distance_test.rb +67 -45
- data/test/speed_test.rb +20 -7
- data/test/temperature_test.rb +21 -6
- metadata +24 -22
data/README.rdoc
CHANGED
@@ -11,6 +11,44 @@ The emphasis is on:
|
|
11
11
|
* coherent interface,
|
12
12
|
* ease of translation (using i18n).
|
13
13
|
|
14
|
+
== Internals
|
15
|
+
|
16
|
+
Internally, values are stored in SI units, with the exception of temperature:
|
17
|
+
* distance - meters,
|
18
|
+
* direction - degrees,
|
19
|
+
* speed - meters per second,
|
20
|
+
* temperature - degrees celcius,
|
21
|
+
* weight - kilograms.
|
22
|
+
|
23
|
+
== Interface
|
24
|
+
|
25
|
+
new: accepts the S.I. unit as a parameter:
|
26
|
+
|
27
|
+
height = M9t::Distance.new(1.75)
|
28
|
+
|
29
|
+
to_f: returns the decimal value(s):
|
30
|
+
|
31
|
+
height.to_f -> 1.75
|
32
|
+
|
33
|
+
other units:
|
34
|
+
there are class methods named after each known unit,
|
35
|
+
which take values in that unit
|
36
|
+
(actually, they are defined as needed):
|
37
|
+
|
38
|
+
marathon = M9t::Distance.miles(26.21875)
|
39
|
+
marathon.to_f -> 42194.988
|
40
|
+
|
41
|
+
to_s: returns a localized string with units:
|
42
|
+
|
43
|
+
I18n.locale = :it
|
44
|
+
puts M9t::Distance.new(3).to_s -> '3 metri'
|
45
|
+
|
46
|
+
=== Class methods for conversion
|
47
|
+
|
48
|
+
Methods are available for conversion between any pair of units:
|
49
|
+
|
50
|
+
M9t::Distance.miles_to_meters(26.21875) -> 42194.988
|
51
|
+
|
14
52
|
== Other Software
|
15
53
|
|
16
54
|
* ruby-units
|
data/Rakefile
CHANGED
@@ -1,42 +1,20 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'rake/gempackagetask'
|
3
2
|
require 'rake/rdoctask'
|
4
3
|
require 'rake/testtask'
|
5
4
|
require 'rake/clean'
|
6
5
|
|
7
|
-
$:.unshift(File.dirname(__FILE__) + '/lib')
|
8
|
-
require
|
6
|
+
$:.unshift( File.dirname(__FILE__) + '/lib' )
|
7
|
+
require "bundler/version"
|
9
8
|
|
10
9
|
RDOC_OPTS = ['--quiet', '--title', 'm9t: Measurement units', '--main', 'README.rdoc', '--inline-source']
|
11
10
|
CLEAN.include 'doc'
|
12
11
|
|
13
12
|
task :default => :test
|
14
13
|
|
15
|
-
spec = Gem::Specification.new do |s|
|
16
|
-
s.name = 'm9t'
|
17
|
-
s.summary = 'Classes for handling measurement units'
|
18
|
-
s.description = 'Classes for handling measurement units, conversions and translations'
|
19
|
-
s.version = M9t::VERSION::STRING
|
20
|
-
|
21
|
-
s.homepage = 'http://github.com/joeyates/m9t'
|
22
|
-
s.author = 'Joe Yates'
|
23
|
-
s.email = 'joe.g.yates@gmail.com'
|
24
|
-
|
25
|
-
s.files = ['README.rdoc', 'COPYING', 'Rakefile'] + FileList['{lib,test}/**/*.rb'] + FileList['locales/**/*.{rb,yml}']
|
26
|
-
s.require_paths = ['lib']
|
27
|
-
s.add_dependency('i18n', '>= 0.3.5')
|
28
|
-
|
29
|
-
s.has_rdoc = true
|
30
|
-
s.rdoc_options += RDOC_OPTS
|
31
|
-
s.extra_rdoc_files = ['README.rdoc', 'COPYING']
|
32
|
-
|
33
|
-
s.test_file = 'test/test_all.rb'
|
34
|
-
end
|
35
|
-
|
36
14
|
Rake::TestTask.new do |t|
|
37
|
-
t.libs
|
15
|
+
t.libs << 'test'
|
38
16
|
t.test_files = FileList['test/*_test.rb']
|
39
|
-
t.verbose
|
17
|
+
t.verbose = true
|
40
18
|
end
|
41
19
|
|
42
20
|
Rake::RDocTask.new do |rdoc|
|
@@ -46,5 +24,12 @@ Rake::RDocTask.new do |rdoc|
|
|
46
24
|
rdoc.rdoc_files.add ['README.rdoc', 'COPYING', 'lib/**/*.rb']
|
47
25
|
end
|
48
26
|
|
49
|
-
|
27
|
+
desc "Build the gem"
|
28
|
+
task :build do
|
29
|
+
system "gem build m9t.gemspec"
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Publish a new version of the gem"
|
33
|
+
task :release => :build do
|
34
|
+
system "gem push m9t-#{M9t::VERSION}"
|
50
35
|
end
|
data/lib/m9t.rb
CHANGED
@@ -27,6 +27,7 @@ require 'i18n'
|
|
27
27
|
|
28
28
|
locales_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'locales'))
|
29
29
|
I18n.load_path += Dir.glob("#{ locales_path }/*.yml")
|
30
|
+
I18n.reload!
|
30
31
|
|
31
32
|
Dir[File.dirname(__FILE__) + '/m9t/*.rb'].each do |file|
|
32
33
|
require file
|
@@ -34,14 +35,6 @@ end
|
|
34
35
|
|
35
36
|
module M9t
|
36
37
|
|
37
|
-
module VERSION #:nodoc:
|
38
|
-
MAJOR = 0
|
39
|
-
MINOR = 1
|
40
|
-
TINY = 12
|
41
|
-
|
42
|
-
STRING = [MAJOR, MINOR, TINY].join('.')
|
43
|
-
end
|
44
|
-
|
45
38
|
# Base class for all M9t exceptions
|
46
39
|
class M9tError < StandardError
|
47
40
|
end
|
data/lib/m9t/base.rb
CHANGED
@@ -6,10 +6,49 @@ module M9t
|
|
6
6
|
|
7
7
|
module Base
|
8
8
|
|
9
|
-
def self.
|
9
|
+
def self.generate_conversions(klass)
|
10
|
+
klass.instance_eval do |klass|
|
11
|
+
def convert(from, to, value)
|
12
|
+
value * self::CONVERSIONS[from] / self::CONVERSIONS[to]
|
13
|
+
end
|
10
14
|
|
11
|
-
|
15
|
+
def method_missing(name, *args, &block)
|
16
|
+
# Define class conversion methods as required
|
17
|
+
if name.to_s =~ /^(\w+)_to_(\w+)$/
|
18
|
+
return send(name, args[0]) if define_conversion($1, $2)
|
19
|
+
end
|
20
|
+
return send(name, args[0]) if define_constructor(name)
|
21
|
+
raise "Method '#{ name }' unknown" # TODO use standard exception
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def define_conversion(from, to)
|
27
|
+
return false if not self::CONVERSIONS[from.to_sym]
|
28
|
+
return false if not self::CONVERSIONS[to.to_sym]
|
29
|
+
self.class.instance_exec do
|
30
|
+
define_method("#{ from }_to_#{ to }") do |value|
|
31
|
+
convert(from.to_sym, to.to_sym, value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Define klass.unit(value) which converts the parameter
|
38
|
+
# from the unit and returns an instance
|
39
|
+
def define_constructor(name)
|
40
|
+
return false if not self::CONVERSIONS[name.to_sym]
|
41
|
+
self.class.instance_exec do
|
42
|
+
define_method( name.to_sym ) do | *args |
|
43
|
+
new( args[ 0 ].to_f * self::CONVERSIONS[ name ] )
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
12
49
|
|
50
|
+
def self.add_options(klass)
|
51
|
+
klass.instance_eval do
|
13
52
|
# Make sure derived classes get the extra methods
|
14
53
|
def inherited(sub) #:nodoc:
|
15
54
|
sub.instance_eval do
|
@@ -33,43 +72,66 @@ module M9t
|
|
33
72
|
name.downcase.split('::')[1]
|
34
73
|
end
|
35
74
|
|
75
|
+
def default_unit
|
76
|
+
self::DEFAULT_OPTIONS[:units]
|
77
|
+
end
|
78
|
+
|
36
79
|
reset_options!
|
37
80
|
end
|
38
|
-
|
39
81
|
end
|
40
82
|
|
41
83
|
# Adds methods for handling options
|
42
84
|
def self.included(base) #:nodoc:
|
43
85
|
M9t::Base.add_options(base)
|
86
|
+
M9t::Base.generate_conversions(base)
|
44
87
|
end
|
45
88
|
|
46
89
|
attr_reader :value, :options
|
90
|
+
alias :to_f :value
|
91
|
+
|
92
|
+
def initialize( value )
|
93
|
+
@value = value.to_f
|
94
|
+
end
|
47
95
|
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
96
|
+
# define conversion instance methods as required
|
97
|
+
def method_missing(name, *args, &block)
|
98
|
+
if name.to_s =~ /^to_(\w+)$/
|
99
|
+
return send(name, @value) if define_conversion($1)
|
100
|
+
end
|
101
|
+
raise "Method '#{ name }' unknown" # TODO use standard exception
|
53
102
|
end
|
54
103
|
|
55
104
|
# Returns the string representation of the measurement,
|
56
105
|
# taking into account locale, desired units and abbreviation.
|
57
|
-
def to_s
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
106
|
+
def to_s( options = {} )
|
107
|
+
options = self.class.options.merge( options )
|
108
|
+
units_error( options[ :units ] ) if not self.class::CONVERSIONS.has_key?( options[ :units ] )
|
109
|
+
value_in_units = self.send("to_#{ options[:units] }")
|
110
|
+
localized_value = I18n.localize_float(value_in_units, {:format => "%0.#{ options[:precision] }f"})
|
111
|
+
|
112
|
+
key = 'units.' + self.class.measurement_name + '.' + options[:units].to_s
|
113
|
+
options[:abbreviated] ? key += '.abbreviated' : key += '.full'
|
63
114
|
unit = I18n.t(key, {:count => value_in_units})
|
64
115
|
|
65
|
-
"#{ localized_value }%s#{ unit }" % (
|
116
|
+
"#{ localized_value }%s#{ unit }" % (options[:abbreviated] ? '' : ' ')
|
66
117
|
end
|
67
118
|
|
68
119
|
private
|
69
120
|
|
70
121
|
def units_error(units)
|
71
|
-
raise M9t::UnitError.new("Unknown units '#{ units }'. Known: #{ self.class::
|
122
|
+
raise M9t::UnitError.new("Unknown units '#{ units }'. Known: #{ self.class::CONVERSIONS.keys.collect{|unit| unit.to_s}.join(', ') }")
|
72
123
|
end
|
124
|
+
|
125
|
+
def define_conversion(to)
|
126
|
+
return false if not self.class::CONVERSIONS[to.to_sym]
|
127
|
+
self.class.instance_exec do
|
128
|
+
define_method("to_#{ to }") do
|
129
|
+
self.class.convert(self.class.default_unit, to.to_sym, self.to_f)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
73
135
|
end
|
74
136
|
|
75
137
|
end
|
data/lib/m9t/direction.rb
CHANGED
@@ -7,7 +7,10 @@ module M9t
|
|
7
7
|
# Represents a geographical direction
|
8
8
|
class Direction
|
9
9
|
DEFAULT_OPTIONS = {:units => :degrees, :abbreviated => false, :decimals => 5}
|
10
|
-
|
10
|
+
CONVERSIONS = {
|
11
|
+
:degrees => 1.0,
|
12
|
+
:compass => nil,
|
13
|
+
}
|
11
14
|
|
12
15
|
# Conversions
|
13
16
|
CIRCLE = 360.0
|
@@ -17,18 +20,17 @@ module M9t
|
|
17
20
|
|
18
21
|
class << self
|
19
22
|
|
20
|
-
# Identity conversion. Simply returns the supplied number
|
21
|
-
def to_degrees(degrees)
|
22
|
-
degrees.to_f
|
23
|
-
end
|
24
|
-
|
25
23
|
# Given a value in degrees, returns the nearest (localized) compass direction
|
26
24
|
# M9t::Directions.to_compass(42) => 'NE'
|
27
|
-
def
|
25
|
+
def degrees_to_compass(degrees)
|
28
26
|
sector = (normalize(degrees) / COMPASS_SECTOR_DEGREES).round
|
29
27
|
I18n.t(self.measurement_name + '.sectors')[sector]
|
30
28
|
end
|
31
29
|
|
30
|
+
def compass_to_degrees(compass_direction)
|
31
|
+
compass(compass_direction).to_f
|
32
|
+
end
|
33
|
+
|
32
34
|
# Accepts a localized compass direction (e.g. 'N') and returns the equivalent M9t::Direction
|
33
35
|
# M9t::Direction.compass('NE') => #<M9t::Direction:0xb76cc750 @value=45.0, @options={:units=>:degrees, :decimals=>5, :abbreviated=>false}>
|
34
36
|
def compass(compass_direction)
|
@@ -53,14 +55,18 @@ module M9t
|
|
53
55
|
end
|
54
56
|
|
55
57
|
# Handles the special case where compass directions are the desired output.
|
56
|
-
def to_s
|
57
|
-
if
|
58
|
-
Direction.
|
58
|
+
def to_s( options = {} )
|
59
|
+
if options[:units] == :compass
|
60
|
+
Direction.degrees_to_compass(@value)
|
59
61
|
else
|
60
62
|
super
|
61
63
|
end
|
62
64
|
end
|
63
65
|
|
66
|
+
def to_compass
|
67
|
+
self.class.degrees_to_compass(@value)
|
68
|
+
end
|
69
|
+
|
64
70
|
end
|
65
71
|
|
66
72
|
end
|
data/lib/m9t/distance.rb
CHANGED
@@ -8,76 +8,17 @@ module M9t
|
|
8
8
|
# Represents a distance
|
9
9
|
class Distance
|
10
10
|
DEFAULT_OPTIONS = {:units => :meters, :abbreviated => false, :precision => 5}
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
CONVERSIONS = {
|
12
|
+
:meters => 1.0,
|
13
|
+
:kilometers => 1000.0,
|
14
|
+
:feet => 0.3048,
|
15
|
+
:miles => 1609.344
|
16
|
+
}
|
17
17
|
|
18
18
|
include M9t::Base
|
19
19
|
|
20
|
-
class << self
|
21
|
-
|
22
|
-
# Alias for new
|
23
|
-
def meters(*args)
|
24
|
-
new(*args)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Accepts a value in kilometers and returns the equivalent M9t::Distance
|
28
|
-
def kilometers(km, options = {})
|
29
|
-
new(km.to_f * KILOMETER, options)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Accepts a value in miles and returns the equivalent M9t::Distance
|
33
|
-
def miles(miles, options = {})
|
34
|
-
new(miles.to_f * MILE, options)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Accepts a value in miles and returns the equivalent M9t::Distance
|
38
|
-
def feet(feet, options = {})
|
39
|
-
new(feet.to_f * FOOT, options)
|
40
|
-
end
|
41
|
-
|
42
|
-
# Identity conversion. Simply returns the supplied number
|
43
|
-
def to_meters(meters)
|
44
|
-
meters.to_f
|
45
|
-
end
|
46
|
-
|
47
|
-
# Converts meters into kilometers
|
48
|
-
def to_kilometers(meters)
|
49
|
-
meters.to_f / KILOMETER
|
50
|
-
end
|
51
|
-
|
52
|
-
# Converts meters into miles
|
53
|
-
def to_miles(meters)
|
54
|
-
meters.to_f / MILE
|
55
|
-
end
|
56
|
-
|
57
|
-
# Converts meters into miles
|
58
|
-
def to_feet(meters)
|
59
|
-
meters.to_f / FOOT
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
20
|
alias :to_meters :value
|
65
21
|
|
66
|
-
# Returns the value converted to kilometers
|
67
|
-
def to_kilometers
|
68
|
-
self.class.to_kilometers(@value)
|
69
|
-
end
|
70
|
-
|
71
|
-
# Returns the value converted to miles
|
72
|
-
def to_miles
|
73
|
-
self.class.to_miles(@value)
|
74
|
-
end
|
75
|
-
|
76
|
-
# Returns the value converted to feet
|
77
|
-
def to_feet
|
78
|
-
self.class.to_feet(@value)
|
79
|
-
end
|
80
|
-
|
81
22
|
end
|
82
23
|
|
83
24
|
end
|
data/lib/m9t/pressure.rb
CHANGED
@@ -8,40 +8,16 @@ module M9t
|
|
8
8
|
# Represents atmospheric (or other) pressure
|
9
9
|
class Pressure
|
10
10
|
DEFAULT_OPTIONS = {:units => :bar, :abbreviated => false, :precision => 5}
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
CONVERSIONS = {
|
12
|
+
:bar => 1.0,
|
13
|
+
:pascals => 0.00001,
|
14
|
+
:hectopascals => 0.001,
|
15
|
+
:kilopascals => 0.01,
|
16
|
+
:inches_of_mercury => 3386.389 * 0.00001
|
17
|
+
}
|
18
18
|
|
19
19
|
include M9t::Base
|
20
20
|
|
21
|
-
def Pressure.hectopascals(hectopascals)
|
22
|
-
new(hectopascals * HECTOPASCAL)
|
23
|
-
end
|
24
|
-
|
25
|
-
def Pressure.inches_of_mercury(inches_of_mercury)
|
26
|
-
new(inches_of_mercury * INCH_OF_MERCURY)
|
27
|
-
end
|
28
|
-
|
29
|
-
def Pressure.to_inches_of_mercury(bar)
|
30
|
-
bar / INCH_OF_MERCURY
|
31
|
-
end
|
32
|
-
|
33
|
-
def Pressure.to_bar(bar)
|
34
|
-
bar.to_f
|
35
|
-
end
|
36
|
-
|
37
|
-
def to_inches_of_mercury
|
38
|
-
Pressure.to_inches_of_mercury(@value)
|
39
|
-
end
|
40
|
-
|
41
|
-
def to_bar
|
42
|
-
Pressure.to_bar(@value)
|
43
|
-
end
|
44
|
-
|
45
21
|
end
|
46
22
|
|
47
23
|
end
|
data/lib/m9t/speed.rb
CHANGED
@@ -8,88 +8,22 @@ module M9t
|
|
8
8
|
# Represents a speed
|
9
9
|
class Speed
|
10
10
|
DEFAULT_OPTIONS = {:units => :meters_per_second, :abbreviated => false, :precision => 5}
|
11
|
-
KNOWN_UNITS = [:meters_per_second, :kilometers_per_hour, :miles_per_hour, :knots]
|
12
|
-
|
13
|
-
# Conversions
|
14
11
|
SECONDS_PER_HOUR = 60.0 * 60
|
15
|
-
|
16
|
-
|
12
|
+
KMH = M9t::Distance::CONVERSIONS[:kilometers] / SECONDS_PER_HOUR
|
13
|
+
MPH = M9t::Distance::CONVERSIONS[:miles] / SECONDS_PER_HOUR
|
17
14
|
KNOTS_TO_KMH = 1.852
|
18
|
-
|
15
|
+
KNOTS = KNOTS_TO_KMH / SECONDS_PER_HOUR * M9t::Distance::CONVERSIONS[:kilometers]
|
16
|
+
CONVERSIONS = {
|
17
|
+
:meters_per_second => 1.0,
|
18
|
+
:kilometers_per_hour => KMH,
|
19
|
+
:miles_per_hour => MPH,
|
20
|
+
:knots => KNOTS
|
21
|
+
}
|
19
22
|
|
20
23
|
include M9t::Base
|
21
24
|
|
22
|
-
class << self
|
23
|
-
|
24
|
-
# Accepts kilometers per hour and returns a M9t::Speed instance
|
25
|
-
def kilometers_per_hour(kmh, options = {})
|
26
|
-
new(kmh.to_f / MS_TO_KMH, options)
|
27
|
-
end
|
28
|
-
|
29
|
-
# Accepts miles per hour and returns a M9t::Speed instance
|
30
|
-
def miles_per_hour(mph, options = {})
|
31
|
-
new(mph.to_f / MS_TO_MPH, options)
|
32
|
-
end
|
33
|
-
|
34
|
-
# Accepts knots and returns a M9t::Speed instance
|
35
|
-
def knots(knots, options = {})
|
36
|
-
new(knots.to_f / MS_TO_KNOTS, options)
|
37
|
-
end
|
38
|
-
|
39
|
-
# Alias for new
|
40
|
-
def meters_per_second(*args)
|
41
|
-
new(*args)
|
42
|
-
end
|
43
|
-
|
44
|
-
# Identity conversion. Simply returns the supplied number
|
45
|
-
def to_meters_per_second(mps)
|
46
|
-
mps.to_f
|
47
|
-
end
|
48
|
-
|
49
|
-
# Converts meters per second to kilometers per hour
|
50
|
-
def to_kilometers_per_hour(mps)
|
51
|
-
mps.to_f * MS_TO_KMH
|
52
|
-
end
|
53
|
-
|
54
|
-
# Converts meters per second to miles per hour
|
55
|
-
def to_miles_per_hour(mps)
|
56
|
-
mps.to_f * MS_TO_MPH
|
57
|
-
end
|
58
|
-
|
59
|
-
# Converts meters per second to knots
|
60
|
-
def to_knots(mps)
|
61
|
-
mps.to_f * MS_TO_KNOTS
|
62
|
-
end
|
63
|
-
|
64
|
-
# Converts knots to kilometers hour
|
65
|
-
def knots_to_kilometers_per_hour(knots)
|
66
|
-
to_kilometers_per_hour(knots.to_f / MS_TO_KNOTS)
|
67
|
-
end
|
68
|
-
|
69
|
-
# Converts knots to kilometers hour
|
70
|
-
def kilometers_per_hour_to_knots(knh)
|
71
|
-
to_knots(kmh.to_f / MS_TO_KMH)
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
25
|
alias :to_meters_per_second :value
|
77
26
|
|
78
|
-
# Returns the value converted to kilometers per hour
|
79
|
-
def to_kilometers_per_hour
|
80
|
-
self.class.to_kilometers_per_hour(@value)
|
81
|
-
end
|
82
|
-
|
83
|
-
# Returns the value converted to miles per hour
|
84
|
-
def to_miles_per_hour
|
85
|
-
self.class.to_miles_per_hour(@value)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Returns the value converted to miles per hour
|
89
|
-
def to_knots
|
90
|
-
self.class.to_knots(@value)
|
91
|
-
end
|
92
|
-
|
93
27
|
end
|
94
28
|
|
95
29
|
end
|
data/lib/m9t/temperature.rb
CHANGED
@@ -9,7 +9,11 @@ module M9t
|
|
9
9
|
# Using degrees (celcius), not kelvin, as default unit
|
10
10
|
class Temperature
|
11
11
|
DEFAULT_OPTIONS = {:units => :degrees, :abbreviated => false, :precision => 5}
|
12
|
-
|
12
|
+
CONVERSIONS = {
|
13
|
+
:degrees => 1.0,
|
14
|
+
:kelvin => nil,
|
15
|
+
:fahrenheit => nil
|
16
|
+
}
|
13
17
|
|
14
18
|
# Conversions
|
15
19
|
ABSOLUTE_ZERO = -273.15
|
@@ -18,23 +22,13 @@ module M9t
|
|
18
22
|
|
19
23
|
class << self
|
20
24
|
|
21
|
-
# Alias for new
|
22
|
-
def degrees(*args)
|
23
|
-
new(*args)
|
24
|
-
end
|
25
|
-
|
26
25
|
# Accepts a value in kelvin and returns the equivalent M9t::Temperature
|
27
|
-
def kelvin(kelvin
|
28
|
-
new(kelvin.to_f + ABSOLUTE_ZERO
|
29
|
-
end
|
30
|
-
|
31
|
-
def fahrenheit(fahrenheit, options = {})
|
32
|
-
new(fahrenheit_to_degrees(fahrenheit), options)
|
26
|
+
def kelvin( kelvin )
|
27
|
+
new( kelvin.to_f + ABSOLUTE_ZERO )
|
33
28
|
end
|
34
29
|
|
35
|
-
|
36
|
-
|
37
|
-
degrees.to_f
|
30
|
+
def fahrenheit( fahrenheit )
|
31
|
+
new( fahrenheit_to_degrees( fahrenheit ) )
|
38
32
|
end
|
39
33
|
|
40
34
|
# Converts degrees to kelvin
|
data/lib/m9t/version.rb
ADDED
data/test/direction_test.rb
CHANGED
@@ -43,16 +43,16 @@ class TestM9tDirection < Test::Unit::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def test_to_degrees_identity
|
46
|
-
assert_equal(45, M9t::Direction.
|
46
|
+
assert_equal(45, M9t::Direction.degrees_to_degrees(45))
|
47
47
|
end
|
48
48
|
|
49
|
-
def
|
50
|
-
assert_equal('N', M9t::Direction.
|
51
|
-
assert_equal('NE', M9t::Direction.
|
52
|
-
assert_equal('E', M9t::Direction.
|
53
|
-
assert_equal('ESE', M9t::Direction.
|
49
|
+
def test_degrees_to_compass
|
50
|
+
assert_equal('N', M9t::Direction.degrees_to_compass(0))
|
51
|
+
assert_equal('NE', M9t::Direction.degrees_to_compass(42)) # Quantizing up
|
52
|
+
assert_equal('E', M9t::Direction.degrees_to_compass(93)) # Quantizing down
|
53
|
+
assert_equal('ESE', M9t::Direction.degrees_to_compass(113)) # 16ths
|
54
54
|
I18n.locale = :it
|
55
|
-
assert_equal('O', M9t::Direction.
|
55
|
+
assert_equal('O', M9t::Direction.degrees_to_compass(270))
|
56
56
|
end
|
57
57
|
|
58
58
|
def test_compass
|
@@ -60,32 +60,40 @@ class TestM9tDirection < Test::Unit::TestCase
|
|
60
60
|
assert_equal(247.5, M9t::Direction.compass('WSW').value)
|
61
61
|
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
def test_unknown_units
|
66
|
-
assert_raises(M9t::UnitError) { M9t::Direction.new(10, {:units => :foos}) }
|
63
|
+
def test_compass_to_degrees
|
64
|
+
assert_equal(247.5, M9t::Direction.compass_to_degrees('WSW'))
|
67
65
|
end
|
68
66
|
|
67
|
+
# Instance methods
|
68
|
+
|
69
69
|
def test_to_s_not_abbreviated_singular
|
70
|
-
|
70
|
+
direction = M9t::Direction.new( 1 )
|
71
|
+
|
72
|
+
assert_equal '1 degree', direction.to_s
|
71
73
|
I18n.locale = :it
|
72
|
-
assert_equal '1 grado',
|
74
|
+
assert_equal '1 grado', direction.to_s
|
73
75
|
end
|
74
76
|
|
75
77
|
def test_to_s_not_abbreviated_plural
|
76
|
-
|
78
|
+
direction = M9t::Direction.new( 135 )
|
79
|
+
|
80
|
+
assert_equal '135 degrees', direction.to_s
|
77
81
|
I18n.locale = :it
|
78
|
-
assert_equal '135 gradi',
|
82
|
+
assert_equal '135 gradi', direction.to_s
|
79
83
|
end
|
80
84
|
|
81
85
|
def test_to_s_abbreviated
|
82
|
-
|
86
|
+
direction = M9t::Direction.new( 135 )
|
87
|
+
|
88
|
+
assert_equal '135°', direction.to_s( :abbreviated => true )
|
83
89
|
end
|
84
90
|
|
85
91
|
def test_compass_units
|
86
|
-
|
92
|
+
direction = M9t::Direction.new( 225 )
|
93
|
+
|
94
|
+
assert_equal 'SW', direction.to_s( :units => :compass )
|
87
95
|
I18n.locale = :it
|
88
|
-
assert_equal 'SO',
|
96
|
+
assert_equal 'SO', direction.to_s( :units => :compass )
|
89
97
|
end
|
90
98
|
|
91
99
|
def test_handles_string_leading_zero
|
data/test/distance_test.rb
CHANGED
@@ -14,17 +14,19 @@ class TestM9tDistance < Test::Unit::TestCase
|
|
14
14
|
|
15
15
|
# Basic use
|
16
16
|
def test_singular
|
17
|
-
distance = M9t::Distance.new(1
|
17
|
+
distance = M9t::Distance.new( 1 )
|
18
18
|
I18n.locale = :en
|
19
|
-
|
19
|
+
|
20
|
+
assert_equal('1 meter', distance.to_s( :precision => 0 ) )
|
20
21
|
end
|
21
22
|
|
22
23
|
def test_plural
|
23
|
-
distance = M9t::Distance.new(10
|
24
|
+
distance = M9t::Distance.new( 10 )
|
25
|
+
|
24
26
|
I18n.locale = :en
|
25
|
-
assert_equal('10 meters', distance.to_s)
|
27
|
+
assert_equal( '10 meters', distance.to_s( :precision => 0 ) )
|
26
28
|
I18n.locale = :it
|
27
|
-
assert_equal('10 metri', distance.to_s)
|
29
|
+
assert_equal( '10 metri', distance.to_s( :precision => 0 ) )
|
28
30
|
end
|
29
31
|
|
30
32
|
# Class methods
|
@@ -35,24 +37,38 @@ class TestM9tDistance < Test::Unit::TestCase
|
|
35
37
|
assert_equal('distance', M9t::Distance.measurement_name)
|
36
38
|
end
|
37
39
|
|
38
|
-
#
|
39
|
-
|
40
|
-
|
40
|
+
# Construction
|
41
|
+
# ...from meters
|
42
|
+
def test_new
|
43
|
+
assert_equal(0.3, M9t::Distance.new(0.3).to_f)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_class_meters
|
47
|
+
assert_equal(0.3, M9t::Distance.meters(0.3).to_f)
|
41
48
|
end
|
42
49
|
|
43
|
-
|
44
|
-
|
50
|
+
# ...from other units
|
51
|
+
def test_class_kilometers
|
52
|
+
assert_in_delta(300.0, M9t::Distance.kilometers(0.3).to_f, 0.00001)
|
45
53
|
end
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
def test_class_miles
|
56
|
+
assert_in_delta(1609.344, M9t::Distance.miles(1).to_f, 0.00001)
|
57
|
+
assert_in_delta(42194.988, M9t::Distance.miles(26.21875).to_f, 0.00001)
|
50
58
|
end
|
51
59
|
|
52
|
-
|
53
|
-
|
60
|
+
# Conversion class methods
|
61
|
+
# ...to other units
|
62
|
+
def test_class_meters_to_kilometers
|
63
|
+
assert_equal(0.0003, M9t::Distance.meters_to_kilometers(0.3))
|
54
64
|
end
|
55
65
|
|
66
|
+
def test_class_miles_to_kilometers
|
67
|
+
assert_in_delta(42.194988, M9t::Distance.miles_to_kilometers(26.21875), 0.00001)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Default options
|
71
|
+
|
56
72
|
def test_default_options_set
|
57
73
|
assert_not_nil(M9t::Distance.options)
|
58
74
|
end
|
@@ -71,30 +87,20 @@ class TestM9tDistance < Test::Unit::TestCase
|
|
71
87
|
|
72
88
|
# Instance methods
|
73
89
|
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_default_options_merged
|
79
|
-
distance = M9t::Distance.new(10, {:abbreviated => true})
|
80
|
-
assert_equal(:meters, distance.options[:units])
|
81
|
-
assert_equal(5, distance.options[:precision])
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_set_default_options_get_inherited
|
85
|
-
M9t::Distance.options[:precision] = 0
|
86
|
-
distance = M9t::Distance.new(10)
|
87
|
-
assert_equal(0, distance.options[:precision])
|
88
|
-
end
|
89
|
-
|
90
|
-
def test_to_meters
|
90
|
+
# Conversion
|
91
|
+
def test_instance_to_meters
|
91
92
|
assert_equal(0.3, M9t::Distance.new(0.3).to_meters)
|
92
93
|
end
|
93
94
|
|
94
|
-
def
|
95
|
+
def test_instance_to_kilometers
|
95
96
|
assert_equal(0.0003, M9t::Distance.new(0.3).to_kilometers)
|
96
97
|
end
|
97
98
|
|
99
|
+
def test_instance_to_kilometers
|
100
|
+
assert_in_delta(0.98425, M9t::Distance.new(0.3).to_feet, 0.00001)
|
101
|
+
end
|
102
|
+
|
103
|
+
# to_s
|
98
104
|
def test_to_s_singular
|
99
105
|
assert_equal('1.00000 meter', M9t::Distance.new(1).to_s)
|
100
106
|
end
|
@@ -103,40 +109,56 @@ class TestM9tDistance < Test::Unit::TestCase
|
|
103
109
|
assert_equal('0.30000 meters', M9t::Distance.new(0.3).to_s)
|
104
110
|
end
|
105
111
|
|
112
|
+
# i18n
|
106
113
|
def test_to_s_plural_abbreviated
|
107
|
-
distance = M9t::Distance.new(10
|
114
|
+
distance = M9t::Distance.new( 10 )
|
108
115
|
I18n.locale = :en
|
109
|
-
assert_equal('10m', distance.to_s
|
116
|
+
assert_equal( '10m', distance.to_s( :abbreviated => true,
|
117
|
+
:precision => 0 ) )
|
110
118
|
I18n.locale = :it
|
111
|
-
assert_equal('10m', distance.to_s
|
119
|
+
assert_equal( '10m', distance.to_s( :abbreviated => true,
|
120
|
+
:precision => 0 ) )
|
112
121
|
end
|
113
122
|
|
114
123
|
def test_to_s_abbreviated
|
115
|
-
|
124
|
+
distance = M9t::Distance.new( 0.3 )
|
125
|
+
|
126
|
+
assert_equal( '0.30000m', distance.to_s( :abbreviated => true ) )
|
116
127
|
end
|
117
128
|
|
118
129
|
def test_to_s_precision
|
119
|
-
|
130
|
+
distance = M9t::Distance.new( 0.3 )
|
131
|
+
|
132
|
+
assert_equal( '0.3m', distance.to_s( :precision => 1,
|
133
|
+
:abbreviated => true ) )
|
120
134
|
end
|
121
135
|
|
122
136
|
def test_to_s_kilometers
|
123
|
-
|
137
|
+
distance = M9t::Distance.new( 156003 )
|
138
|
+
|
139
|
+
assert_equal( '156.0 kilometers', distance.to_s( :precision => 1,
|
140
|
+
:units => :kilometers ) )
|
124
141
|
end
|
125
142
|
|
126
143
|
def test_miles_singular
|
127
|
-
|
144
|
+
marathon = M9t::Distance.miles( 26.21875 )
|
128
145
|
I18n.locale = :en
|
129
|
-
assert_equal(
|
146
|
+
assert_equal( '26 miles', marathon.to_s( :units => :miles,
|
147
|
+
:precision => 0 ) )
|
130
148
|
I18n.locale = :it
|
131
|
-
assert_equal(
|
149
|
+
assert_equal( '26 miglia', marathon.to_s( :units => :miles,
|
150
|
+
:precision => 0 ) )
|
132
151
|
end
|
133
152
|
|
134
153
|
def test_to_s_miles_plural
|
135
|
-
|
154
|
+
ten_km = M9t::Distance.new( 10000 )
|
155
|
+
|
136
156
|
I18n.locale = :en
|
137
|
-
assert_equal('6.2 miles',
|
157
|
+
assert_equal( '6.2 miles', ten_km.to_s( :units => :miles,
|
158
|
+
:precision => 1 ) )
|
138
159
|
I18n.locale = :it
|
139
|
-
assert_equal('6,2 miglia',
|
160
|
+
assert_equal( '6,2 miglia', ten_km.to_s( :units => :miles,
|
161
|
+
:precision => 1 ) )
|
140
162
|
end
|
141
163
|
|
142
164
|
end
|
data/test/speed_test.rb
CHANGED
@@ -28,7 +28,7 @@ class TestM9tSpeed < Test::Unit::TestCase
|
|
28
28
|
# conversion constants
|
29
29
|
|
30
30
|
def test_knot_conversion
|
31
|
-
assert_in_delta(
|
31
|
+
assert_in_delta(0.51444, M9t::Speed::KNOTS, 0.0001)
|
32
32
|
end
|
33
33
|
|
34
34
|
# input conversions
|
@@ -48,7 +48,7 @@ class TestM9tSpeed < Test::Unit::TestCase
|
|
48
48
|
# output conversions
|
49
49
|
|
50
50
|
def test_class_to_miles_per_hour
|
51
|
-
assert_in_delta(100.6621, M9t::Speed.
|
51
|
+
assert_in_delta(100.6621, M9t::Speed.meters_per_second_to_miles_per_hour(45), 0.0001)
|
52
52
|
end
|
53
53
|
|
54
54
|
# Instance methods
|
@@ -56,7 +56,11 @@ class TestM9tSpeed < Test::Unit::TestCase
|
|
56
56
|
# new
|
57
57
|
|
58
58
|
def test_unknown_units
|
59
|
-
|
59
|
+
speed = M9t::Speed.new( '010' )
|
60
|
+
|
61
|
+
assert_raises( M9t::UnitError ) do
|
62
|
+
speed.to_s( :units => :foos )
|
63
|
+
end
|
60
64
|
end
|
61
65
|
|
62
66
|
# output conversions
|
@@ -78,17 +82,26 @@ class TestM9tSpeed < Test::Unit::TestCase
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def test_to_s_precision
|
81
|
-
|
85
|
+
speed = M9t::Speed.new( 135 )
|
86
|
+
|
87
|
+
assert_equal '135 meters per second', speed.to_s( :precision => 0 )
|
82
88
|
end
|
83
89
|
|
84
90
|
def test_to_s_abbreviated
|
85
|
-
|
91
|
+
speed = M9t::Speed.new( 135 )
|
92
|
+
|
93
|
+
assert_equal '135m/s', speed.to_s( :abbreviated => true,
|
94
|
+
:precision => 0 )
|
86
95
|
end
|
87
96
|
|
88
97
|
def test_to_s_knots
|
89
|
-
|
98
|
+
speed = M9t::Speed.new( 135 )
|
99
|
+
|
100
|
+
assert_equal '262 knots', speed.to_s( :units => :knots,
|
101
|
+
:precision => 0 )
|
90
102
|
I18n.locale = :it
|
91
|
-
assert_equal '262 nodi',
|
103
|
+
assert_equal '262 nodi', speed.to_s( :units => :knots,
|
104
|
+
:precision => 0 )
|
92
105
|
end
|
93
106
|
|
94
107
|
end
|
data/test/temperature_test.rb
CHANGED
@@ -56,7 +56,11 @@ class TestM9tTemperature < Test::Unit::TestCase
|
|
56
56
|
# new
|
57
57
|
|
58
58
|
def test_unknown_units
|
59
|
-
|
59
|
+
temperature = M9t::Temperature.new( 1 )
|
60
|
+
|
61
|
+
assert_raises( M9t::UnitError ) do
|
62
|
+
temperature.to_s( :units => :foos )
|
63
|
+
end
|
60
64
|
end
|
61
65
|
|
62
66
|
# output conversions
|
@@ -78,18 +82,29 @@ class TestM9tTemperature < Test::Unit::TestCase
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def test_to_s_precision
|
81
|
-
|
85
|
+
temperature = M9t::Temperature.new( 135 )
|
86
|
+
|
87
|
+
assert_equal '135 degrees', temperature.to_s( :precision => 0 )
|
82
88
|
end
|
83
89
|
|
84
90
|
def test_to_s_abbreviated
|
85
|
-
|
86
|
-
|
91
|
+
temperature = M9t::Temperature.new( 135 )
|
92
|
+
|
93
|
+
assert_equal '135°C', temperature.to_s( :abbreviated => true,
|
94
|
+
:precision => 0 )
|
95
|
+
assert_equal '408.15K', temperature.to_s( :units => :kelvin,
|
96
|
+
:abbreviated => true,
|
97
|
+
:precision => 2 )
|
87
98
|
end
|
88
99
|
|
89
100
|
def test_to_s_kelvin
|
90
|
-
|
101
|
+
temperature = M9t::Temperature.new( 100 )
|
102
|
+
|
103
|
+
assert_equal '373.15 kelvin', temperature.to_s( :units => :kelvin,
|
104
|
+
:precision => 2 )
|
91
105
|
I18n.locale = :it
|
92
|
-
assert_equal '373,15 kelvin',
|
106
|
+
assert_equal '373,15 kelvin', temperature.to_s( :units => :kelvin,
|
107
|
+
:precision => 2 )
|
93
108
|
end
|
94
109
|
|
95
110
|
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: m9t
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
8
|
+
- 2
|
7
9
|
- 1
|
8
|
-
|
9
|
-
version: 0.1.12
|
10
|
+
version: 0.2.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Joe Yates
|
@@ -14,16 +15,18 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
+
date: 2011-04-04 00:00:00 +01:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: i18n
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 25
|
27
30
|
segments:
|
28
31
|
- 0
|
29
32
|
- 3
|
@@ -37,62 +40,61 @@ executables: []
|
|
37
40
|
|
38
41
|
extensions: []
|
39
42
|
|
40
|
-
extra_rdoc_files:
|
41
|
-
|
42
|
-
- COPYING
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
43
45
|
files:
|
44
46
|
- README.rdoc
|
45
47
|
- COPYING
|
46
48
|
- Rakefile
|
47
|
-
- lib/m9t.rb
|
48
|
-
- lib/m9t/pressure.rb
|
49
|
-
- lib/m9t/speed.rb
|
50
49
|
- lib/m9t/base.rb
|
51
50
|
- lib/m9t/direction.rb
|
52
51
|
- lib/m9t/distance.rb
|
53
52
|
- lib/m9t/i18n.rb
|
53
|
+
- lib/m9t/pressure.rb
|
54
|
+
- lib/m9t/speed.rb
|
54
55
|
- lib/m9t/temperature.rb
|
55
|
-
-
|
56
|
+
- lib/m9t/version.rb
|
57
|
+
- lib/m9t.rb
|
56
58
|
- test/direction_test.rb
|
57
|
-
- test/i18n_test.rb
|
58
59
|
- test/distance_test.rb
|
60
|
+
- test/i18n_test.rb
|
61
|
+
- test/pressure_test.rb
|
62
|
+
- test/speed_test.rb
|
59
63
|
- test/temperature_test.rb
|
60
64
|
- test/test_all.rb
|
61
|
-
- test/speed_test.rb
|
62
|
-
- locales/it.yml
|
63
65
|
- locales/en.yml
|
66
|
+
- locales/it.yml
|
64
67
|
has_rdoc: true
|
65
68
|
homepage: http://github.com/joeyates/m9t
|
66
69
|
licenses: []
|
67
70
|
|
68
71
|
post_install_message:
|
69
|
-
rdoc_options:
|
70
|
-
|
71
|
-
- --title
|
72
|
-
- "m9t: Measurement units"
|
73
|
-
- --main
|
74
|
-
- README.rdoc
|
75
|
-
- --inline-source
|
72
|
+
rdoc_options: []
|
73
|
+
|
76
74
|
require_paths:
|
77
75
|
- lib
|
78
76
|
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
79
78
|
requirements:
|
80
79
|
- - ">="
|
81
80
|
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
82
|
segments:
|
83
83
|
- 0
|
84
84
|
version: "0"
|
85
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
86
87
|
requirements:
|
87
88
|
- - ">="
|
88
89
|
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
89
91
|
segments:
|
90
92
|
- 0
|
91
93
|
version: "0"
|
92
94
|
requirements: []
|
93
95
|
|
94
|
-
rubyforge_project:
|
95
|
-
rubygems_version: 1.3.
|
96
|
+
rubyforge_project: nowarning
|
97
|
+
rubygems_version: 1.3.7
|
96
98
|
signing_key:
|
97
99
|
specification_version: 3
|
98
100
|
summary: Classes for handling measurement units
|