measure_scaler 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b92da404900ec09dec83b7aa22f892e39bdb4a29
4
+ data.tar.gz: 1247474d4bdf6b08732bf4b7f8484492bdaa3923
5
+ SHA512:
6
+ metadata.gz: 894b049483dd4ab06ae27f61afd7f9ffd25fa28259ea5158e94e8957b4dc22c7750acf3054e02d1dd9e2ceab58d960e22c3fcb8580e06e8a7b3bbac6e2a490a4
7
+ data.tar.gz: 60bdbdc710e795e533a75601058fbc8ab7bea4768559d06ee2442d14863a85acd8eb357f691b02922ee88f44794a89425682af92b4b717f86da17248521b937a
data/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
1
+ service_name: travis-ci
2
+ repo_token: f2gvKLY4oblFVZqu9NCqryR2BsryRo3mT
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+ cache: bundler
3
+
4
+
5
+ rvm:
6
+ - jruby
7
+ - 1.9.3
8
+ - 2.0.0
9
+
10
+
11
+ notifications:
12
+ email:
13
+ recipients:
14
+ - iwan.buetti@gmail.com
15
+ on_failure: change
16
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in measure_scaler.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # Note: The cmd option is now required due to the increasing number of ways
2
+ # rspec may be run, below are examples of the most common uses.
3
+ # * bundler: 'bundle exec rspec'
4
+ # * bundler binstubs: 'bin/rspec'
5
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
6
+ # installed the spring binstubs per the docs)
7
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
8
+ # * 'just' rspec: 'rspec'
9
+ guard :rspec, cmd: 'bundle exec rspec' do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Iwan Buetti
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # MeasureScaler
2
+
3
+ [![Build Status](https://travis-ci.org/iwan/measure_scaler.png)](https://travis-ci.org/iwan/measure_scaler)
4
+ [![Coverage Status](https://img.shields.io/coveralls/iwan/measure_scaler.svg)](https://coveralls.io/r/iwan/measure_scaler)
5
+ [![Code Climate](https://codeclimate.com/github/iwan/measure_scaler/badges/gpa.svg)](https://codeclimate.com/github/iwan/measure_scaler)
6
+
7
+ Simple gem to deal with measure scaling.
8
+
9
+ A couple of examples:
10
+
11
+ ```ruby
12
+ include MeasureScaler
13
+
14
+ m = Measure.new(12300.456789, "MWh")
15
+ m.scale.to_s # => "12.300456789 GWh"
16
+ ```
17
+ You can add precision:
18
+ ```ruby
19
+ Measure.new(12300.456789, "MWh", 4).scale.to_s # => "12.3 GWh"
20
+ Measure.new(12300.456789, "MWh", 5).scale.to_s # => "12.3 GWh"
21
+ Measure.new(12300.456789, "MWh", 6).scale.to_s # => "12.3005 GWh"
22
+ ```
23
+
24
+ It works with arrays too:
25
+ ```ruby
26
+ Measure.new([20_000, 15_000, 8_934], "MWh").scale.qty # => [20.0, 15.0, 8.934]
27
+ Measure.new([20_000, 15_000, 8_934], "MWh").scale.unit.to_s # => "GWh"
28
+ ```
29
+
30
+ And works with 'reverse' unit of measure...
31
+ ```ruby
32
+ Measure.new(12300.456789, "€/kWh", 4).scale.to_s # => "12.3 €/Wh"
33
+ ```
34
+
35
+ You can define your measure pattern with regexp:
36
+ ```ruby
37
+ PatternDefinitions.config do
38
+ add /^(€\/)(.?)(Wh)$/
39
+ add /^(.?)(Wh)$/
40
+ end
41
+ ```
42
+
43
+
44
+ ## Installation
45
+
46
+ Add this line to your application's Gemfile:
47
+
48
+ gem 'measure_scaler'
49
+
50
+ And then execute:
51
+
52
+ $ bundle
53
+
54
+ Or install it yourself as:
55
+
56
+ $ gem install measure_scaler
57
+
58
+ <!-- ## Usage
59
+
60
+ TODO: Write usage instructions here
61
+ -->
62
+ ## Contributing
63
+
64
+ 1. Fork it ( https://github.com/iwan/measure_scaler/fork )
65
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
66
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
67
+ 4. Push to the branch (`git push origin my-new-feature`)
68
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+
5
+ # Default directory to look in is `/spec`
6
+ # Run with `bundle exec rake spec`
7
+ RSpec::Core::RakeTask.new(:spec) do |task|
8
+ task.rspec_opts = ['--color', '--format', 'progress']
9
+ end
10
+
11
+
12
+ task :default => :spec
@@ -0,0 +1,16 @@
1
+ %w(
2
+ pattern_definitions
3
+ definitions
4
+ errors
5
+ prefixes
6
+ prefix
7
+ quantity_methods
8
+ unit
9
+ measure
10
+ version
11
+ ).each { |file| require File.join(File.dirname(__FILE__), 'measure_scaler', file) }
12
+
13
+
14
+ module MeasureScaler
15
+ # Your code goes here...
16
+ end
@@ -0,0 +1,6 @@
1
+ module MeasureScaler
2
+ PatternDefinitions.config do
3
+ add /^(€\/)(.?)(Wh)$/
4
+ add /^(.?)(Wh)$/
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module MeasureScaler
2
+ class PrefixError < StandardError
3
+
4
+ end
5
+ end
@@ -0,0 +1,49 @@
1
+ module MeasureScaler
2
+ class Measure
3
+ attr_reader :qty, :unit, :precision
4
+
5
+ # Measure.new(12500.34, "MWh")
6
+ def initialize(qty, unit, precision=nil)
7
+ @qty, @precision = qty, precision
8
+ @unit = unit.is_a?(Unit) ? unit : Unit.new(unit)
9
+ end
10
+
11
+ def scale
12
+ # TODO: gestisci unità non riconosciute (non valide)
13
+
14
+
15
+ if @unit.pattern_found?
16
+ ord = @qty.scaling_proposal # multipli di 3
17
+ ord, new_unit = @unit.scale(ord)
18
+ qty = @qty.scale(ord)
19
+ qty = precisize(qty) if @precision
20
+ Measure.new(qty, new_unit, @precision)
21
+ else
22
+ @qty = precisize(@qty) if @precision
23
+ self
24
+ end
25
+ end
26
+
27
+ def to_s
28
+ "#{@qty} #{@unit}"
29
+ end
30
+
31
+
32
+ private
33
+
34
+ # arg is an array or a numeric value
35
+ def precisize(arg)
36
+ if arg.is_a? Array
37
+ arg.map{|e| precisize_num(e)}
38
+ else
39
+ precisize_num(arg)
40
+ end
41
+ end
42
+
43
+ def precisize_num(num)
44
+ lg = Math.log10(num.to_f).ceil
45
+ (num.to_f*10**(@precision-lg)).round/(10.0**(@precision-lg))
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,22 @@
1
+ module MeasureScaler
2
+ module PatternDefinitions
3
+ extend self
4
+
5
+ def def_list
6
+ @def_list ||= Array.new
7
+ end
8
+
9
+ def config(&block)
10
+ instance_eval(&block)
11
+ end
12
+
13
+ def add(regexp)
14
+ def_list << regexp unless def_list.include?(regexp)
15
+ end
16
+
17
+ def clear
18
+ def_list.clear
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,41 @@
1
+ module MeasureScaler
2
+ class Prefix
3
+ include Prefixes
4
+ attr_reader :symbol, :factor
5
+
6
+ def initialize(symbol)
7
+ validate(symbol)
8
+
9
+ @symbol = symbol
10
+ @factor = find_factor(symbol)
11
+ end
12
+
13
+
14
+ def scale(proposed_order=0)
15
+ proposed_order = align_to_3(proposed_order)
16
+ # return the effective order and the new symbol
17
+ new_factor = [@factor+proposed_order, MAX_FACTOR].min
18
+ new_factor = [new_factor, MIN_FACTOR].max
19
+ new_symbol = find_symbol(new_factor)
20
+ effective_order = new_factor - @factor
21
+ [effective_order, new_symbol] # TODO: perché non ritornare [new_order, Prefix.new(new_symbol)] ?
22
+ end
23
+
24
+ def to_s
25
+ @symbol
26
+ end
27
+
28
+ private
29
+ def validate(symbol)
30
+ raise PrefixError, "#{symbol} is not a valid prefix symbol" if !valid?(symbol)
31
+ end
32
+
33
+ def align_to_3(ord)
34
+ if ord%3==0
35
+ ord
36
+ else
37
+ (ord/3.0).round*3
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,35 @@
1
+ module MeasureScaler
2
+ module Prefixes
3
+ # http://en.wikipedia.org/wiki/Metric_prefix
4
+
5
+ LIST = ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"]
6
+ MAX_FACTOR = 24
7
+ MIN_FACTOR = -24
8
+ STEP = 3
9
+
10
+ # Get the base-10 exponent related to the symbol
11
+ # Example: find_factor("M") # => 6 (million)
12
+ def find_factor(symbol)
13
+ valid?(symbol) ? (LIST.index(symbol)*STEP)+MIN_FACTOR : nil
14
+ end
15
+
16
+ # Get the symbol related to base-10 passed
17
+ # The factor should be a multiple of 3, greater or equal to -24
18
+ # and smaller or equal to 24
19
+ # Example: find_symbol(-3) # => "m" (thousandth)
20
+ def find_symbol(factor)
21
+ return nil if factor%STEP!=0 || factor<MIN_FACTOR || factor>MAX_FACTOR
22
+ LIST[(factor-MIN_FACTOR)/STEP]
23
+ end
24
+
25
+ # Is a valid symbol?
26
+ def valid?(symbol)
27
+ LIST.include?(symbol)
28
+ end
29
+
30
+ # Return the list of available symbols
31
+ def symbols_list
32
+ LIST
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ module MeasureScaler
2
+ module QuantityMethods
3
+ Numeric.class_eval do
4
+ def scaling_proposal
5
+ (Math.log10(self).floor/3)*3
6
+ end
7
+
8
+ def scale(ord) # order of magnitude
9
+ # TODO: raise if ord%3!=0
10
+ to_f/10**ord
11
+ end
12
+ end
13
+
14
+ Array.class_eval do
15
+ def scaling_proposal
16
+ a = self.map{|e| e.scaling_proposal}
17
+ h = Hash[a.uniq.map{|e| [e,0]}] # hash for count the proposal scale
18
+ a.each{|e| h[e]+=1}
19
+ most_freq = h.values.max
20
+ a = h.to_a.find_all{|e| e[1]==most_freq}.map{|e| e[0]}.sort
21
+ a[(a.size-1)/2] # or a[a.size/2]
22
+ end
23
+
24
+ def scale(ord) # order of magnitude
25
+ map{|e| e.scale(ord)}
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ module MeasureScaler
2
+ class Unit
3
+ attr_reader :prefix, :preunit, :unit, :direction
4
+ def initialize(string_or_hash)
5
+ case string_or_hash
6
+ when String
7
+ decode_string(string_or_hash)
8
+ when Hash
9
+ h = {direction: 1, preunit: nil}.merge(string_or_hash)
10
+ @prefix = Prefix.new(h[:prefix])
11
+ @preunit = h[:preunit]
12
+ @unit = h[:unit]
13
+ @direction = h[:direction]
14
+
15
+ else
16
+ raise "attribute not valid"
17
+ end
18
+ end
19
+
20
+
21
+ def pattern_found?
22
+ !@prefix.nil?
23
+ end
24
+
25
+ def scale(order) # order is a multiple of 3
26
+ definitive_order, new_prefix = @prefix.scale(order*@direction)
27
+ [ definitive_order*@direction,
28
+ Unit.new(
29
+ prefix: new_prefix,
30
+ preunit: @preunit,
31
+ unit: @unit,
32
+ direction: @direction)
33
+ ]
34
+ end
35
+
36
+ def to_s(prefix=nil)
37
+ "#{@preunit}#{prefix||@prefix}#{@unit}"
38
+ end
39
+
40
+ private
41
+
42
+ def decode_string(s)
43
+ @prefix = nil
44
+ @preunit = nil
45
+ @unit = nil
46
+ @direction = 1
47
+
48
+ s.strip!
49
+ PatternDefinitions.def_list.each do |regexp|
50
+ s.match(regexp) do |md|
51
+ # md is a MatchData obj
52
+ case md.size
53
+ when 3
54
+ @prefix = Prefix.new(md[1]) #
55
+ @unit = md[2]
56
+ when 4
57
+ @preunit = md[1]
58
+ @prefix = Prefix.new(md[2])
59
+ @unit = md[3]
60
+ @direction = -1 if @preunit.include?("/")
61
+ else
62
+ raise "unit string decode failed"
63
+ end
64
+ break
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ module MeasureScaler
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'measure_scaler/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "measure_scaler"
8
+ spec.version = MeasureScaler::VERSION
9
+ spec.authors = ["Iwan Buetti"]
10
+ spec.email = ["iwan.buetti@gmail.com"]
11
+ spec.summary = "Simple gem to deal with measure scaling"
12
+ # spec.description = %q{TODO: Write a longer description. Optional.}
13
+ spec.homepage = "https://github.com/iwan/measure_scaler"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "rspec-nc"
26
+ spec.add_development_dependency "guard"
27
+ spec.add_development_dependency "guard-rspec"
28
+ spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "pry-remote"
30
+ spec.add_development_dependency "pry-nav"
31
+
32
+ spec.add_development_dependency "coveralls"
33
+
34
+ end
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+ include MeasureScaler
3
+
4
+ RSpec.describe Measure do
5
+
6
+
7
+ context 'number' do
8
+ let(:qty1) { 12500.34 }
9
+ let(:unit1) { "MWh" }
10
+ let(:prec1) { 4 } # precision
11
+ let(:valid_measure1) { Measure.new(qty1, unit1) }
12
+ let(:valid_measure2) { Measure.new(qty1, unit1, prec1) }
13
+ let(:valid_measure2) { Measure.new(qty1, unit1, prec1) }
14
+
15
+ let(:valid_measure3) { Measure.new(qty1, "€/kWh") }
16
+ let(:valid_measure4) { Measure.new(qty1, "€/kWh", prec1) }
17
+
18
+ it 'initialize successfully' do
19
+ expect(valid_measure1.qty).to eq(qty1)
20
+ expect(valid_measure1.unit).to be_an_instance_of Unit
21
+ expect(valid_measure1.unit.prefix).to be_an_instance_of Prefix
22
+ expect(valid_measure1.unit.prefix.symbol).to eq("M")
23
+ expect(valid_measure1.unit.prefix.factor).to eq(6)
24
+ expect(valid_measure1.unit.unit).to eq("Wh")
25
+ expect(valid_measure1.unit.preunit).to be_nil
26
+ # ...
27
+ expect(valid_measure1.precision).to be_nil
28
+ expect(valid_measure2.precision).to eq(prec1)
29
+ end
30
+
31
+ it "initialize incorrectly" do
32
+ end
33
+
34
+ context 'without preunit' do
35
+ it "when scaled it's always a measure" do
36
+ expect(valid_measure1.scale).to be_an_instance_of Measure
37
+ expect(valid_measure2.scale).to be_an_instance_of Measure
38
+ end
39
+
40
+ it "scale without precision" do
41
+ scaled = valid_measure1.scale
42
+ expect(scaled.to_s).to eq("12.50034 GWh")
43
+ end
44
+
45
+ it "scale with precision" do
46
+ scaled = valid_measure2.scale
47
+ expect(scaled.to_s).to eq("12.5 GWh")
48
+
49
+ expect(Measure.new(qty1, unit1, 1).scale.to_s).to eq("10.0 GWh")
50
+ expect(Measure.new(qty1, unit1, 2).scale.to_s).to eq("13.0 GWh")
51
+ expect(Measure.new(qty1, unit1, 5).scale.to_s).to eq("12.5 GWh")
52
+ expect(Measure.new(qty1, unit1, 6).scale.to_s).to eq("12.5003 GWh")
53
+ expect(Measure.new(qty1, unit1, 7).scale.to_s).to eq("12.50034 GWh")
54
+ end
55
+ end
56
+
57
+ context 'with preunit' do
58
+ it "when scaled it's always a measure" do
59
+ expect(valid_measure3.scale).to be_an_instance_of Measure
60
+ end
61
+
62
+ it "scale without precision" do
63
+ scaled = valid_measure3.scale
64
+ expect(scaled.to_s).to eq("12.50034 €/Wh")
65
+ end
66
+
67
+ it "scale with precision" do
68
+ scaled = valid_measure4.scale
69
+ expect(scaled.to_s).to eq("12.5 €/Wh")
70
+ end
71
+ end
72
+ end
73
+
74
+ context 'array' do
75
+ let(:arr1) { [12500.34, 201653.1, 5000.9] }
76
+ let(:unit1) { "MWh" }
77
+ let(:prec1) { 4 } # precision
78
+ let(:valid_measure1) { Measure.new(arr1, unit1) }
79
+ let(:valid_measure2) { Measure.new(arr1, unit1, prec1) }
80
+ let(:valid_measure2) { Measure.new(arr1, unit1, prec1) }
81
+
82
+ let(:valid_measure3) { Measure.new(arr1, "€/kWh") }
83
+ let(:valid_measure4) { Measure.new(arr1, "€/kWh", prec1) }
84
+
85
+ it 'initialize successfully' do
86
+ expect(valid_measure1.qty).to eq(arr1)
87
+ expect(valid_measure1.unit).to be_an_instance_of Unit
88
+ expect(valid_measure1.unit.prefix).to be_an_instance_of Prefix
89
+ expect(valid_measure1.unit.prefix.symbol).to eq("M")
90
+ expect(valid_measure1.unit.prefix.factor).to eq(6)
91
+ expect(valid_measure1.unit.unit).to eq("Wh")
92
+ expect(valid_measure1.unit.preunit).to be_nil
93
+ # ...
94
+ expect(valid_measure1.precision).to be_nil
95
+ expect(valid_measure2.precision).to eq(prec1)
96
+ end
97
+
98
+ it "initialize incorrectly" do
99
+ end
100
+
101
+ context 'without preunit' do
102
+ it "when scaled it's always a measure" do
103
+ expect(valid_measure1.scale).to be_an_instance_of Measure
104
+ expect(valid_measure2.scale).to be_an_instance_of Measure
105
+ end
106
+
107
+ it "scale without precision" do
108
+ scaled = valid_measure1.scale
109
+ expect(scaled.qty).to eq([12.50034, 201.6531, 5.0009])
110
+ expect(scaled.unit.to_s).to eq("GWh")
111
+ end
112
+
113
+ it "scale with precision" do
114
+ scaled = valid_measure2.scale
115
+ expect(scaled.qty).to eq([12.5, 201.7, 5.001])
116
+ expect(scaled.unit.to_s).to eq("GWh")
117
+ end
118
+ end
119
+
120
+ context 'with preunit' do
121
+ it "when scaled it's always a measure" do
122
+ expect(valid_measure3.scale).to be_an_instance_of Measure
123
+ expect(valid_measure4.scale).to be_an_instance_of Measure
124
+ end
125
+
126
+ it "scale without precision" do
127
+ scaled = valid_measure3.scale
128
+ expect(scaled.qty).to eq([12.50034, 201.6531, 5.0009])
129
+ expect(scaled.unit.to_s).to eq("€/Wh")
130
+ end
131
+
132
+ it "scale with precision" do
133
+ scaled = valid_measure4.scale
134
+ expect(scaled.qty).to eq([12.5, 201.7, 5.001])
135
+ expect(scaled.unit.to_s).to eq("€/Wh")
136
+ end
137
+
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ include MeasureScaler
3
+
4
+ RSpec.describe PatternDefinitions do
5
+
6
+
7
+ it 'initialize successfully' do
8
+ expect(PatternDefinitions.def_list).to be_an_instance_of Array
9
+
10
+ PatternDefinitions.clear
11
+ expect(PatternDefinitions.def_list.size).to eq(0)
12
+
13
+ PatternDefinitions.config do
14
+ add /^(€\/)(.?)(Wh)$/
15
+ add /^(.?)(Wh)$/
16
+ end
17
+
18
+ expect(PatternDefinitions.def_list.size).to eq(2)
19
+
20
+ PatternDefinitions.config do
21
+ add /^(€\/)(.?)(Wh)$/ # <- already present
22
+ add /^(.?)(W)$/ # <- new entry
23
+ end
24
+ expect(PatternDefinitions.def_list.size).to eq(3)
25
+
26
+ PatternDefinitions.clear
27
+ expect(PatternDefinitions.def_list.size).to eq(0)
28
+ end
29
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ include MeasureScaler
3
+
4
+ RSpec.describe Prefix do
5
+ let(:valid_prefix) { Prefix.new("M") }
6
+
7
+ it 'initialize successfully' do
8
+ expect(valid_prefix).to be_an_instance_of Prefix
9
+ expect(valid_prefix.symbol).to eq("M")
10
+ expect(valid_prefix.factor).to eq(6)
11
+ end
12
+
13
+ it "initialize incorrectly" do
14
+ expect{Prefix.new("X")}.to raise_error(MeasureScaler::PrefixError)
15
+ expect{Prefix.new}.to raise_error
16
+ end
17
+
18
+ it "scale correctly" do
19
+ expect(valid_prefix.scale(0)).to eq([0, "M"])
20
+ expect(valid_prefix.scale(1)).to eq([0, "M"])
21
+ expect(valid_prefix.scale(2)).to eq([3, "G"])
22
+ expect(valid_prefix.scale(3)).to eq([3, "G"])
23
+ expect(valid_prefix.scale(30)).to eq([18, "Y"])
24
+
25
+ expect(valid_prefix.scale(-1)).to eq([0, "M"])
26
+ expect(valid_prefix.scale(-2)).to eq([-3, "k"])
27
+ expect(valid_prefix.scale(-3)).to eq([-3, "k"])
28
+ expect(valid_prefix.scale(-40)).to eq([-30, "y"])
29
+ end
30
+
31
+ it "scale incorrectly" do
32
+
33
+ end
34
+
35
+ it "convert to string" do
36
+ expect(valid_prefix.to_s).to eq("M")
37
+ end
38
+
39
+
40
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ include MeasureScaler
3
+
4
+ RSpec.describe Prefixes do
5
+ class DummyClass; end
6
+
7
+ before(:all) do
8
+ @p = DummyClass.new
9
+ @p.extend Prefixes
10
+ end
11
+
12
+ it 'find first symbol factor' do
13
+ expect(@p.find_factor(Prefixes::LIST.first)).to eq(Prefixes::MIN_FACTOR)
14
+ end
15
+
16
+ it 'find last symbol factor' do
17
+ expect(@p.find_factor(Prefixes::LIST.last)).to eq(Prefixes::MAX_FACTOR)
18
+ end
19
+
20
+ it "doesn't find factor for invalid symbol" do
21
+ expect(@p.find_factor("X")).to be_nil
22
+ end
23
+
24
+ it 'find all symbol factor' do
25
+ Prefixes::LIST.each_with_index do |symbol, i|
26
+ factor = Prefixes::MIN_FACTOR + i*Prefixes::STEP
27
+ expect(@p.find_factor(symbol)).to eq(factor)
28
+ end
29
+ end
30
+
31
+ it "find all factor symbol" do
32
+ f = Prefixes::MIN_FACTOR
33
+ i = 0
34
+ while f<=Prefixes::MAX_FACTOR
35
+ expect(@p.find_symbol(f)).to eql(Prefixes::LIST[i])
36
+ f+=Prefixes::STEP
37
+ i+=1
38
+ end
39
+ end
40
+
41
+ it "doesn't find symbol for invalid factor" do
42
+ expect(@p.find_symbol(5)).to be_nil
43
+ expect(@p.find_symbol(-30)).to be_nil
44
+ expect(@p.find_symbol(30)).to be_nil
45
+ end
46
+
47
+ it "validate valid symbol" do
48
+ expect(@p.valid?("M")).to be_truthy
49
+ expect(@p.valid?("m")).to be_truthy
50
+ expect(@p.valid?("")).to be_truthy
51
+ end
52
+
53
+ it "validate non-valid symbol" do
54
+ expect(@p.valid?("X")).to be_falsey
55
+ expect(@p.valid?(nil)).to be_falsey
56
+ end
57
+
58
+ it "get symbols list" do
59
+ expect(@p.symbols_list).to eq(Prefixes::LIST)
60
+ end
61
+
62
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ include MeasureScaler
3
+
4
+ describe QuantityMethods do
5
+
6
+ context 'number' do
7
+ it "propose a scale" do
8
+ expect(2.5.scaling_proposal).to eq(0)
9
+ expect(25.scaling_proposal).to eq(0)
10
+ expect(250.scaling_proposal).to eq(0)
11
+ expect(999.99.scaling_proposal).to eq(0)
12
+ expect(1000.scaling_proposal).to eq(3)
13
+ expect(2500.scaling_proposal).to eq(3)
14
+ expect(2500000.scaling_proposal).to eq(6)
15
+
16
+ expect(0.25.scaling_proposal).to eq(-3)
17
+ expect(0.025.scaling_proposal).to eq(-3)
18
+ expect(0.0025.scaling_proposal).to eq(-3)
19
+ expect(0.00025.scaling_proposal).to eq(-6)
20
+ end
21
+
22
+ it "scale" do
23
+ expect(2500.scale(-3)).to eq(2500000)
24
+ expect(2500.scale(0)).to eq(2500)
25
+ expect(2500.scale(3)).to eq(2.5)
26
+
27
+ expect(0.scale(3)).to eq(0)
28
+ end
29
+ end
30
+
31
+ context 'array' do
32
+ it "propose a scale" do
33
+ expect([0.25, 1200, 34, 34214, 900, 899000].scaling_proposal).to eq(3)
34
+ expect([0.25, 1200, 34, 34214, 900].scaling_proposal).to eq(0)
35
+ expect([0.25, 1200, 34, 34214, 900, 0.01].scaling_proposal).to eq(0)
36
+ expect([0.25, 0.034, 0.9, 0.01].scaling_proposal).to eq(-3)
37
+ end
38
+
39
+ it "scale" do
40
+ expect([0.25, 1200, 34, 34214, 900, 899000].scale(0)).to eq([0.25, 1200, 34, 34214, 900, 899000])
41
+ expect([0.25, 1200, 34, 34214, 900, 899000].scale(3)).to eq([0.00025, 1.2, 0.034, 34.214, 0.9, 899])
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,6 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+
5
+ require 'pry'
6
+ require 'measure_scaler'
data/spec/unit_spec.rb ADDED
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+ include MeasureScaler
3
+
4
+ RSpec.describe Unit do
5
+ let(:valid_unit_1) { Unit.new("MWh") }
6
+ let(:valid_unit_2) { Unit.new("€/MWh") }
7
+ let(:valid_unit_3) { Unit.new(prefix: "M", preunit: "€/", unit: "Wh", direction: -1) }
8
+ let(:invalid_unit_1) { Unit.new("AAA") }
9
+ before do
10
+ PatternDefinitions.clear
11
+ PatternDefinitions.config do
12
+ add /^(€\/)(.?)(Wh)$/
13
+ add /^(.?)(Wh)$/
14
+ end
15
+
16
+ end
17
+
18
+ it 'initialize successfully' do
19
+ expect(valid_unit_1).to be_an_instance_of Unit
20
+ expect(valid_unit_1.prefix).to be_an_instance_of Prefix
21
+ expect(valid_unit_1.prefix.symbol).to eq("M")
22
+ expect(valid_unit_1.preunit).to be_nil
23
+ expect(valid_unit_1.unit).to eq("Wh")
24
+ expect(valid_unit_1.direction).to eq(1)
25
+
26
+ expect(valid_unit_2).to be_an_instance_of Unit
27
+ expect(valid_unit_2.prefix).to be_an_instance_of Prefix
28
+ expect(valid_unit_2.prefix.symbol).to eq("M")
29
+ expect(valid_unit_2.preunit).to eq("€/")
30
+ expect(valid_unit_2.unit).to eq("Wh")
31
+ expect(valid_unit_2.direction).to eq(-1)
32
+
33
+ expect(valid_unit_3).to be_an_instance_of Unit
34
+ expect(valid_unit_3.prefix).to be_an_instance_of Prefix
35
+ expect(valid_unit_3.prefix.symbol).to eq("M")
36
+ expect(valid_unit_3.preunit).to eq("€/")
37
+ expect(valid_unit_3.unit).to eq("Wh")
38
+ expect(valid_unit_3.direction).to eq(-1)
39
+ end
40
+
41
+ it "fail init" do
42
+ expect{ Unit.new(2)}.to raise_error
43
+ expect(invalid_unit_1).to be_an_instance_of Unit
44
+ expect(invalid_unit_1.prefix).to be_nil
45
+ expect(invalid_unit_1.preunit).to be_nil
46
+ expect(invalid_unit_1.unit).to be_nil
47
+ expect(invalid_unit_1.direction).to eq(1)
48
+ end
49
+
50
+ it "does find pattern" do
51
+ expect(valid_unit_1.pattern_found?).to be_truthy
52
+ end
53
+
54
+ it "doesn't find pattern" do
55
+ expect(invalid_unit_1.pattern_found?).to be_falsey
56
+ end
57
+
58
+ it "scale correctly" do
59
+ def_order, new_unit = valid_unit_1.scale(3)
60
+ expect(def_order).to eq(3)
61
+ expect(new_unit).to be_an_instance_of Unit
62
+ expect(new_unit.prefix).not_to eq(valid_unit_1.prefix)
63
+ expect(new_unit.preunit).to eq(valid_unit_1.preunit)
64
+ expect(new_unit.unit).to eq(valid_unit_1.unit)
65
+ expect(new_unit.direction).to eq(valid_unit_1.direction)
66
+
67
+ def_order, new_unit = valid_unit_2.scale(3)
68
+ expect(def_order).to eq(3)
69
+ expect(new_unit).to be_an_instance_of Unit
70
+ expect(new_unit.prefix).not_to eq(valid_unit_2.prefix)
71
+ expect(new_unit.preunit).to eq(valid_unit_2.preunit)
72
+ expect(new_unit.unit).to eq(valid_unit_2.unit)
73
+ expect(new_unit.direction).to eq(valid_unit_2.direction)
74
+
75
+ end
76
+
77
+ end
data/usage/usage01.rb ADDED
@@ -0,0 +1,21 @@
1
+ require_relative '../lib/measure_scaler'
2
+
3
+
4
+ m = MeasureScaler::Measure.new(12300.456789, "MWh", 4)
5
+ puts m.inspect
6
+ puts m.to_s
7
+ # puts m.unit.inspect
8
+ m2 = m.scale
9
+ puts m2.inspect
10
+ puts m2.to_s
11
+ # puts m.scale
12
+
13
+ puts "--------------------------"
14
+
15
+ puts MeasureScaler::Measure.new(12300.456789, "€/kWh", 4).scale.to_s
16
+
17
+ puts "--------------------------"
18
+
19
+ include MeasureScaler
20
+ puts Measure.new(12300.456789, "€/kWh").scale.to_s
21
+
metadata ADDED
@@ -0,0 +1,219 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: measure_scaler
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Iwan Buetti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
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
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-nc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry-remote
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-nav
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: coveralls
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description:
154
+ email:
155
+ - iwan.buetti@gmail.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - ".coveralls.yml"
161
+ - ".gitignore"
162
+ - ".travis.yml"
163
+ - Gemfile
164
+ - Guardfile
165
+ - LICENSE.txt
166
+ - README.md
167
+ - Rakefile
168
+ - lib/measure_scaler.rb
169
+ - lib/measure_scaler/definitions.rb
170
+ - lib/measure_scaler/errors.rb
171
+ - lib/measure_scaler/measure.rb
172
+ - lib/measure_scaler/pattern_definitions.rb
173
+ - lib/measure_scaler/prefix.rb
174
+ - lib/measure_scaler/prefixes.rb
175
+ - lib/measure_scaler/quantity_methods.rb
176
+ - lib/measure_scaler/unit.rb
177
+ - lib/measure_scaler/version.rb
178
+ - measure_scaler.gemspec
179
+ - spec/measure_spec.rb
180
+ - spec/pattern_spec.rb
181
+ - spec/prefix_spec.rb
182
+ - spec/prefixes_spec.rb
183
+ - spec/quantity_methods_spec.rb
184
+ - spec/spec_helper.rb
185
+ - spec/unit_spec.rb
186
+ - usage/usage01.rb
187
+ homepage: https://github.com/iwan/measure_scaler
188
+ licenses:
189
+ - MIT
190
+ metadata: {}
191
+ post_install_message:
192
+ rdoc_options: []
193
+ require_paths:
194
+ - lib
195
+ required_ruby_version: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ required_rubygems_version: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ version: '0'
205
+ requirements: []
206
+ rubyforge_project:
207
+ rubygems_version: 2.0.3
208
+ signing_key:
209
+ specification_version: 4
210
+ summary: Simple gem to deal with measure scaling
211
+ test_files:
212
+ - spec/measure_spec.rb
213
+ - spec/pattern_spec.rb
214
+ - spec/prefix_spec.rb
215
+ - spec/prefixes_spec.rb
216
+ - spec/quantity_methods_spec.rb
217
+ - spec/spec_helper.rb
218
+ - spec/unit_spec.rb
219
+ has_rdoc: