alchemist 0.1.5 → 0.1.6
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.
- 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
|