measurement 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ v0.1 First version
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Jeremy Wells
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,15 @@
1
+ CHANGELOG
2
+ LICENSE
3
+ Manifest
4
+ README.rdoc
5
+ Rakefile
6
+ lib/measurement.rb
7
+ lib/measurement/conversion.rb
8
+ lib/measurement/length.rb
9
+ lib/measurement/weight.rb
10
+ spec/lib/conversion_spec.rb
11
+ spec/lib/length_spec.rb
12
+ spec/lib/measurement_spec.rb
13
+ spec/lib/weight_spec.rb
14
+ spec/spec.opts
15
+ spec/spec_helper.rb
data/README.rdoc ADDED
@@ -0,0 +1,40 @@
1
+ = Library for holding, converting and formatting measurements
2
+
3
+ * http://github.com/jemmyw/measurement
4
+
5
+ == DESCRIPTION
6
+
7
+ == INSTALL:
8
+
9
+ * sudo gem install measurement
10
+
11
+ == EXAMPLE:
12
+
13
+ require 'measurement/length'
14
+ length = Length.parse('180.34cm')
15
+ puts length.in_feet_and_inches => 5' 11"
16
+
17
+ == LICENSE:
18
+
19
+ (The MIT License)
20
+
21
+ Copyright (c) 2009 Jeremy Wells
22
+
23
+ Permission is hereby granted, free of charge, to any person obtaining
24
+ a copy of this software and associated documentation files (the
25
+ 'Software'), to deal in the Software without restriction, including
26
+ without limitation the rights to use, copy, modify, merge, publish,
27
+ distribute, sublicense, and/or sell copies of the Software, and to
28
+ permit persons to whom the Software is furnished to do so, subject to
29
+ the following conditions:
30
+
31
+ The above copyright notice and this permission notice shall be
32
+ included in all copies or substantial portions of the Software.
33
+
34
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
35
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
37
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
38
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
39
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
40
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'spec/rake/spectask'
4
+ require 'echoe'
5
+ Echoe.new('measurement') do |gem|
6
+ gem.author = "Jeremy Wells"
7
+ gem.summary = "A library for holding, converting and formatting measurements"
8
+ gem.email = "jemmyw@gmail.com"
9
+ end
@@ -0,0 +1,129 @@
1
+ require File.join(File.dirname(__FILE__), 'measurement', 'conversion')
2
+
3
+ module Measurement
4
+ class NoScaleFoundException < Exception; end
5
+
6
+ class Base
7
+ def self.base(*args)
8
+ if args.any?
9
+ @base = Conversion.new(1.0, *args)
10
+ add_conversion(@base)
11
+ else
12
+ @base
13
+ end
14
+ end
15
+
16
+ def self.conversions
17
+ @conversions ||= []
18
+ end
19
+
20
+ def self.conversion(scale, *args)
21
+ add_conversion(Conversion.new(scale, *args))
22
+ end
23
+
24
+ def self.add_conversion(conversion)
25
+ conversions << conversion
26
+ end
27
+
28
+ def self.fetch_scale(scale = nil)
29
+ scale.nil? ? base : conversions.detect do |conversion|
30
+ conversion.has_name?(scale)
31
+ end
32
+ end
33
+
34
+ def self.find_scale(scale)
35
+ conversions.detect do |conversion|
36
+ conversion.has_name?(scale) ||
37
+ conversion.suffix == scale
38
+ end
39
+ end
40
+
41
+ def self.from(amount, scale)
42
+ fetch_scale(scale).from(amount)
43
+ end
44
+
45
+ def self.to(amount, scale = nil)
46
+ fetch_scale(scale).to(amount)
47
+ end
48
+
49
+ def self.format(amount, scale = nil, precision = 2)
50
+ fetch_scale(scale).format(amount, precision)
51
+ end
52
+
53
+ def self.parse(string)
54
+ string = string.dup
55
+ base_amount = 0.0
56
+
57
+ while string =~ /(\d+(\.\d+)?)([^\d]*)/
58
+ amount = $1.to_f
59
+ scale = $3 && $3.strip
60
+
61
+ if scale && scale.length > 0
62
+ scale = find_scale(scale)
63
+
64
+ if scale.nil?
65
+ raise NoScaleFoundException.new(scale)
66
+ else
67
+ base_amount += scale.from(amount)
68
+ end
69
+ else
70
+ base_amount += amount
71
+ end
72
+
73
+ string.sub!(/(\d+(\.\d+)?)([^\d]*)/, '')
74
+ end
75
+
76
+ self.new(base_amount)
77
+ end
78
+
79
+ def initialize(amount = 0, scale = nil)
80
+ @amount = self.class.from(amount, scale)
81
+ end
82
+
83
+ def to_i
84
+ @amount.to_i
85
+ end
86
+
87
+ def to_f
88
+ @amount.to_f
89
+ end
90
+
91
+ def as(scale)
92
+ self.class.to(@amount, scale)
93
+ end
94
+
95
+ def method_missing(method, *args)
96
+ if method.to_s =~ /^(as|in)_(.*)/
97
+ scale = $2
98
+ if scale =~ /and/
99
+ to_s(scale, *args)
100
+ else
101
+ as(scale.to_sym, *args)
102
+ end
103
+ else
104
+ super
105
+ end
106
+ end
107
+
108
+ def to_s(scale = nil, precision = 2)
109
+ if scale.to_s =~ /_and_/
110
+ scales = scale.to_s.split('_and_')
111
+ amount = @amount
112
+ strs = []
113
+
114
+ while scale = scales.shift
115
+ n_in = self.class.to(amount, scale.to_sym)
116
+ n_in = n_in.floor unless scales.empty?
117
+ n_out = self.class.from(n_in, scale.to_sym)
118
+ amount -= self.class.from(n_in, scale.to_sym)
119
+ strs << self.class.format(n_out, scale.to_sym, 0)
120
+ end
121
+
122
+ strs.join(' ')
123
+ else
124
+ self.class.format(@amount, scale, precision)
125
+ end
126
+ end
127
+ alias_method :format, :to_s
128
+ end
129
+ end
@@ -0,0 +1,35 @@
1
+ module Measurement
2
+ class Conversion
3
+ attr_reader :names
4
+
5
+ def initialize(scale, *args)
6
+ @options = args.last.is_a?(Hash) ? args.pop : {}
7
+ @names = args
8
+ @scale = scale
9
+ end
10
+
11
+ def has_name?(name)
12
+ names.include?(name)
13
+ end
14
+
15
+ def from(amount)
16
+ amount.to_f * @scale
17
+ end
18
+
19
+ def to(amount)
20
+ amount.to_f / @scale
21
+ end
22
+
23
+ def format(amount, precision = 2)
24
+ prefix + ("%.#{precision}f" % to(amount)) + suffix
25
+ end
26
+
27
+ def prefix
28
+ @options[:prefix] || ''
29
+ end
30
+
31
+ def suffix
32
+ @options[:suffix] || ''
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'measurement')
2
+
3
+ class Length < Measurement::Base
4
+ base :metre, :suffix => 'm'
5
+ conversion 1000, :kilometre, :kilometres, :km, :suffix => 'km'
6
+ conversion 0.01, :centimetre, :centimetres, :cm, :suffix => 'cm'
7
+ conversion 0.001, :millimetre, :mm, :suffix => 'mm'
8
+
9
+ conversion 0.0254, :inch, :inches, :suffix => '"'
10
+ conversion 0.3048, :feet, :foot, :suffix => "'"
11
+ conversion 1609.34, :mile, :miles, :suffix => ' miles'
12
+ conversion 0.1016, :hand, :hands, :suffix => ' hands'
13
+
14
+ conversion 299792458, :light_seconds, :suffix => ' light seconds'
15
+ conversion 1079252848800, :light_hours, :suffix => ' light hours'
16
+ end
@@ -0,0 +1,9 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'measurement')
2
+
3
+ class Weight < Measurement::Base
4
+ base :grams, :suffix => 'g'
5
+ conversion 1000.0, :kilograms, :kg, :kgs, :suffix => 'kg'
6
+ conversion 453.59236, :pounds, :pound, :lbs, :suffix => 'lbs'
7
+ conversion 28.3495231, :ounces, :ounce, :oz, :suffix => 'oz'
8
+ conversion 6350.29318, :stone, :st, :suffix => 'st'
9
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{measurement}
5
+ s.version = "0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Jeremy Wells"]
9
+ s.date = %q{2010-02-27}
10
+ s.description = %q{A library for holding, converting and formatting measurements}
11
+ s.email = %q{jemmyw@gmail.com}
12
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.rdoc", "lib/measurement.rb", "lib/measurement/conversion.rb", "lib/measurement/length.rb", "lib/measurement/weight.rb"]
13
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.rdoc", "Rakefile", "lib/measurement.rb", "lib/measurement/conversion.rb", "lib/measurement/length.rb", "lib/measurement/weight.rb", "spec/lib/conversion_spec.rb", "spec/lib/length_spec.rb", "spec/lib/measurement_spec.rb", "spec/lib/weight_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "measurement.gemspec"]
14
+ s.homepage = %q{}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Measurement", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{measurement}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{A library for holding, converting and formatting measurements}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Measurement::Conversion do
4
+ describe '#instance methods' do
5
+ before do
6
+ @conversion = Measurement::Conversion.new(150.0, :test, :other)
7
+ end
8
+
9
+ describe '#from' do
10
+ it 'should multiply the amount by the conversion scale' do
11
+ @conversion.from(1).should == 150.0
12
+ end
13
+ end
14
+
15
+ describe '#to' do
16
+ it 'should divide the amount by the conversion scale' do
17
+ @conversion.to(150).should == 1
18
+ end
19
+ end
20
+
21
+ describe '#format' do
22
+ it 'should return a string' do
23
+ @conversion.format(1).should be_a(String)
24
+ end
25
+
26
+ it 'should format using the given precision' do
27
+ @conversion.format(200,1).should == "1.3"
28
+ @conversion.format(200,2).should == "1.33"
29
+ end
30
+
31
+ it 'should apply the suffix' do
32
+ @conversion = Measurement::Conversion.new(150.0, :test, :suffix => 'test')
33
+ @conversion.format(150, 0).should == "1test"
34
+ end
35
+
36
+ it 'should apply the prefix' do
37
+ @conversion = Measurement::Conversion.new(150.0, :test, :prefix => 'test')
38
+ @conversion.format(150, 0).should == "test1"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Length do
4
+ it 'should have 10 conversions' do
5
+ Length.conversions.size.should == 10
6
+ end
7
+
8
+ it 'should use metres as a base' do
9
+ Length.new(1).to_s(nil, 0).should == '1m'
10
+ end
11
+
12
+ { :cm => 100,
13
+ :mm => 1000,
14
+ :inches => 39.370,
15
+ :feet => 3.281,
16
+ :hand => 9.842,
17
+ :km => 0.001
18
+ }.each do |key, value|
19
+ it "should have #{key} with 1 metre = #{value} #{key}" do
20
+ Length.new(1).as(key).should be_close(value, 0.001)
21
+ end
22
+ end
23
+
24
+ it 'should have miles' do
25
+ Length.new(1).in_miles.should be_close(0.0006213, 0.0000001)
26
+ end
27
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Measurement::Base do
4
+ describe '::parse' do
5
+ it 'should parse in the base unit if no unit is specified' do
6
+ Length.parse('113').to_f.should == 113.0
7
+ end
8
+
9
+ it 'should parse floating point numbers' do
10
+ Length.parse('113.43').to_f.should == 113.43
11
+ end
12
+
13
+ it 'should parse in the unit specified' do
14
+ Length.parse('32cm').to_f.should == 0.32
15
+ Length.parse('32cm').to_s(:cm, 0).should == '32cm'
16
+ end
17
+
18
+ it 'should parse multiple units' do
19
+ Length.parse('32cm 5mm').to_f.should == 0.325
20
+ Length.parse('32cm 5mm').to_s(:cm, 0).should == '32cm'
21
+ Length.parse('32cm 5mm').to_s(:cm_and_mm).should == '32cm 5mm'
22
+ end
23
+
24
+ it 'should be able to parse units based on their suffix' do
25
+ Length.parse('5"').in_inches.should == 5.0
26
+ Length.parse(%Q{5' 11"}).to_f.should == 1.8034
27
+ end
28
+
29
+ it 'should raise a NoScaleFoundException if there is no scale matching the one passed' do
30
+ lambda do
31
+ Length.parse('10giglygoops')
32
+ end.should raise_error(Measurement::NoScaleFoundException)
33
+ end
34
+ end
35
+
36
+ describe '#method_missing' do
37
+ it 'should call as if passed in_scale' do
38
+ Length.new(10).in_cm.should == Length.new(10).as(:cm)
39
+ end
40
+
41
+ it 'should call as if passed as_scale' do
42
+ Length.new(10).as_cm.should == Length.new(10).as(:cm)
43
+ end
44
+
45
+ it 'should call to_s if passed in_scale_and_another_scale' do
46
+ length = Length.new(123.52390842)
47
+ length.in_cm_and_mm.should == length.to_s(:cm_and_mm)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Weight do
4
+ it 'should use metres as a base' do
5
+ Weight.new(1).to_s(nil, 0).should == '1g'
6
+ end
7
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --reverse
3
+ --debugger
@@ -0,0 +1,3 @@
1
+ require 'lib/measurement'
2
+ require 'lib/measurement/length'
3
+ require 'lib/measurement/weight'
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: measurement
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Wells
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-27 00:00:00 +13:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A library for holding, converting and formatting measurements
17
+ email: jemmyw@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - CHANGELOG
24
+ - LICENSE
25
+ - README.rdoc
26
+ - lib/measurement.rb
27
+ - lib/measurement/conversion.rb
28
+ - lib/measurement/length.rb
29
+ - lib/measurement/weight.rb
30
+ files:
31
+ - CHANGELOG
32
+ - LICENSE
33
+ - Manifest
34
+ - README.rdoc
35
+ - Rakefile
36
+ - lib/measurement.rb
37
+ - lib/measurement/conversion.rb
38
+ - lib/measurement/length.rb
39
+ - lib/measurement/weight.rb
40
+ - spec/lib/conversion_spec.rb
41
+ - spec/lib/length_spec.rb
42
+ - spec/lib/measurement_spec.rb
43
+ - spec/lib/weight_spec.rb
44
+ - spec/spec.opts
45
+ - spec/spec_helper.rb
46
+ - measurement.gemspec
47
+ has_rdoc: true
48
+ homepage: ""
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --line-numbers
54
+ - --inline-source
55
+ - --title
56
+ - Measurement
57
+ - --main
58
+ - README.rdoc
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "1.2"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project: measurement
76
+ rubygems_version: 1.3.5
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A library for holding, converting and formatting measurements
80
+ test_files: []
81
+