alchemist 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/Gemfile.lock +10 -1
- data/NEWS.md +6 -0
- data/README.md +13 -6
- data/Rakefile +5 -0
- data/alchemist.gemspec +3 -2
- data/lib/alchemist.rb +39 -2
- data/lib/alchemist/compound_measurement.rb +17 -2
- data/lib/alchemist/configuration.rb +2 -8
- data/lib/alchemist/conversion_calculator.rb +47 -0
- data/lib/alchemist/library.rb +31 -8
- data/lib/alchemist/measurement.rb +37 -19
- data/lib/alchemist/measurement_convertor.rb +8 -28
- data/lib/alchemist/module_builder.rb +32 -22
- data/lib/alchemist/objects/planets/earth.rb +1 -1
- data/lib/alchemist/prefix_parser.rb +21 -16
- data/lib/alchemist/version.rb +1 -1
- data/spec/alchemist_spec.rb +63 -14
- data/spec/byte_spec.rb +14 -0
- data/spec/compound_measurement_spec.rb +16 -0
- data/spec/configuration_spec.rb +16 -0
- data/spec/conversion_table_spec.rb +6 -20
- data/spec/error_spec.rb +11 -0
- data/spec/library_spec.rb +18 -4
- data/spec/measurement_convertor_spec.rb +7 -0
- data/spec/measurement_spec.rb +13 -1
- data/spec/module_builder_spec.rb +16 -0
- data/spec/prefix_parser_spec.rb +14 -2
- data/spec/spec_helper.rb +13 -0
- metadata +38 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2d96474ca74ad168ff21a950de907b6f09974ba748c66457bd0f6528ac6aafde
|
4
|
+
data.tar.gz: 756514b42731f45ed578e872943bd2004cdf4ec0ede8feb2fcdf204a6ece2431
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f363df781906fb3e2defd4719adbeb90a285bedf7ad833233019697f11ce63caf96f31d80e5903433a4da32c009d79a1187457b7ff958319e23d3b3f87d7e60c
|
7
|
+
data.tar.gz: 2be97bbc13985330796ddebef1c611c495dd20fbb9885ee932b2930833578a046b71dcea47ccd3cd6bc1534b0fb57e3d65c76109ca6a35a77f12fed165e7852c
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
alchemist (0.1.
|
4
|
+
alchemist (0.1.8)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
diff-lcs (1.2.4)
|
10
|
+
multi_json (1.8.2)
|
10
11
|
rake (10.0.3)
|
11
12
|
rspec (2.14.1)
|
12
13
|
rspec-core (~> 2.14.0)
|
@@ -16,6 +17,10 @@ GEM
|
|
16
17
|
rspec-expectations (2.14.0)
|
17
18
|
diff-lcs (>= 1.1.3, < 2.0)
|
18
19
|
rspec-mocks (2.14.1)
|
20
|
+
simplecov (0.7.1)
|
21
|
+
multi_json (~> 1.0)
|
22
|
+
simplecov-html (~> 0.7.1)
|
23
|
+
simplecov-html (0.7.1)
|
19
24
|
|
20
25
|
PLATFORMS
|
21
26
|
ruby
|
@@ -24,3 +29,7 @@ DEPENDENCIES
|
|
24
29
|
alchemist!
|
25
30
|
rake
|
26
31
|
rspec
|
32
|
+
simplecov
|
33
|
+
|
34
|
+
BUNDLED WITH
|
35
|
+
2.0.2
|
data/NEWS.md
ADDED
data/README.md
CHANGED
@@ -10,19 +10,19 @@ code more readable.
|
|
10
10
|
Having code that looks like this is meaningless
|
11
11
|
|
12
12
|
```ruby
|
13
|
-
|
13
|
+
meters = 8 * 1609.344
|
14
14
|
```
|
15
15
|
|
16
16
|
You could add comments
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
|
19
|
+
meters = 8 * 1609.344 # converting miles to meters
|
20
20
|
```
|
21
21
|
|
22
22
|
But why not have this!
|
23
23
|
|
24
24
|
```ruby
|
25
|
-
8.
|
25
|
+
8.miles.to.meters
|
26
26
|
```
|
27
27
|
|
28
28
|
You can even perform mathematical operations
|
@@ -47,7 +47,7 @@ require 'alchemist/geospatial'
|
|
47
47
|
To switch to the IEC memory standard, force SI units with
|
48
48
|
|
49
49
|
```ruby
|
50
|
-
Alchemist
|
50
|
+
Alchemist.config.use_si = true
|
51
51
|
```
|
52
52
|
|
53
53
|
To see all the units alchemist has built in conversion for, check out the [units file](lib/alchemist/data/units.yml)
|
@@ -78,8 +78,15 @@ if you only want to use one category for conversions you can load it individuall
|
|
78
78
|
Alchemist.setup('distance') # This will load only distance
|
79
79
|
```
|
80
80
|
|
81
|
-
Rails
|
82
|
-
|
81
|
+
Rails
|
82
|
+
-----
|
83
|
+
|
84
|
+
#### Setup
|
85
|
+
|
86
|
+
It is suggested that you add your `Alchemist.setup` call to `config/initializers/alchemist.rb` and then restart your rails server.
|
87
|
+
|
88
|
+
|
89
|
+
#### Rails Warning
|
83
90
|
|
84
91
|
Rails adds some methods like `bytes` to `Numeric` so it's highly recommended that instead of trying to call `bytes` on a numeric, you should use the `measure` method:
|
85
92
|
|
data/Rakefile
CHANGED
data/alchemist.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.authors = ["Matthew Mongeau"]
|
10
10
|
gem.email = ["halogenandtoast@gmail.com"]
|
11
11
|
gem.homepage = 'http://github.com/halogenandtoast/alchemist'
|
12
|
-
gem.summary = '
|
13
|
-
gem.description = '
|
12
|
+
gem.summary = 'A scientific conversion library'
|
13
|
+
gem.description = 'A scientific conversion library'
|
14
14
|
gem.license = 'MIT'
|
15
15
|
|
16
16
|
gem.files = `git ls-files`.split($/)
|
@@ -19,4 +19,5 @@ Gem::Specification.new do |gem|
|
|
19
19
|
|
20
20
|
gem.add_development_dependency 'rake'
|
21
21
|
gem.add_development_dependency 'rspec'
|
22
|
+
gem.add_development_dependency 'simplecov'
|
22
23
|
end
|
data/lib/alchemist.rb
CHANGED
@@ -4,19 +4,56 @@ require "alchemist/compound_measurement"
|
|
4
4
|
require "alchemist/module_builder"
|
5
5
|
require "alchemist/configuration"
|
6
6
|
require "alchemist/library"
|
7
|
+
require "alchemist/conversion_calculator"
|
7
8
|
|
8
9
|
module Alchemist
|
10
|
+
|
9
11
|
autoload :Earth, "alchemist/objects/planets/earth"
|
10
12
|
|
13
|
+
class IncompatibleTypeError < StandardError ; end
|
14
|
+
class GeospatialArgumentError < StandardError ; end
|
15
|
+
|
11
16
|
def self.setup category = nil
|
12
17
|
if category
|
13
|
-
|
18
|
+
load_category category
|
14
19
|
else
|
15
|
-
|
20
|
+
load_all_categories
|
16
21
|
end
|
17
22
|
end
|
18
23
|
|
19
24
|
def self.measure value, unit, exponent = 1.0
|
20
25
|
Measurement.new value, unit, exponent
|
21
26
|
end
|
27
|
+
|
28
|
+
def self.measure_prefixed value, prefix, unit
|
29
|
+
exponent = library.exponent_for(unit, prefix)
|
30
|
+
Measurement.new value, unit, exponent, prefix: prefix
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.library
|
34
|
+
@library ||= Library.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.config
|
38
|
+
@configuration ||= Configuration.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.register(types, names, value)
|
42
|
+
library.register(types, names, value)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.reset!
|
46
|
+
@library = nil
|
47
|
+
@configuration = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def self.load_all_categories
|
53
|
+
library.load_all_categories
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.load_category category
|
57
|
+
library.load_category(category)
|
58
|
+
end
|
22
59
|
end
|
@@ -1,13 +1,22 @@
|
|
1
1
|
module Alchemist
|
2
2
|
class CompoundMeasurement
|
3
|
+
include Comparable
|
3
4
|
attr_accessor :numerators, :denominators
|
4
5
|
|
5
6
|
def initialize(numerator)
|
6
|
-
@coefficient =
|
7
|
-
@numerators = [numerator]
|
7
|
+
@coefficient = numerator.value
|
8
|
+
@numerators = [numerator / @coefficient]
|
8
9
|
@denominators = []
|
9
10
|
end
|
10
11
|
|
12
|
+
def <=> other
|
13
|
+
if @coefficient == other.coefficient
|
14
|
+
[@numerators, @denominators] <=> [other.numerators, other.denominators]
|
15
|
+
else
|
16
|
+
@coefficient <=> other.coefficient
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
11
20
|
def *(value)
|
12
21
|
case value
|
13
22
|
when Numeric
|
@@ -19,6 +28,8 @@ module Alchemist
|
|
19
28
|
end
|
20
29
|
end
|
21
30
|
|
31
|
+
private
|
32
|
+
|
22
33
|
def consolidate
|
23
34
|
compress_units
|
24
35
|
set_coefficients
|
@@ -61,5 +72,9 @@ module Alchemist
|
|
61
72
|
consolidate
|
62
73
|
end
|
63
74
|
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
attr_reader :coefficient
|
64
79
|
end
|
65
80
|
end
|
@@ -1,20 +1,14 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
|
3
1
|
module Alchemist
|
4
|
-
def self.config
|
5
|
-
Configuration.instance
|
6
|
-
end
|
7
|
-
|
8
2
|
class Configuration
|
3
|
+
|
9
4
|
DATA_DIR = File.join(File.dirname(__FILE__), "data")
|
10
5
|
DEFAULT_UNITS_FILE = File.join(DATA_DIR, "units.yml")
|
11
6
|
DEFAULT_SI_UNITS_FILE = File.join(DATA_DIR, "si_units.yml")
|
12
7
|
DEFAULT_BINARY_PREFIXES_FILE = File.join(DATA_DIR, "binary_prefixes.yml")
|
13
8
|
DEFAULT_UNIT_PREFIXES_FILE = File.join(DATA_DIR, "unit_prefixes.yml")
|
14
9
|
|
15
|
-
include Singleton
|
16
|
-
|
17
10
|
attr_accessor :use_si
|
11
|
+
|
18
12
|
def initialize
|
19
13
|
@use_si = false
|
20
14
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Alchemist
|
2
|
+
class ConversionCalculator
|
3
|
+
def initialize(from, parsed_unit)
|
4
|
+
@from = from
|
5
|
+
@parsed_unit = parsed_unit
|
6
|
+
end
|
7
|
+
|
8
|
+
def calculate
|
9
|
+
Measurement.new(value / exponent, unit_name, exponent)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
attr_reader :from, :parsed_unit
|
14
|
+
|
15
|
+
def exponent
|
16
|
+
parsed_unit.exponent
|
17
|
+
end
|
18
|
+
|
19
|
+
def unit_name
|
20
|
+
parsed_unit.unit_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def value
|
24
|
+
if proc_based?
|
25
|
+
factor[1].call(base)
|
26
|
+
else
|
27
|
+
base / BigDecimal(factor.to_s)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def proc_based?
|
32
|
+
factor.is_a? Array
|
33
|
+
end
|
34
|
+
|
35
|
+
def base
|
36
|
+
@base ||= BigDecimal(from.base(type).to_s)
|
37
|
+
end
|
38
|
+
|
39
|
+
def type
|
40
|
+
@type ||= parsed_unit.guess_type(from)
|
41
|
+
end
|
42
|
+
|
43
|
+
def factor
|
44
|
+
@factor = Alchemist.library.conversion_base_for(type, unit_name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/alchemist/library.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
|
3
1
|
module Alchemist
|
4
|
-
def self.library
|
5
|
-
Library.instance
|
6
|
-
end
|
7
|
-
|
8
2
|
class Library
|
9
|
-
include Singleton
|
10
3
|
|
11
4
|
attr_reader :si_units, :unit_prefixes, :conversion_table, :binary_prefixes
|
12
5
|
|
@@ -15,14 +8,42 @@ module Alchemist
|
|
15
8
|
@si_units = YAML.load_file(Configuration::DEFAULT_SI_UNITS_FILE)
|
16
9
|
@unit_prefixes = YAML.load_file(Configuration::DEFAULT_UNIT_PREFIXES_FILE)
|
17
10
|
@binary_prefixes = YAML.load_file(Configuration::DEFAULT_BINARY_PREFIXES_FILE)
|
11
|
+
@loaded_modules = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def exponent_for(name, prefix)
|
15
|
+
if binary_unit?(name)
|
16
|
+
binary_prefixes[prefix]
|
17
|
+
else
|
18
|
+
unit_prefixes[prefix]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def binary_unit?(name)
|
23
|
+
using_binary? && measurement_for(name).include?(:information_storage)
|
24
|
+
end
|
25
|
+
|
26
|
+
def using_binary?
|
27
|
+
!Alchemist.config.use_si?
|
18
28
|
end
|
19
29
|
|
20
30
|
def categories
|
21
31
|
@conversion_table.keys
|
22
32
|
end
|
23
33
|
|
34
|
+
def load_category(category)
|
35
|
+
@loaded_modules[category] ||= ModuleBuilder.new(category)
|
36
|
+
Numeric.send :include, @loaded_modules[category]
|
37
|
+
end
|
38
|
+
|
39
|
+
def load_all_categories
|
40
|
+
categories.each do |category|
|
41
|
+
load_category category
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
24
45
|
def unit_names category
|
25
|
-
@conversion_table[category.to_sym].map
|
46
|
+
@conversion_table[category.to_sym].map(&:first)
|
26
47
|
end
|
27
48
|
|
28
49
|
def measurement_for unit_name
|
@@ -68,6 +89,8 @@ module Alchemist
|
|
68
89
|
conversions[name] << type
|
69
90
|
conversion_table[type][name] = value
|
70
91
|
end
|
92
|
+
|
93
|
+
@loaded_modules[type].define_unit_method(names)
|
71
94
|
end
|
72
95
|
|
73
96
|
private
|
@@ -1,15 +1,21 @@
|
|
1
|
+
require "bigdecimal"
|
1
2
|
require "alchemist/measurement_convertor"
|
2
3
|
|
3
4
|
module Alchemist
|
4
5
|
class Measurement
|
5
6
|
include Comparable
|
6
7
|
|
7
|
-
attr_reader :
|
8
|
+
attr_reader :unprefixed_unit_name, :exponent, :value, :prefix
|
8
9
|
|
9
|
-
def initialize value, unit_name, exponent = 1.0
|
10
|
+
def initialize value, unit_name, exponent = 1.0, options = {}
|
10
11
|
@value = value.to_f
|
11
|
-
@
|
12
|
+
@unprefixed_unit_name = unit_name.to_sym
|
12
13
|
@exponent = exponent
|
14
|
+
@prefix = options[:prefix] || ""
|
15
|
+
end
|
16
|
+
|
17
|
+
def unit_name
|
18
|
+
"#{prefix}#{unprefixed_unit_name}"
|
13
19
|
end
|
14
20
|
|
15
21
|
def per
|
@@ -27,13 +33,15 @@ module Alchemist
|
|
27
33
|
def + measurement
|
28
34
|
ensure_shared_type!(measurement)
|
29
35
|
converted = measurement.to(unit_name)
|
30
|
-
|
36
|
+
addend = converted.value / exponent
|
37
|
+
remeasure(value + addend)
|
31
38
|
end
|
32
39
|
|
33
40
|
def - measurement
|
34
41
|
ensure_shared_type!(measurement)
|
35
42
|
converted = measurement.to(unit_name)
|
36
|
-
|
43
|
+
subtrahend = converted.value / exponent
|
44
|
+
remeasure(value - subtrahend)
|
37
45
|
end
|
38
46
|
|
39
47
|
def / measurement
|
@@ -68,15 +76,19 @@ module Alchemist
|
|
68
76
|
end
|
69
77
|
|
70
78
|
def to_f
|
71
|
-
|
79
|
+
(precise_value * exponent).to_f
|
80
|
+
end
|
81
|
+
|
82
|
+
def <=> other
|
83
|
+
to_f <=> other.to(unit_name).to_f
|
72
84
|
end
|
73
85
|
|
74
|
-
def
|
75
|
-
|
86
|
+
def == other
|
87
|
+
to_f <=> other.to(unit_name).to_f
|
76
88
|
end
|
77
89
|
|
78
90
|
def types
|
79
|
-
library.measurement_for(
|
91
|
+
library.measurement_for(unprefixed_unit_name)
|
80
92
|
end
|
81
93
|
|
82
94
|
def shared_types other_unit_name
|
@@ -115,12 +127,12 @@ module Alchemist
|
|
115
127
|
end
|
116
128
|
|
117
129
|
def library
|
118
|
-
|
130
|
+
Alchemist.library
|
119
131
|
end
|
120
132
|
|
121
133
|
def ensure_shared_type! measurement
|
122
|
-
if !has_shared_types?(measurement.
|
123
|
-
|
134
|
+
if !has_shared_types?(measurement.unprefixed_unit_name)
|
135
|
+
incompatible_type_error
|
124
136
|
end
|
125
137
|
end
|
126
138
|
|
@@ -128,12 +140,12 @@ module Alchemist
|
|
128
140
|
if conversion_base.is_a?(Array)
|
129
141
|
exponent * conversion_base.first.call(value)
|
130
142
|
else
|
131
|
-
|
143
|
+
precise_value * conversion_base * exponent
|
132
144
|
end
|
133
145
|
end
|
134
146
|
|
135
147
|
def conversion_base_for unit_type
|
136
|
-
library.conversion_base_for(unit_type,
|
148
|
+
library.conversion_base_for(unit_type, unprefixed_unit_name)
|
137
149
|
end
|
138
150
|
|
139
151
|
def has_shared_types? other_unit_name
|
@@ -147,15 +159,21 @@ module Alchemist
|
|
147
159
|
return Alchemist.measure(value * measurement.to_f, new_type)
|
148
160
|
end
|
149
161
|
end
|
150
|
-
|
151
|
-
end
|
152
|
-
|
153
|
-
def incompatible_types
|
154
|
-
raise Exception, "Incompatible Types"
|
162
|
+
incompatible_type_error
|
155
163
|
end
|
156
164
|
|
157
165
|
def convertor
|
158
166
|
MeasurementConvertor.new(self)
|
159
167
|
end
|
168
|
+
|
169
|
+
def precise_value
|
170
|
+
BigDecimal(@value.to_s)
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def incompatible_type_error
|
176
|
+
raise IncompatibleTypeError, "Incompatible Types"
|
177
|
+
end
|
160
178
|
end
|
161
179
|
end
|
@@ -8,44 +8,24 @@ module Alchemist
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def method_missing method, *args, &block
|
11
|
-
|
12
|
-
convert(
|
11
|
+
parsed_unit = parse_prefix(method)
|
12
|
+
convert(parsed_unit)
|
13
13
|
end
|
14
14
|
|
15
15
|
private
|
16
16
|
attr_reader :from
|
17
17
|
|
18
|
-
def
|
19
|
-
|
18
|
+
def parse_prefix(name)
|
19
|
+
PrefixParser.new(name)
|
20
20
|
end
|
21
21
|
|
22
|
-
def convert types, unit_name, exponent
|
23
|
-
if type = types[0]
|
24
|
-
convert_from_type(type, unit_name, exponent)
|
25
|
-
else
|
26
|
-
raise Exception, "Incompatible Types"
|
27
|
-
end
|
28
|
-
end
|
29
22
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
value = value_from(conversion_base, conversion_factor)
|
35
|
-
Measurement.new(value / exponent, unit_name, exponent)
|
36
|
-
end
|
37
|
-
|
38
|
-
def value_from(base, factor)
|
39
|
-
if proc_based?(factor)
|
40
|
-
factor[1].call(base)
|
23
|
+
def convert parsed_unit
|
24
|
+
if parsed_unit.shares_type?(from)
|
25
|
+
ConversionCalculator.new(from, parsed_unit).calculate
|
41
26
|
else
|
42
|
-
|
27
|
+
raise IncompatibleTypeError, "Incompatible Types"
|
43
28
|
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
def proc_based? conversion_factor
|
48
|
-
conversion_factor.is_a? Array
|
49
29
|
end
|
50
30
|
end
|
51
31
|
end
|
@@ -1,41 +1,51 @@
|
|
1
1
|
module Alchemist
|
2
|
-
class ModuleBuilder
|
2
|
+
class ModuleBuilder < Module
|
3
3
|
def initialize category
|
4
|
-
|
4
|
+
define_inspect_method(category)
|
5
|
+
define_unit_methods(category)
|
5
6
|
end
|
6
7
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
category_module.class_eval category_methods
|
8
|
+
def define_unit_method(names)
|
9
|
+
names.each do |name|
|
10
|
+
define_method(name.to_sym) { Alchemist.measure self, name.to_sym }
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
15
|
-
attr_reader :category
|
16
15
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
end
|
16
|
+
def define_inspect_method(category)
|
17
|
+
define_method :inspect do
|
18
|
+
"#<Module(#{category})>"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_unit_methods(category)
|
23
|
+
unit_names(category).map do |name|
|
24
|
+
define_method name do
|
25
|
+
Alchemist.measure self, name.to_sym
|
26
|
+
end
|
27
|
+
prefixes_for(name).map do |prefix|
|
28
|
+
define_method "#{prefix}#{name}" do
|
29
|
+
Alchemist.measure_prefixed self, prefix.to_sym, name.to_sym
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
21
33
|
end
|
22
34
|
|
23
|
-
def
|
24
|
-
|
35
|
+
def library
|
36
|
+
Alchemist.library
|
25
37
|
end
|
26
38
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
39
|
+
def unit_names(category)
|
40
|
+
library.unit_names(category)
|
41
|
+
end
|
42
|
+
|
43
|
+
def prefixes_for(name)
|
44
|
+
if library.si_units.include?(name.to_s)
|
45
|
+
library.unit_prefixes.keys
|
30
46
|
else
|
31
47
|
[]
|
32
48
|
end
|
33
49
|
end
|
34
|
-
|
35
|
-
def prefixed_methods(name)
|
36
|
-
prefixes_with_value(name).map do |prefix, value|
|
37
|
-
%(define_method("#{prefix}#{name}") { Alchemist.measure self, :#{name}, #{value} })
|
38
|
-
end.join("\n")
|
39
|
-
end
|
40
50
|
end
|
41
51
|
end
|
@@ -1,14 +1,18 @@
|
|
1
1
|
module Alchemist
|
2
2
|
class PrefixParser
|
3
|
-
|
3
|
+
attr_reader :unit_name, :exponent
|
4
|
+
|
5
|
+
def initialize(unit)
|
6
|
+
@unit = unit
|
4
7
|
matches = unit.to_s.match(prefix_matcher)
|
5
8
|
prefix, parsed_unit = matches.captures
|
6
9
|
|
7
10
|
if prefix && library.si_units.include?(parsed_unit)
|
8
|
-
|
9
|
-
|
11
|
+
@exponent = library.exponent_for(parsed_unit, prefix.to_sym)
|
12
|
+
@unit_name = parsed_unit.to_sym
|
10
13
|
else
|
11
|
-
|
14
|
+
@exponent = 1
|
15
|
+
@unit_name = unit
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
@@ -16,8 +20,21 @@ module Alchemist
|
|
16
20
|
@prefix_matcher ||= generate_prefix_matcher
|
17
21
|
end
|
18
22
|
|
23
|
+
def shares_type?(from)
|
24
|
+
guess_type(from)
|
25
|
+
end
|
26
|
+
|
27
|
+
def guess_type(from)
|
28
|
+
shared_types(from).first
|
29
|
+
end
|
30
|
+
|
19
31
|
private
|
20
32
|
|
33
|
+
def shared_types from
|
34
|
+
library.measurement_for(from.unprefixed_unit_name) & library.measurement_for(unit_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
21
38
|
def library
|
22
39
|
Alchemist.library
|
23
40
|
end
|
@@ -26,17 +43,5 @@ module Alchemist
|
|
26
43
|
prefix_keys = library.unit_prefixes.keys.map(&:to_s).sort{ |a,b| b.length <=> a.length }
|
27
44
|
%r{^(#{prefix_keys.join('|')})?(.+)}
|
28
45
|
end
|
29
|
-
|
30
|
-
def prefixed_value_for prefix, unit
|
31
|
-
if use_binary_prefix? unit
|
32
|
-
library.binary_prefixes[prefix]
|
33
|
-
else
|
34
|
-
library.unit_prefixes[prefix]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def use_binary_prefix? unit
|
39
|
-
!Alchemist.config.use_si? && library.measurement_for(unit).include?(:information_storage)
|
40
|
-
end
|
41
46
|
end
|
42
47
|
end
|
data/lib/alchemist/version.rb
CHANGED
data/spec/alchemist_spec.rb
CHANGED
@@ -1,32 +1,81 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Alchemist do
|
4
|
+
it "loads a single category into the library" do
|
5
|
+
library_double = stub_library
|
4
6
|
|
5
|
-
it "sets up Numeric" do
|
6
|
-
category_module = build_category_module
|
7
|
-
fake_numeric = build_fake_numeric
|
8
7
|
Alchemist.setup('distance')
|
9
|
-
|
10
|
-
expect(
|
8
|
+
|
9
|
+
expect(library_double).to have_received(:load_category).with('distance')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "loads all categories into the library" do
|
13
|
+
library_double = stub_library
|
14
|
+
|
15
|
+
Alchemist.setup
|
16
|
+
|
17
|
+
expect(library_double).to have_received(:load_all_categories)
|
11
18
|
end
|
12
19
|
|
13
20
|
it "creates a measurement" do
|
14
21
|
unit = Alchemist.measure(1, :meter)
|
22
|
+
|
15
23
|
expect(unit).to eq(1.meter)
|
16
24
|
end
|
17
25
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
it "delegates register to the Library" do
|
27
|
+
stub_library
|
28
|
+
|
29
|
+
Alchemist.register(:foo, :bar, :baz)
|
30
|
+
|
31
|
+
expect(Alchemist.library).to have_received(:register).with(:foo, :bar, :baz)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "builds a library" do
|
35
|
+
library_double = stub_library
|
36
|
+
|
37
|
+
expect(Alchemist.library).to eq library_double
|
38
|
+
end
|
39
|
+
|
40
|
+
it "builds its configuration" do
|
41
|
+
configuration_double = stub_configuration
|
42
|
+
|
43
|
+
expect(Alchemist.config).to eq configuration_double
|
44
|
+
end
|
45
|
+
|
46
|
+
it "will reset! the library" do
|
47
|
+
stub_library
|
48
|
+
2.times { Alchemist.library }
|
49
|
+
Alchemist.reset!
|
50
|
+
Alchemist.library
|
51
|
+
expect(Alchemist::Library).to have_received(:new).twice
|
52
|
+
end
|
53
|
+
|
54
|
+
it "will reset! the configuration" do
|
55
|
+
stub_configuration
|
56
|
+
2.times { Alchemist.config }
|
57
|
+
Alchemist.reset!
|
58
|
+
Alchemist.config
|
59
|
+
expect(Alchemist::Configuration).to have_received(:new).twice
|
60
|
+
end
|
61
|
+
|
62
|
+
def stub_library
|
63
|
+
double(Alchemist::Library, library_methods).tap do |library_double|
|
64
|
+
allow(Alchemist::Library).to receive(:new).and_return(library_double)
|
23
65
|
end
|
24
66
|
end
|
25
67
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
68
|
+
def library_methods
|
69
|
+
{
|
70
|
+
register: true,
|
71
|
+
load_category: true,
|
72
|
+
load_all_categories: true
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def stub_configuration
|
77
|
+
double(Alchemist::Configuration).tap do |configuration_double|
|
78
|
+
allow(Alchemist::Configuration).to receive(:new).and_return(configuration_double)
|
30
79
|
end
|
31
80
|
end
|
32
81
|
end
|
data/spec/byte_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Alchemist
|
4
|
+
RSpec.describe "byte conversions" do
|
5
|
+
it "uses JEDEC specification" do
|
6
|
+
expect(1.kb.to.b.to_f).to eq(1024.0)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "uses SI when configured to do so" do
|
10
|
+
Alchemist.config.use_si = true
|
11
|
+
expect(1.kb.to.b.to_f).to eq(1000.0)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -9,5 +9,21 @@ module Alchemist
|
|
9
9
|
it "can handle elimination of a unit" do
|
10
10
|
expect(4.m.per.m).to eq(4)
|
11
11
|
end
|
12
|
+
|
13
|
+
it "can multiply a coefficient" do
|
14
|
+
expect(10.miles.per.second * 3).to eq(30.miles.per.second)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "considers units different by coefficient" do
|
18
|
+
expect(10.miles.per.second).not_to eq(30.miles.per.second)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "considers unit different by numerators" do
|
22
|
+
expect(10.miles.per.second).not_to eq(10.feet.per.second)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "considers unit different by denominators" do
|
26
|
+
expect(10.miles.per.second).not_to eq(10.miles.per.minutes)
|
27
|
+
end
|
12
28
|
end
|
13
29
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Alchemist
|
4
|
+
describe Configuration do
|
5
|
+
it "defaults use_si to false" do
|
6
|
+
config = Configuration.new
|
7
|
+
expect(config.use_si?).to be false
|
8
|
+
end
|
9
|
+
|
10
|
+
it "allows use_si to be changed" do
|
11
|
+
config = Configuration.new
|
12
|
+
config.use_si = true
|
13
|
+
expect(config.use_si?).to be true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,27 +2,17 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Alchemist
|
4
4
|
describe ConversionTable do
|
5
|
-
after(:each) do
|
6
|
-
load_file default_file
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should use the new file" do
|
10
|
-
load_file good_file
|
11
|
-
expect(conversion_table[:volume]).to eq({ litre: 1.0, swallow: 0.006, pint: 0.5506105 })
|
12
|
-
end
|
13
5
|
|
14
|
-
it "
|
15
|
-
|
16
|
-
expect(
|
6
|
+
it "loads a properly formed file" do
|
7
|
+
conversion_table = ConversionTable.new
|
8
|
+
expect(conversion_table.load_all(good_file)).not_to be_nil
|
17
9
|
end
|
18
10
|
|
19
|
-
|
20
|
-
|
11
|
+
it "fails to load a improperly formed file" do
|
12
|
+
conversion_table = ConversionTable.new
|
13
|
+
expect(conversion_table.load_all(bad_file)).to be_nil
|
21
14
|
end
|
22
15
|
|
23
|
-
def load_file file
|
24
|
-
Alchemist.library.load_conversion_table file
|
25
|
-
end
|
26
16
|
|
27
17
|
def good_file
|
28
18
|
File.join(File.dirname(__FILE__), "fixtures", "good_test.yml")
|
@@ -31,9 +21,5 @@ module Alchemist
|
|
31
21
|
def bad_file
|
32
22
|
File.join(File.dirname(__FILE__), "fixtures", "bad_test.yml")
|
33
23
|
end
|
34
|
-
|
35
|
-
def default_file
|
36
|
-
Configuration::DEFAULT_UNITS_FILE
|
37
|
-
end
|
38
24
|
end
|
39
25
|
end
|
data/spec/error_spec.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Alchemist, "errors" do
|
4
|
+
it "raises IncompatibleTypeError when invalid types are used" do
|
5
|
+
expect { 1.second + 1.meter }.to raise_error(Alchemist::IncompatibleTypeError)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "throws GeospatialArgumentError when invalid type is used" do
|
9
|
+
expect { 1.second.geospatial }.to raise_error(Alchemist::GeospatialArgumentError)
|
10
|
+
end
|
11
|
+
end
|
data/spec/library_spec.rb
CHANGED
@@ -3,10 +3,14 @@ require 'spec_helper'
|
|
3
3
|
module Alchemist
|
4
4
|
describe Library do
|
5
5
|
it "returns a list of the binary prefixes" do
|
6
|
+
library = Library.new
|
6
7
|
expect(library.binary_prefixes[:kilo]).to eq(1024.0)
|
7
8
|
end
|
8
9
|
|
9
10
|
it "can register units with formulas" do
|
11
|
+
stub_loading
|
12
|
+
library = Library.new
|
13
|
+
library.load_category :yetis
|
10
14
|
to = lambda { |t| t + 1 }
|
11
15
|
from = lambda { |t| t - 1 }
|
12
16
|
library.register(:yetis, :yeti, [to, from])
|
@@ -14,26 +18,36 @@ module Alchemist
|
|
14
18
|
end
|
15
19
|
|
16
20
|
it "can register units with plural names" do
|
21
|
+
stub_loading
|
22
|
+
library = Library.new
|
23
|
+
library.load_category :beards
|
17
24
|
library.register(:beards, [:beard_second, :beard_seconds], 1.0)
|
18
25
|
expect(library.conversion_table[:beards]).to eq({:beard_second=>1.0, :beard_seconds=>1.0})
|
19
26
|
end
|
20
27
|
|
21
28
|
it "can register units" do
|
29
|
+
stub_loading
|
30
|
+
library = Library.new
|
31
|
+
library.load_category :quux
|
22
32
|
library.register :quux, :qaat, 1.0
|
23
33
|
library.register :quux, :quut, 3.0
|
24
34
|
expect(library.conversion_table[:quux]).to eq({:qaat=>1.0, :quut=>3.0})
|
25
35
|
end
|
26
36
|
|
27
37
|
it "knows if it has a measurement" do
|
28
|
-
|
38
|
+
library = Library.new
|
39
|
+
expect(library.has_measurement?(:meter)).to be true
|
29
40
|
end
|
30
41
|
|
31
42
|
it "knows if it doesn't have a measurement" do
|
32
|
-
|
43
|
+
library = Library.new
|
44
|
+
expect(library.has_measurement?(:wombat)).to be false
|
33
45
|
end
|
34
46
|
|
35
|
-
def
|
36
|
-
|
47
|
+
def stub_loading
|
48
|
+
module_double = double(Module, define_unit_method: true)
|
49
|
+
allow(ModuleBuilder).to receive(:new).and_return(module_double)
|
50
|
+
allow(Numeric).to receive(:send).with(:include, module_double).and_return(true)
|
37
51
|
end
|
38
52
|
end
|
39
53
|
end
|
data/spec/measurement_spec.rb
CHANGED
@@ -6,6 +6,10 @@ module Alchemist
|
|
6
6
|
expect(1.m).to eq(1.meter)
|
7
7
|
end
|
8
8
|
|
9
|
+
it "has a unit name" do
|
10
|
+
expect(1.kilometer.unit_name).to eq("kilometer")
|
11
|
+
end
|
12
|
+
|
9
13
|
it "can be converted" do
|
10
14
|
expect(5.grams).to eq(0.005.kilograms)
|
11
15
|
end
|
@@ -32,6 +36,10 @@ module Alchemist
|
|
32
36
|
expect(5.meters + 2.inches).to eq(5.0508.meters)
|
33
37
|
end
|
34
38
|
|
39
|
+
it "can add different measurements with exponents" do
|
40
|
+
expect(10.kilometers + 1.mile).to eq(11.609344.kilometers)
|
41
|
+
end
|
42
|
+
|
35
43
|
it "can be subtracted" do
|
36
44
|
expect(3.meters - 2.meters).to eq(1.meter)
|
37
45
|
end
|
@@ -40,6 +48,10 @@ module Alchemist
|
|
40
48
|
expect(5.meters - 2.inches).to eq(4.9492.meters)
|
41
49
|
end
|
42
50
|
|
51
|
+
it "can subtract measurements with exponents" do
|
52
|
+
expect(10.kilometers - 1.mile).to eq(8.390656.kilometers)
|
53
|
+
end
|
54
|
+
|
43
55
|
it "can provide an integer value" do
|
44
56
|
expect(10.meters.to_i).to eq(10)
|
45
57
|
end
|
@@ -78,7 +90,7 @@ module Alchemist
|
|
78
90
|
describe '#geospatial' do
|
79
91
|
|
80
92
|
it 'should convert angles to meters' do
|
81
|
-
expect(1.degree.geospatial).to eq(111318.
|
93
|
+
expect(1.degree.geospatial).to eq(111318.84502145035.meters)
|
82
94
|
end
|
83
95
|
|
84
96
|
it 'should convert distances to radians' do
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Alchemist
|
4
|
+
describe ModuleBuilder do
|
5
|
+
it "allows methods to be added to the build module" do
|
6
|
+
allow(Alchemist).to receive(:library).and_return(library_double)
|
7
|
+
builder = ModuleBuilder.new(:test)
|
8
|
+
builder.define_unit_method([:wombat])
|
9
|
+
expect(builder.instance_methods).to include(:wombat)
|
10
|
+
end
|
11
|
+
|
12
|
+
def library_double
|
13
|
+
double(Alchemist::Library, unit_names: [], si_units: [])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/prefix_parser_spec.rb
CHANGED
@@ -3,8 +3,20 @@ require 'spec_helper'
|
|
3
3
|
module Alchemist
|
4
4
|
describe PrefixParser do
|
5
5
|
it "can parse a prefix" do
|
6
|
-
parsed = PrefixParser.new
|
7
|
-
expect(parsed).to eq(
|
6
|
+
parsed = PrefixParser.new(:kilometer)
|
7
|
+
expect(parsed.exponent).to eq(1000.0)
|
8
|
+
expect(parsed.unit_name).to eq(:meter)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "can parse binary prefixes if si is off" do
|
12
|
+
parsed = PrefixParser.new(:gigabyte)
|
13
|
+
expect(parsed.exponent).to eq(1024 ** 3)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "can parse si prefixes if si is on" do
|
17
|
+
Alchemist.config.use_si = true
|
18
|
+
parsed = PrefixParser.new(:gigabyte)
|
19
|
+
expect(parsed.exponent).to eq(1000 ** 3)
|
8
20
|
end
|
9
21
|
end
|
10
22
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
2
|
|
3
|
+
if ENV["COVERAGE"]
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter "/spec/"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
3
10
|
require 'alchemist'
|
4
11
|
require 'alchemist/geospatial'
|
5
12
|
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.before(:each) do
|
15
|
+
Alchemist.reset!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
6
19
|
Alchemist.setup
|
metadata
CHANGED
@@ -1,59 +1,75 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alchemist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Mongeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: simplecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A scientific conversion library
|
42
56
|
email:
|
43
57
|
- halogenandtoast@gmail.com
|
44
58
|
executables: []
|
45
59
|
extensions: []
|
46
60
|
extra_rdoc_files: []
|
47
61
|
files:
|
48
|
-
- .gitignore
|
62
|
+
- ".gitignore"
|
49
63
|
- Gemfile
|
50
64
|
- Gemfile.lock
|
65
|
+
- NEWS.md
|
51
66
|
- README.md
|
52
67
|
- Rakefile
|
53
68
|
- alchemist.gemspec
|
54
69
|
- lib/alchemist.rb
|
55
70
|
- lib/alchemist/compound_measurement.rb
|
56
71
|
- lib/alchemist/configuration.rb
|
72
|
+
- lib/alchemist/conversion_calculator.rb
|
57
73
|
- lib/alchemist/conversion_table.rb
|
58
74
|
- lib/alchemist/data/binary_prefixes.yml
|
59
75
|
- lib/alchemist/data/si_units.yml
|
@@ -69,12 +85,17 @@ files:
|
|
69
85
|
- lib/alchemist/setup.rb
|
70
86
|
- lib/alchemist/version.rb
|
71
87
|
- spec/alchemist_spec.rb
|
88
|
+
- spec/byte_spec.rb
|
72
89
|
- spec/compound_measurement_spec.rb
|
90
|
+
- spec/configuration_spec.rb
|
73
91
|
- spec/conversion_table_spec.rb
|
92
|
+
- spec/error_spec.rb
|
74
93
|
- spec/fixtures/bad_test.yml
|
75
94
|
- spec/fixtures/good_test.yml
|
76
95
|
- spec/library_spec.rb
|
96
|
+
- spec/measurement_convertor_spec.rb
|
77
97
|
- spec/measurement_spec.rb
|
98
|
+
- spec/module_builder_spec.rb
|
78
99
|
- spec/prefix_parser_spec.rb
|
79
100
|
- spec/spec_helper.rb
|
80
101
|
homepage: http://github.com/halogenandtoast/alchemist
|
@@ -87,28 +108,32 @@ require_paths:
|
|
87
108
|
- lib
|
88
109
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
110
|
requirements:
|
90
|
-
- -
|
111
|
+
- - ">="
|
91
112
|
- !ruby/object:Gem::Version
|
92
113
|
version: '0'
|
93
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
115
|
requirements:
|
95
|
-
- -
|
116
|
+
- - ">="
|
96
117
|
- !ruby/object:Gem::Version
|
97
118
|
version: '0'
|
98
119
|
requirements: []
|
99
120
|
rubyforge_project:
|
100
|
-
rubygems_version: 2.
|
121
|
+
rubygems_version: 2.7.6
|
101
122
|
signing_key:
|
102
123
|
specification_version: 4
|
103
|
-
summary:
|
124
|
+
summary: A scientific conversion library
|
104
125
|
test_files:
|
105
126
|
- spec/alchemist_spec.rb
|
127
|
+
- spec/byte_spec.rb
|
106
128
|
- spec/compound_measurement_spec.rb
|
129
|
+
- spec/configuration_spec.rb
|
107
130
|
- spec/conversion_table_spec.rb
|
131
|
+
- spec/error_spec.rb
|
108
132
|
- spec/fixtures/bad_test.yml
|
109
133
|
- spec/fixtures/good_test.yml
|
110
134
|
- spec/library_spec.rb
|
135
|
+
- spec/measurement_convertor_spec.rb
|
111
136
|
- spec/measurement_spec.rb
|
137
|
+
- spec/module_builder_spec.rb
|
112
138
|
- spec/prefix_parser_spec.rb
|
113
139
|
- spec/spec_helper.rb
|
114
|
-
has_rdoc:
|