alchemist 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +11 -9
- data/README.md +56 -84
- data/Rakefile +3 -12
- data/alchemist.gemspec +2 -0
- data/lib/alchemist.rb +68 -31
- data/lib/alchemist/{compound_numeric_conversion.rb → compound_measurement.rb} +3 -4
- data/lib/alchemist/conversion_table.rb +69 -0
- data/lib/alchemist/data/binary_prefixes.yml +33 -0
- data/lib/alchemist/data/si_units.yml +76 -0
- data/lib/alchemist/data/unit_prefixes.yml +58 -0
- data/lib/alchemist/{units.yml → data/units.yml} +0 -0
- data/lib/alchemist/geospatial.rb +9 -0
- data/lib/alchemist/measurement.rb +128 -0
- data/lib/alchemist/measurement_convertor.rb +35 -0
- data/lib/alchemist/module_builder.rb +41 -0
- data/lib/alchemist/objects/planets/earth.rb +34 -0
- data/lib/alchemist/version.rb +1 -1
- data/spec/alchemist_spec.rb +51 -0
- data/spec/compound_measurement_spec.rb +13 -0
- data/spec/conversion_table_spec.rb +39 -0
- data/spec/fixtures/bad_test.yml +11 -0
- data/spec/fixtures/good_test.yml +11 -0
- data/spec/measurement_spec.rb +69 -0
- data/spec/spec_helper.rb +6 -0
- metadata +44 -19
- data/LICENSE.txt +0 -22
- data/lib/alchemist/binary_prefixes.rb +0 -25
- data/lib/alchemist/compound.rb +0 -7
- data/lib/alchemist/numeric_conversion.rb +0 -146
- data/lib/alchemist/numeric_ext.rb +0 -13
- data/lib/alchemist/si_units.rb +0 -13
- data/lib/alchemist/unit_prefixes.rb +0 -38
- data/lib/alchemist/units.rb +0 -76
- data/test/alchemist_compound_test.rb +0 -12
- data/test/alchemist_measurement_test.rb +0 -13
- data/test/alchemist_test.rb +0 -98
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 09cdd7bc72d33ef49f70bfa21e7a6b98bc56ca35
|
4
|
+
data.tar.gz: 5930f598e0adec3f2a8b3e3e2030fd61b9c48234
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72133a2fa6b707b2e52e6cb5354506d364b176aaab25383b9db8f341be847fa2622a89e888fc3adeb8021f2e347b210961a2fca687d4278a5807da5d41827bc0
|
7
|
+
data.tar.gz: b6ded515a9ebd212ace47ba64a91a9f44619f757457f27a8ae384edf380b327312e5223c444122ae5e3a2552c9d1330964c99e115f88c2e66ac6315f31fc8b3d
|
data/Gemfile.lock
CHANGED
@@ -1,24 +1,26 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
alchemist (0.1.
|
4
|
+
alchemist (0.1.5)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
|
10
|
-
method_source (0.8.1)
|
11
|
-
pry (0.9.12)
|
12
|
-
coderay (~> 1.0.5)
|
13
|
-
method_source (~> 0.8)
|
14
|
-
slop (~> 3.4)
|
9
|
+
diff-lcs (1.2.4)
|
15
10
|
rake (10.0.3)
|
16
|
-
|
11
|
+
rspec (2.14.1)
|
12
|
+
rspec-core (~> 2.14.0)
|
13
|
+
rspec-expectations (~> 2.14.0)
|
14
|
+
rspec-mocks (~> 2.14.0)
|
15
|
+
rspec-core (2.14.3)
|
16
|
+
rspec-expectations (2.14.0)
|
17
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
18
|
+
rspec-mocks (2.14.1)
|
17
19
|
|
18
20
|
PLATFORMS
|
19
21
|
ruby
|
20
22
|
|
21
23
|
DEPENDENCIES
|
22
24
|
alchemist!
|
23
|
-
pry
|
24
25
|
rake
|
26
|
+
rspec
|
data/README.md
CHANGED
@@ -9,113 +9,85 @@ code more readable.
|
|
9
9
|
|
10
10
|
Having code that looks like this is meaningless
|
11
11
|
|
12
|
-
|
12
|
+
```ruby
|
13
|
+
miles = 8 * 1609.344
|
14
|
+
```
|
13
15
|
|
14
16
|
You could add comments
|
15
17
|
|
16
|
-
|
18
|
+
```ruby
|
19
|
+
miles = 8 * 1609.344 # converting meters to miles
|
20
|
+
```
|
17
21
|
|
18
22
|
But why not have this!
|
19
23
|
|
20
|
-
|
24
|
+
```ruby
|
25
|
+
8.meters.to.miles
|
26
|
+
```
|
21
27
|
|
22
28
|
You can even perform mathematical operations
|
23
29
|
|
24
|
-
|
30
|
+
```ruby
|
31
|
+
10.kilometers + 1.mile # 11.609344 kilometers
|
32
|
+
```
|
25
33
|
|
26
34
|
Handling bytes now works according to the JEDEC memory standard
|
27
35
|
|
28
|
-
|
36
|
+
```ruby
|
37
|
+
1.kb.to.b.to_f == 1024.0
|
38
|
+
```
|
29
39
|
|
30
|
-
|
40
|
+
Converting distance of arc length on Earth to an (approximate) corresponding spherical geometry angle can be done with
|
31
41
|
|
32
|
-
|
42
|
+
```ruby
|
43
|
+
require 'alchemist/geospatial'
|
44
|
+
1.mile.geospatial.to.degree == 0.014457066992474555
|
45
|
+
```
|
33
46
|
|
34
|
-
|
47
|
+
To switch to the IEC memory standard, force SI units with
|
35
48
|
|
36
|
-
|
49
|
+
```ruby
|
50
|
+
Alchemist::use_si = true
|
51
|
+
```
|
37
52
|
|
38
|
-
|
39
|
-
now do comparisons without having to convert to floats like so:
|
53
|
+
To see all the units alchemist has built in conversion for, check out the [units file](lib/alchemist/data/units.yml)
|
40
54
|
|
41
|
-
|
55
|
+
<strong>You may also register your own units</strong>
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
Alchemist.register(:distance, [:beard_second, :beard_seconds], 5.angstroms)
|
59
|
+
```
|
42
60
|
|
43
61
|
Installation
|
44
62
|
------------
|
45
63
|
|
46
64
|
gem install alchemist
|
47
65
|
|
48
|
-
|
66
|
+
Setup
|
49
67
|
-----
|
50
68
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
- light\_years
|
77
|
-
- parsecs
|
78
|
-
- nautical\_miles
|
79
|
-
- admirality\_miles
|
80
|
-
- fathoms
|
81
|
-
- cable\_lengths
|
82
|
-
- angstroms
|
83
|
-
- picas
|
84
|
-
- printer\_picas
|
85
|
-
- points
|
86
|
-
- printer\_points
|
87
|
-
|
88
|
-
### Mass
|
89
|
-
|
90
|
-
- grams or grammes
|
91
|
-
- carats
|
92
|
-
- ounces
|
93
|
-
- pennyweights
|
94
|
-
- pounds
|
95
|
-
- troy\_pounds or apothecary\_pounds
|
96
|
-
- slugs
|
97
|
-
- assay\_tons
|
98
|
-
- metric\_tons
|
99
|
-
- tons or short\_tons
|
100
|
-
|
101
|
-
### Volume
|
102
|
-
|
103
|
-
- litres or liters
|
104
|
-
- barrels
|
105
|
-
- bushels
|
106
|
-
- cubic\_meters
|
107
|
-
- cups
|
108
|
-
- imperial\_fluid\_ounces
|
109
|
-
- fluid\_ounces
|
110
|
-
- imperial\_gallons
|
111
|
-
- gallons
|
112
|
-
- imperial\_gills
|
113
|
-
- gills
|
114
|
-
- pints
|
115
|
-
- liquid\_pints
|
116
|
-
- quarts
|
117
|
-
- liquid\_quarts
|
118
|
-
- tablespoons
|
119
|
-
- teaspoons
|
120
|
-
|
121
|
-
### And many more checkout **lib/alchemist.rb** for the rest
|
69
|
+
In order for methods like `1.meter` to work, you'll either need to setup Alchemist yourself:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
Alchemist.setup # This will load every category of measurement
|
73
|
+
```
|
74
|
+
|
75
|
+
if you only want to use one category for conversions you can load it individually:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
Alchemist.setup('distance') # This will load only distance
|
79
|
+
```
|
80
|
+
|
81
|
+
Rails Warning
|
82
|
+
-------------
|
83
|
+
|
84
|
+
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
|
+
|
86
|
+
```ruby
|
87
|
+
Alchemist.measure(10, :bytes)
|
88
|
+
```
|
89
|
+
|
90
|
+
License
|
91
|
+
-------
|
92
|
+
|
93
|
+
Alchemist is licensed under the MIT license as specified in the [gemspec](alchemist.gemspec)
|
data/Rakefile
CHANGED
@@ -1,15 +1,6 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rake'
|
3
|
-
require '
|
3
|
+
require 'rspec/core/rake_task'
|
4
4
|
|
5
|
-
|
6
|
-
task :
|
7
|
-
|
8
|
-
namespace :test do
|
9
|
-
Rake::TestTask.new(:units) do |test|
|
10
|
-
test.libs << 'test'
|
11
|
-
test.ruby_opts << '-rubygems'
|
12
|
-
test.pattern = 'test/*.rb'
|
13
|
-
test.verbose = true
|
14
|
-
end
|
15
|
-
end
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
task default: :spec
|
data/alchemist.gemspec
CHANGED
@@ -11,10 +11,12 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.homepage = 'http://github.com/halogenandtoast/alchemist'
|
12
12
|
gem.summary = 'Conversions... like you\'ve never seen them before!'
|
13
13
|
gem.description = 'Conversions... like you\'ve never seen them before!!'
|
14
|
+
gem.license = 'MIT'
|
14
15
|
|
15
16
|
gem.files = `git ls-files`.split($/)
|
16
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
18
|
gem.require_paths = ["lib"]
|
18
19
|
|
19
20
|
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'rspec'
|
20
22
|
end
|
data/lib/alchemist.rb
CHANGED
@@ -1,31 +1,32 @@
|
|
1
|
-
require "alchemist/
|
2
|
-
require "alchemist/
|
3
|
-
require "alchemist/
|
4
|
-
require "alchemist/
|
1
|
+
require "alchemist/conversion_table"
|
2
|
+
require "alchemist/measurement"
|
3
|
+
require "alchemist/compound_measurement"
|
4
|
+
require "alchemist/module_builder"
|
5
5
|
|
6
6
|
module Alchemist
|
7
|
-
|
8
|
-
NumericConversion.new value, unit, exponent
|
9
|
-
end
|
7
|
+
autoload :Earth, "alchemist/objects/planets/earth"
|
10
8
|
|
11
|
-
|
12
|
-
@use_si ||= false
|
13
|
-
end
|
9
|
+
DATA_DIR = File.join(File.dirname(__FILE__), "alchemist", "data")
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
DEFAULT_UNITS_FILE = File.join(DATA_DIR, "units.yml")
|
12
|
+
DEFAULT_BINARY_PREFIXES_FILE = File.join(DATA_DIR, "binary_prefixes.yml")
|
13
|
+
DEFAULT_SI_UNITS_FILE = File.join(DATA_DIR, "si_units.yml")
|
14
|
+
DEFAULT_UNIT_PREFIXES_FILE = File.join(DATA_DIR, "unit_prefixes.yml")
|
18
15
|
|
19
|
-
def self.
|
20
|
-
|
16
|
+
def self.setup category = nil
|
17
|
+
if category
|
18
|
+
Numeric.send(:include, ModuleBuilder.new(category).build)
|
19
|
+
else
|
20
|
+
conversion_table.keys.each { |category| Numeric.send(:include, ModuleBuilder.new(category).build) }
|
21
|
+
end
|
21
22
|
end
|
22
23
|
|
23
|
-
def self.
|
24
|
-
|
24
|
+
def self.measure value, unit, exponent = 1.0
|
25
|
+
Measurement.new value, unit, exponent
|
25
26
|
end
|
26
27
|
|
27
|
-
def self.
|
28
|
-
|
28
|
+
def self.has_measurement? name
|
29
|
+
conversions.keys.include? name.to_sym
|
29
30
|
end
|
30
31
|
|
31
32
|
def self.measurement_for name
|
@@ -33,9 +34,9 @@ module Alchemist
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def self.register(type, names, value)
|
36
|
-
|
37
37
|
names = Array(names)
|
38
|
-
value = value.is_a?(
|
38
|
+
value = value.is_a?(Measurement) ? value.base(type) : value
|
39
|
+
Alchemist.conversion_table[type] ||= {}
|
39
40
|
|
40
41
|
names.each do |name|
|
41
42
|
conversions[name] ||= []
|
@@ -44,11 +45,6 @@ module Alchemist
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
|
-
def self.register_operation_conversions type, other_type, operation, converted_type
|
48
|
-
operator_actions[operation] ||= []
|
49
|
-
operator_actions[operation] << [type, other_type, converted_type]
|
50
|
-
end
|
51
|
-
|
52
48
|
def self.parse_prefix(unit)
|
53
49
|
matches = unit.to_s.match(prefix_matcher)
|
54
50
|
prefix, parsed_unit = matches.captures
|
@@ -61,16 +57,59 @@ module Alchemist
|
|
61
57
|
end
|
62
58
|
end
|
63
59
|
|
60
|
+
def self.register_operation_conversions type, other_type, operation, converted_type
|
61
|
+
operator_actions[operation] ||= []
|
62
|
+
operator_actions[operation] << [type, other_type, converted_type]
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.operator_actions
|
66
|
+
@operator_actions ||= {}
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.binary_prefixes
|
70
|
+
@binary_prefixes ||= YAML.load_file(DEFAULT_BINARY_PREFIXES_FILE)
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.si_units
|
74
|
+
@si_units ||= YAML.load_file(DEFAULT_SI_UNITS_FILE)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.unit_prefixes
|
78
|
+
@unit_prefixes ||= YAML.load_file(DEFAULT_UNIT_PREFIXES_FILE)
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.use_si
|
82
|
+
@use_si ||= false
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.use_si= use_si
|
86
|
+
@use_si = use_si
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.load_conversion_table(filename=DEFAULT_UNITS_FILE)
|
90
|
+
@conversion_table = ConversionTable.new.load_all(filename)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.conversion_table
|
94
|
+
@conversion_table ||= load_conversion_table
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.conversions
|
98
|
+
@conversions ||= load_conversions
|
99
|
+
end
|
100
|
+
|
101
|
+
|
64
102
|
private
|
65
103
|
|
66
104
|
def self.use_binary_prefix? unit
|
67
105
|
!use_si && measurement_for(unit).include?(:information_storage)
|
68
106
|
end
|
69
107
|
|
70
|
-
|
71
108
|
def self.prefix_matcher
|
72
|
-
|
73
|
-
|
109
|
+
@prefix_matcher ||= begin
|
110
|
+
prefix_keys = unit_prefixes.keys.map(&:to_s).sort{ |a,b| b.length <=> a.length }
|
111
|
+
%r{^(#{prefix_keys.join('|')})?(.+)}
|
112
|
+
end
|
74
113
|
end
|
75
114
|
|
76
115
|
def self.prefixed_value_for prefix, unit
|
@@ -92,5 +131,3 @@ module Alchemist
|
|
92
131
|
conversions
|
93
132
|
end
|
94
133
|
end
|
95
|
-
|
96
|
-
require "alchemist/compound"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Alchemist
|
2
|
-
class
|
2
|
+
class CompoundMeasurement
|
3
3
|
attr_accessor :numerators, :denominators
|
4
4
|
|
5
5
|
def initialize(numerator)
|
@@ -13,13 +13,12 @@ module Alchemist
|
|
13
13
|
when Numeric
|
14
14
|
@coefficient *= value
|
15
15
|
self
|
16
|
-
when Alchemist::
|
16
|
+
when Alchemist::Measurement
|
17
17
|
@numerators << value
|
18
18
|
return consolidate
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
# TODO: minify this
|
23
22
|
def consolidate
|
24
23
|
compress_units
|
25
24
|
set_coefficients
|
@@ -58,7 +57,7 @@ module Alchemist
|
|
58
57
|
|
59
58
|
def method_missing(method, *attrs, &block)
|
60
59
|
if Alchemist.measurement_for(method)
|
61
|
-
@denominators << Alchemist.
|
60
|
+
@denominators << Alchemist.measure(1, method)
|
62
61
|
consolidate
|
63
62
|
end
|
64
63
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Alchemist
|
4
|
+
class ConversionTable
|
5
|
+
|
6
|
+
def load_all(yaml_file)
|
7
|
+
begin
|
8
|
+
YAML.load_file(yaml_file).merge(proc_based)
|
9
|
+
rescue Psych::SyntaxError, Errno::ENOENT
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def proc_based
|
17
|
+
{
|
18
|
+
:density => {
|
19
|
+
:specific_gravity => 1, :sg => 1,
|
20
|
+
:brix => [lambda{ |d| -261.3 / (d - 261.3) }, lambda{ |d| 261.3 - (261.3 / d) }],
|
21
|
+
:plato => [lambda{ |d| -260.0 / (d - 260.0) }, lambda{ |d| 260.0 - (260.0 / d) }],
|
22
|
+
:baume => [lambda{ |d| -145.0 / (d - 145.0) }, lambda{ |d| 145.0 - (145.0 / d) }]
|
23
|
+
},
|
24
|
+
:temperature => temperature
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def temperature
|
29
|
+
{
|
30
|
+
:kelvin => 1.0, :K => 1.0,
|
31
|
+
|
32
|
+
:celsius => celsius_conversion,
|
33
|
+
:centrigrade => celsius_conversion,
|
34
|
+
:degree_celsius => celsius_conversion,
|
35
|
+
:degree_centrigrade => celsius_conversion,
|
36
|
+
:degrees_celsius => celsius_conversion,
|
37
|
+
:degrees_centrigrade => celsius_conversion,
|
38
|
+
:fahrenheit => fahrenheit_conversion,
|
39
|
+
:degree_fahrenheit => fahrenheit_conversion,
|
40
|
+
:degrees_fahrenheit => fahrenheit_conversion,
|
41
|
+
:rankine => 1.8, :rankines => 1.8
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_celsius
|
46
|
+
lambda{ |t| t + 273.15 }
|
47
|
+
end
|
48
|
+
|
49
|
+
def from_celsius
|
50
|
+
lambda{ |t| t - 273.15 }
|
51
|
+
end
|
52
|
+
|
53
|
+
def celsius_conversion
|
54
|
+
[to_celsius, from_celsius]
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_fahrenheit
|
58
|
+
lambda{ |t| (t - 32.0) * (5.0/9.0) + 273.15 }
|
59
|
+
end
|
60
|
+
|
61
|
+
def from_fahrenheit
|
62
|
+
lambda{ |t| (t - 273.15) * (9.0/5.0) + 32.0 }
|
63
|
+
end
|
64
|
+
|
65
|
+
def fahrenheit_conversion
|
66
|
+
[to_fahrenheit, from_fahrenheit]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|