general_units 0.0.4 → 0.0.7
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/lib/general_units.rb +8 -0
- data/lib/general_units/arithmetics/methods.rb +28 -0
- data/lib/general_units/derivatives/box.rb +132 -66
- data/lib/general_units/derivatives/box/packer.rb +52 -0
- data/lib/general_units/helpers/action_view_extension.rb +2 -2
- data/lib/general_units/models/active_record_extension.rb +7 -7
- data/lib/general_units/numeric.rb +4 -0
- data/lib/general_units/units/base/measurement.rb +185 -0
- data/lib/general_units/units/base/unit.rb +36 -0
- data/lib/general_units/units/length.rb +15 -65
- data/lib/general_units/units/volume.rb +20 -0
- data/lib/general_units/units/weight.rb +11 -66
- data/lib/general_units/version.rb +1 -1
- metadata +7 -3
- data/lib/general_units/units/arithmetics/methods.rb +0 -152
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bb73e1c7d4e5f31b9e497ed16286044be1bd8db
|
4
|
+
data.tar.gz: 1c48246254178ba001ca32f74470b0349aa3aef6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50ed29c361c9264f312f7c258d7d2e990d670b39490abbf139b5014e4d20f9896880a2f7515792aaa370ea01095bbafdd6005a80950a57d69d090d623ef2f611
|
7
|
+
data.tar.gz: fb25b41770e84fa70242d47a65b781c6878773aebe6737fa2efb21c0d08464ed060248a4cb53c7ba4f74fd98a37aa38b2b97acb4065df666e045da1d28857c85
|
data/lib/general_units.rb
CHANGED
@@ -2,6 +2,7 @@ require "general_units/version"
|
|
2
2
|
|
3
3
|
module GeneralUnits
|
4
4
|
def self.load!
|
5
|
+
load_arithmetics!
|
5
6
|
load_units!
|
6
7
|
load_numeric!
|
7
8
|
load_derivatives!
|
@@ -9,9 +10,16 @@ module GeneralUnits
|
|
9
10
|
require 'general_units/railtie'
|
10
11
|
end
|
11
12
|
|
13
|
+
def self.load_arithmetics!
|
14
|
+
require 'general_units/arithmetics/methods'
|
15
|
+
end
|
16
|
+
|
12
17
|
def self.load_units!
|
18
|
+
require 'general_units/units/base/measurement'
|
19
|
+
require 'general_units/units/base/unit'
|
13
20
|
require 'general_units/units/weight'
|
14
21
|
require 'general_units/units/length'
|
22
|
+
require 'general_units/units/volume'
|
15
23
|
end
|
16
24
|
|
17
25
|
def self.load_numeric!
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module GeneralUnits
|
2
|
+
|
3
|
+
module Arithmetics
|
4
|
+
def self.two_factors_of(number)
|
5
|
+
if (number = number.to_i) && (number > 1)
|
6
|
+
primes, powers = number.prime_division.transpose
|
7
|
+
exponents = powers.map {|i| (0..i).to_a}
|
8
|
+
divisors = exponents.shift.product(*exponents).map do |powers|
|
9
|
+
primes.zip(powers).map {|prime, power| prime ** power}.inject(:*)
|
10
|
+
end
|
11
|
+
divisors.sort.map {|div| [div, number/div]}
|
12
|
+
else
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.three_factors_of(number)
|
18
|
+
export = []
|
19
|
+
two_factors_of(number).each do |factors|
|
20
|
+
two_factors_of(factors[1]).each do |next_factors|
|
21
|
+
export << [factors[0]] + next_factors
|
22
|
+
end
|
23
|
+
end
|
24
|
+
export
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'prime'
|
2
|
+
require 'general_units/derivatives/box/packer'
|
2
3
|
|
3
4
|
module GeneralUnits
|
4
5
|
|
@@ -12,8 +13,10 @@ module GeneralUnits
|
|
12
13
|
delegate :hash, :to => :attributes
|
13
14
|
|
14
15
|
def initialize(length = 0, width = 0, height = 0, unit)
|
15
|
-
|
16
|
-
|
16
|
+
if unit = valid_unit(unit)
|
17
|
+
VALUES.each {|v| instance_variable_set(:"@#{v}", validate_dimension_value(eval(v), unit))}
|
18
|
+
@unit = unit
|
19
|
+
end
|
17
20
|
end
|
18
21
|
|
19
22
|
def attributes
|
@@ -25,11 +28,11 @@ module GeneralUnits
|
|
25
28
|
end
|
26
29
|
|
27
30
|
def amount
|
28
|
-
|
31
|
+
volume.amount
|
29
32
|
end
|
30
33
|
|
31
34
|
def volume
|
32
|
-
length * width * height
|
35
|
+
Volume.new(length * width * height, :"cubic_#{unit.code}")
|
33
36
|
end
|
34
37
|
|
35
38
|
def has_space?
|
@@ -44,33 +47,50 @@ module GeneralUnits
|
|
44
47
|
values.map {|d| d.to_s(round)}.join("x")
|
45
48
|
end
|
46
49
|
|
47
|
-
def formatted(round = nil)
|
48
|
-
|
50
|
+
def formatted(round = nil, &block)
|
51
|
+
if block_given?
|
52
|
+
yield to_s(round), unit
|
53
|
+
else
|
54
|
+
"#{to_s(round)} #{unit.short}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_volume
|
59
|
+
volume
|
49
60
|
end
|
50
61
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
62
|
+
def two_max_values
|
63
|
+
sorted = values.sort.reverse
|
64
|
+
sorted.first(2)
|
65
|
+
end
|
66
|
+
|
67
|
+
def max_face
|
68
|
+
two_max_values[0] * two_max_values[1]
|
69
|
+
end
|
70
|
+
|
71
|
+
def inspect
|
72
|
+
"<#{self.class.name} length=#{length} width=#{width} height=#{height} unit=#{unit}>"
|
54
73
|
end
|
55
74
|
|
56
75
|
def same_size?(other_object)
|
57
|
-
other_object =
|
76
|
+
other_object = validate_box(other_object)
|
58
77
|
eval VALUES.permutation.to_a.map {|values_names| "(length == other_object.#{values_names[0]} && width == other_object.#{values_names[1]} && height == other_object.#{values_names[2]})"}.join("||")
|
59
78
|
end
|
60
79
|
|
61
80
|
def includes?(other_object)
|
62
|
-
other_object =
|
81
|
+
other_object = validate_box(other_object)
|
63
82
|
eval VALUES.permutation.to_a.map {|values_names| "(length >= other_object.#{values_names[0]} && width >= other_object.#{values_names[1]} && height >= other_object.#{values_names[2]})"}.join("||")
|
64
83
|
end
|
65
84
|
|
66
85
|
### ARITHMETICS START ###
|
86
|
+
delegate :<=>, :<, :>, :<=, :>=, :positive?, :negative?, :div, :divmod, :modulo, :%, :remainder, :abs, :zero?, :nonzero?, :coerce, :to => :volume
|
67
87
|
|
68
88
|
def -@
|
69
89
|
Box.new(*values.map {|v| -v}, unit)
|
70
90
|
end
|
71
91
|
|
72
92
|
def ==(other_object)
|
73
|
-
other_object =
|
93
|
+
other_object = validate_box(other_object)
|
74
94
|
length == other_object.length && width == other_object.width && height == other_object.height
|
75
95
|
rescue
|
76
96
|
false
|
@@ -79,53 +99,11 @@ module GeneralUnits
|
|
79
99
|
def eql?(other_object)
|
80
100
|
self == other_object
|
81
101
|
end
|
82
|
-
|
83
|
-
def <=>(other_object)
|
84
|
-
other_object = validate_capacity_or_length(other_object)
|
85
|
-
volume <=> case other_object
|
86
|
-
when Length then other_object
|
87
|
-
when Box then other_object.volume
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def >(other_object)
|
92
|
-
other_object = validate_capacity_or_length(other_object)
|
93
|
-
volume > case other_object
|
94
|
-
when Length then other_object
|
95
|
-
when Box then other_object.volume
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def <(other_object)
|
100
|
-
other_object = validate_capacity_or_length(other_object)
|
101
|
-
volume < case other_object
|
102
|
-
when Length then other_object
|
103
|
-
when Box then other_object.volume
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def >=(other_object)
|
108
|
-
other_object = validate_capacity_or_length(other_object)
|
109
|
-
volume >= case other_object
|
110
|
-
when Length then other_object
|
111
|
-
when Box then other_object.volume
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def <=(other_object)
|
116
|
-
other_object = validate_capacity_or_length(other_object)
|
117
|
-
volume <= case other_object
|
118
|
-
when Length then other_object
|
119
|
-
when Box then other_object.volume
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
delegate :positive?, :negative?, :to => :volume
|
124
102
|
|
125
103
|
def +(other_object)
|
126
104
|
other_object = validate_capacity_or_length(other_object)
|
127
105
|
case other_object
|
128
|
-
when Length then Box.new(*values.map {|v| v + other_object/3}, unit)
|
106
|
+
when Length, Volume then Box.new(*values.map {|v| v + other_object/3}, unit)
|
129
107
|
when Box then Box.new(*VALUES.map {|v| eval(v) + other_object.send(v)}, unit)
|
130
108
|
end
|
131
109
|
end
|
@@ -133,7 +111,7 @@ module GeneralUnits
|
|
133
111
|
def -(other_object)
|
134
112
|
other_object = validate_capacity_or_length(other_object)
|
135
113
|
case other_object
|
136
|
-
when Length then Box.new(*values.map {|v| v - other_object/3}, unit)
|
114
|
+
when Length, Volume then Box.new(*values.map {|v| v - other_object/3}, unit)
|
137
115
|
when Box then Box.new(*VALUES.map {|v| eval(v) - other_object.send(v)}, unit)
|
138
116
|
end
|
139
117
|
end
|
@@ -141,7 +119,7 @@ module GeneralUnits
|
|
141
119
|
def *(other_object)
|
142
120
|
other_object = validate_capacity_or_length(other_object)
|
143
121
|
case other_object
|
144
|
-
when Length then Box.new(*values.map {|v| v * other_object}, unit)
|
122
|
+
when Length, Volume then Box.new(*values.map {|v| v * other_object}, unit)
|
145
123
|
when Box then Box.new(*VALUES.map {|v| eval(v) * other_object.send(v)}, unit)
|
146
124
|
end
|
147
125
|
end
|
@@ -149,22 +127,109 @@ module GeneralUnits
|
|
149
127
|
def /(other_object)
|
150
128
|
other_object = validate_capacity_or_length(other_object)
|
151
129
|
case other_object
|
152
|
-
when Length then Box.new(*values.map {|v| v / other_object}, unit)
|
130
|
+
when Length, Volume then Box.new(*values.map {|v| v / other_object}, unit)
|
153
131
|
when Box then Box.new(*VALUES.map {|v| eval(v) / other_object.send(v)}, unit)
|
154
132
|
end
|
155
133
|
end
|
134
|
+
|
135
|
+
### ARITHMETICS END ###
|
156
136
|
|
157
|
-
|
137
|
+
def multiplicator(sum)
|
138
|
+
GeneralUnits::Arithmetics.three_factors_of(sum).map do |v|
|
139
|
+
Box.new(v[0]*length, v[1]*width, v[2]*height, unit)
|
140
|
+
end
|
141
|
+
end
|
158
142
|
|
159
|
-
|
143
|
+
def multiply_to_strong_box(sum)
|
144
|
+
multiplicator(sum).min_by {|box| box.values.max - box.values.min}
|
145
|
+
end
|
146
|
+
|
147
|
+
def multiply_to_optimal(sum)
|
148
|
+
if sum.odd?
|
149
|
+
[multiply_to_strong_box(sum-1), self]
|
150
|
+
else
|
151
|
+
[multiply_to_strong_box(sum)]
|
152
|
+
end.compact
|
153
|
+
end
|
154
|
+
|
155
|
+
def concat_with(other_box, &block)
|
156
|
+
#other_box = other_box.convert_to(unit)
|
157
|
+
|
158
|
+
length_1, width_1, height_1 = *values.sort.reverse
|
159
|
+
length_2, width_2, height_2 = *other_box.values.sort.reverse
|
160
|
+
|
161
|
+
x1 = (length_1 - length_2).abs
|
162
|
+
length = [length_1, length_2].max
|
163
|
+
|
164
|
+
x2 = (width_1 - width_2).abs
|
165
|
+
width = [width_1, width_2].max
|
166
|
+
|
167
|
+
height = height_1 + height_2
|
168
|
+
|
169
|
+
if x1 > 0
|
170
|
+
y1 = width
|
171
|
+
z1 = length_1 > length_2 ? height_2 : height_1
|
172
|
+
yield(Box.new(x1, y1, z1, unit)) if block_given?
|
173
|
+
end
|
174
|
+
|
175
|
+
if x2 > 0
|
176
|
+
y2 = ((length_1 > length_2) && (width_1 > width_2)) ? length-x1 : length
|
177
|
+
z2 = width_1 > width_2 ? height_2 : height_1
|
178
|
+
yield(Box.new(x2, y2, z2, unit)) if block_given?
|
179
|
+
end
|
180
|
+
|
181
|
+
Box.new(length, width, height, unit).convert_to(unit)
|
182
|
+
end
|
183
|
+
|
184
|
+
def estimated_spaces_with(other_box, &block)
|
185
|
+
#other_box = other_box.convert_to(unit)
|
186
|
+
|
187
|
+
if includes?(other_box)
|
188
|
+
length_1, width_1, height_1 = *values.sort.reverse
|
189
|
+
length_2, width_2, height_2 = *other_box.values.sort.reverse
|
190
|
+
|
191
|
+
estimated_spaces = []
|
192
|
+
|
193
|
+
x1 = (length_1 - length_2).abs
|
194
|
+
if x1 > 0
|
195
|
+
space1 = Box.new(x1, width_1, height_1, unit)
|
196
|
+
estimated_spaces << space1
|
197
|
+
yield(space1) if block_given?
|
198
|
+
end
|
199
|
+
|
200
|
+
x2 = (width_1 - width_2).abs
|
201
|
+
if x2 > 0
|
202
|
+
space2 = Box.new(length_1 - x1, x2, height_1, unit)
|
203
|
+
estimated_spaces << space2
|
204
|
+
yield(space2) if block_given?
|
205
|
+
end
|
206
|
+
|
207
|
+
x3 = (height_1 - height_2).abs
|
208
|
+
if x3 > 0
|
209
|
+
space3 = Box.new(length_2, width_2, x3, unit)
|
210
|
+
estimated_spaces << space3
|
211
|
+
yield(space3) if block_given?
|
212
|
+
end
|
213
|
+
|
214
|
+
estimated_spaces
|
215
|
+
end
|
216
|
+
end
|
160
217
|
|
161
218
|
private
|
219
|
+
|
220
|
+
def valid_unit(unit)
|
221
|
+
unit_object = case unit
|
222
|
+
when String, Symbol then Length.units.find {|u| u.code.to_s == unit.to_s}
|
223
|
+
when Base::Unit then unit
|
224
|
+
end
|
225
|
+
unit_object || raise(TypeError, "Unprocessable unit #{unit.inspect}")
|
226
|
+
end
|
162
227
|
|
163
|
-
def
|
228
|
+
def validate_dimension_value(val, unit)
|
164
229
|
val.is_a?(Length) ? val.convert_to(unit) : Length.new(val, unit)
|
165
230
|
end
|
166
231
|
|
167
|
-
def
|
232
|
+
def validate_box(val)
|
168
233
|
case val
|
169
234
|
when Box then val.convert_to(unit)
|
170
235
|
else raise(TypeError, "Box required, #{val.class} passed.")
|
@@ -173,9 +238,10 @@ module GeneralUnits
|
|
173
238
|
|
174
239
|
def validate_capacity_or_length(val)
|
175
240
|
case val
|
176
|
-
when Box
|
177
|
-
when
|
178
|
-
|
241
|
+
when Box then val.convert_to(unit)
|
242
|
+
when Volume then val.convert_to(volume.unit.code)
|
243
|
+
when Length, Numeric then val.to_volume(volume.unit.code)
|
244
|
+
else raise(TypeError, "Box or Volume or Numeric required, #{val.class} passed.")
|
179
245
|
end
|
180
246
|
end
|
181
247
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module GeneralUnits
|
2
|
+
class Box
|
3
|
+
|
4
|
+
class Packer
|
5
|
+
attr_reader :boxes, :gaps, :coupled, :gaps_used, :rotated
|
6
|
+
|
7
|
+
def initialize(*boxes)
|
8
|
+
@boxes = boxes.sort_by(&:max_face).reverse
|
9
|
+
@coupled = @boxes.first # first box - biggest
|
10
|
+
@gaps = []
|
11
|
+
@gaps_used = [] # for test
|
12
|
+
@rotated = 0 # if height > current length
|
13
|
+
pack!
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
inspect
|
18
|
+
end
|
19
|
+
|
20
|
+
def inspect
|
21
|
+
"<#{self.class.name} boxes=#{boxes.size} gaps=#{gaps.size} used=#{gaps_used.size} coupled=#{coupled}>"
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def pack!
|
27
|
+
boxes[1..-1].each do |box|
|
28
|
+
unless use_gap_for(box)
|
29
|
+
@coupled = coupled.concat_with(box) {|r| @gaps << r}
|
30
|
+
# if coupled.height > coupled.length
|
31
|
+
# @rotated += 1
|
32
|
+
# end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
coupled
|
36
|
+
end
|
37
|
+
|
38
|
+
def use_gap_for(box)
|
39
|
+
gap = @gaps.find_all {|g| g.includes?(box)}.min_by {|g| g.volume - box.volume}
|
40
|
+
if gap && gap.estimated_spaces_with(box) {|r| @gaps << r}
|
41
|
+
@gaps.delete_if {|r| r.object_id == gap.object_id}
|
42
|
+
@gaps_used << box
|
43
|
+
true
|
44
|
+
else
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -7,11 +7,11 @@ module GeneralUnits
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def weight_units_for_select
|
10
|
-
Weight
|
10
|
+
Weight.units.map {|u| [u.name, u.code]}
|
11
11
|
end
|
12
12
|
|
13
13
|
def length_units_for_select
|
14
|
-
Length
|
14
|
+
Length.units.map {|u| [u.name, u.code]}
|
15
15
|
end
|
16
16
|
|
17
17
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module GeneralUnits
|
2
2
|
|
3
3
|
module ActiveRecordExtension
|
4
|
-
extend ActiveSupport::Concern
|
4
|
+
extend ::ActiveSupport::Concern
|
5
5
|
|
6
6
|
module ClassMethods
|
7
7
|
|
@@ -17,12 +17,12 @@ module GeneralUnits
|
|
17
17
|
self._has_weight[prefix][:default_unit] = default_unit = options[:default_unit]||:kilogram
|
18
18
|
self._has_weight[prefix][:default_unit_method] = default_unit_method = options[:default_unit_method]||:"deafult_#{prefix}_unit"
|
19
19
|
|
20
|
-
|
20
|
+
validates_inclusion_of unit_field, :in => Weight.units.map {|u| u.code.to_s}, :if => Proc.new {|o| o.send(amount_field).present?}
|
21
21
|
|
22
22
|
class_eval <<-EOV
|
23
23
|
|
24
24
|
def #{unit_field}=(value)
|
25
|
-
if value.to_sym.in?(GeneralUnits::Weight
|
25
|
+
if value.to_sym.in?(GeneralUnits::Weight.units.map(&:code))
|
26
26
|
super(value.to_s)
|
27
27
|
else
|
28
28
|
raise ArgumentError, "Unprocessable unit: \#{value.inspect\}"
|
@@ -77,12 +77,12 @@ module GeneralUnits
|
|
77
77
|
self._has_length[prefix][:default_unit] = default_unit = options[:default_unit]||:centimeter
|
78
78
|
self._has_length[prefix][:default_unit_method] = default_unit_method = options[:default_unit_method]||:"deafult_#{prefix}_unit"
|
79
79
|
|
80
|
-
|
80
|
+
validates_inclusion_of unit_field, :in => Length.units.map {|u| u.code.to_s}, :if => Proc.new {|o| o.send(amount_field).present?}
|
81
81
|
|
82
82
|
class_eval <<-EOV
|
83
83
|
|
84
84
|
def #{unit_field}=(value)
|
85
|
-
if value.to_sym.in?(GeneralUnits::Length
|
85
|
+
if value.to_sym.in?(GeneralUnits::Length.units.map(&:code))
|
86
86
|
super(value.to_s)
|
87
87
|
else
|
88
88
|
raise ArgumentError, "Unprocessable unit: \#{value.inspect\}"
|
@@ -140,12 +140,12 @@ module GeneralUnits
|
|
140
140
|
self._has_box[prefix][:default_unit] = default_unit = options[:default_unit]||:centimeter
|
141
141
|
self._has_box[prefix][:default_unit_method] = default_unit_method = options[:default_unit_method]||:"deafult_#{prefix}_unit"
|
142
142
|
|
143
|
-
|
143
|
+
validates_inclusion_of unit_field, :in => Length.units.map {|u| u.code.to_s}, :if => Proc.new {|o| o.send(length_field).present? || o.send(width_field).present? || o.send(height_field).present?}
|
144
144
|
|
145
145
|
class_eval <<-EOV
|
146
146
|
|
147
147
|
def #{unit_field}=(value)
|
148
|
-
if value.to_sym.in?(GeneralUnits::Length
|
148
|
+
if value.to_sym.in?(GeneralUnits::Length.units.map(&:code))
|
149
149
|
super(value.to_s)
|
150
150
|
else
|
151
151
|
raise ArgumentError, "Unprocessable unit: \#{value.inspect\}"
|
@@ -0,0 +1,185 @@
|
|
1
|
+
module GeneralUnits
|
2
|
+
module Base
|
3
|
+
class Measurement
|
4
|
+
class_attribute :units unless defined?(units)
|
5
|
+
|
6
|
+
attr_reader :amount, :unit
|
7
|
+
delegate :hash, :to => :attributes
|
8
|
+
|
9
|
+
def initialize(amount = 0, unit)
|
10
|
+
if unit = valid_unit?(unit)
|
11
|
+
@amount = amount.try(:to_d)||0.to_d
|
12
|
+
@unit = unit
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def attributes
|
17
|
+
{:amount => amount, :unit => unit}
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s(round = nil)
|
21
|
+
"#{to_f.divmod(1).last == 0 ? to_f.round(0) : to_f.round(round||2)}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def inspect
|
25
|
+
"<#{self.class.name} amount=#{amount} unit=#{unit}>"
|
26
|
+
end
|
27
|
+
|
28
|
+
def formatted(round = nil, &block)
|
29
|
+
if block_given?
|
30
|
+
yield to_s(round), unit
|
31
|
+
else
|
32
|
+
"#{to_s(round)} #{unit.short}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
### ARITHMETICS START ###
|
37
|
+
delegate :to_f, :to_d, :to_i, :round, :to => :amount
|
38
|
+
|
39
|
+
def measurement
|
40
|
+
self.class.name.split("::").last.underscore
|
41
|
+
end
|
42
|
+
|
43
|
+
def -@
|
44
|
+
self.class.new(-amount, unit)
|
45
|
+
end
|
46
|
+
|
47
|
+
def ==(other_object)
|
48
|
+
amount == valid_amount(other_object)
|
49
|
+
rescue NoMethodError
|
50
|
+
false
|
51
|
+
end
|
52
|
+
|
53
|
+
def eql?(other_object)
|
54
|
+
self == other_object
|
55
|
+
end
|
56
|
+
|
57
|
+
def <=>(other_object)
|
58
|
+
amount <=> valid_amount(other_object)
|
59
|
+
rescue NoMethodError
|
60
|
+
raise ArgumentError, "Comparison of #{self.class} with #{val.inspect} failed"
|
61
|
+
end
|
62
|
+
|
63
|
+
def >(other_object)
|
64
|
+
amount > valid_amount(other_object)
|
65
|
+
end
|
66
|
+
|
67
|
+
def <(other_object)
|
68
|
+
amount < valid_amount(other_object)
|
69
|
+
end
|
70
|
+
|
71
|
+
def >=(other_object)
|
72
|
+
amount >= valid_amount(other_object)
|
73
|
+
end
|
74
|
+
|
75
|
+
def <=(other_object)
|
76
|
+
amount <= valid_amount(other_object)
|
77
|
+
end
|
78
|
+
|
79
|
+
def positive?
|
80
|
+
self > 0
|
81
|
+
end
|
82
|
+
|
83
|
+
def negative?
|
84
|
+
self < 0
|
85
|
+
end
|
86
|
+
|
87
|
+
def +(other_object)
|
88
|
+
self.class.new(amount + valid_amount(other_object), unit)
|
89
|
+
end
|
90
|
+
|
91
|
+
def -(other_object)
|
92
|
+
self.class.new(amount - valid_amount(other_object), unit)
|
93
|
+
end
|
94
|
+
|
95
|
+
def *(other_object)
|
96
|
+
self.class.new(amount * valid_amount(other_object), unit)
|
97
|
+
end
|
98
|
+
|
99
|
+
def /(other_object)
|
100
|
+
self.class.new(amount / valid_amount(other_object), unit)
|
101
|
+
end
|
102
|
+
|
103
|
+
def div(value)
|
104
|
+
amount.div(value)
|
105
|
+
end
|
106
|
+
|
107
|
+
def divmod(val)
|
108
|
+
if val.is_a?(self.class)
|
109
|
+
divmod_object(val)
|
110
|
+
else
|
111
|
+
divmod_other(val)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def divmod_object(val)
|
116
|
+
amount = val.convert_to(unit).amount
|
117
|
+
quotient, remainder = amount.divmod(amount)
|
118
|
+
[quotient, self.class.new(remainder, unit)]
|
119
|
+
end
|
120
|
+
private :divmod_object
|
121
|
+
|
122
|
+
def divmod_other(val)
|
123
|
+
quotient, remainder = amount.divmod(valid_amount(other_object))
|
124
|
+
[self.class.new(quotient, unit), self.class.new(remainder, unit)]
|
125
|
+
end
|
126
|
+
private :divmod_other
|
127
|
+
|
128
|
+
def modulo(val)
|
129
|
+
divmod(val)[1]
|
130
|
+
end
|
131
|
+
|
132
|
+
def %(val)
|
133
|
+
modulo(val)
|
134
|
+
end
|
135
|
+
|
136
|
+
def remainder(val)
|
137
|
+
if val.is_a?(self.class) && unit != val.unit
|
138
|
+
val = val.convert_to(unit)
|
139
|
+
end
|
140
|
+
|
141
|
+
if (amount < 0 && val < 0) || (amount > 0 && val > 0)
|
142
|
+
self.modulo(val)
|
143
|
+
else
|
144
|
+
self.modulo(val) - (val.is_a?(self.class) ? val : self.class.new(val, unit))
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def abs
|
149
|
+
self.class.new(amount.abs, unit)
|
150
|
+
end
|
151
|
+
|
152
|
+
def zero?
|
153
|
+
amount == 0
|
154
|
+
end
|
155
|
+
|
156
|
+
def nonzero?
|
157
|
+
amount != 0 ? self : nil
|
158
|
+
end
|
159
|
+
|
160
|
+
def coerce(other)
|
161
|
+
[self, other]
|
162
|
+
end
|
163
|
+
### ARITHMETICS END ###
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def valid_amount(other_object)
|
168
|
+
case other_object
|
169
|
+
when self.class then other_object.convert_to(unit).amount
|
170
|
+
when Numeric then other_object
|
171
|
+
else other_object.send(:"to_#{measurement}").convert_to(unit).amount
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def valid_unit?(unit)
|
176
|
+
unit_object = case unit
|
177
|
+
when String, Symbol then units.find {|u| u.code.to_s == unit.to_s}
|
178
|
+
when Unit then unit
|
179
|
+
end
|
180
|
+
unit_object || raise(TypeError, "Unprocessable unit #{unit.inspect}")
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module GeneralUnits
|
2
|
+
module Base
|
3
|
+
class Unit
|
4
|
+
METRIC_SYSTEMS = [:metric, :english, :american]
|
5
|
+
|
6
|
+
attr_reader :code, :name, :short, :fractional, :system
|
7
|
+
|
8
|
+
def initialize(code, name, short, fractional, system = :metric)
|
9
|
+
@code = code
|
10
|
+
@name = name.to_s
|
11
|
+
@short = short.to_s
|
12
|
+
@fractional = fractional.to_d
|
13
|
+
@system = system.to_sym
|
14
|
+
METRIC_SYSTEMS.each do |s|
|
15
|
+
class_eval do
|
16
|
+
define_method "#{s}?" do
|
17
|
+
self.system == s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
name
|
25
|
+
end
|
26
|
+
|
27
|
+
def inspect
|
28
|
+
code
|
29
|
+
end
|
30
|
+
|
31
|
+
def system
|
32
|
+
METRIC_SYSTEMS.find {|s| s == @system}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,52 +1,19 @@
|
|
1
|
-
require 'general_units/units/arithmetics/methods'
|
2
|
-
|
3
1
|
module GeneralUnits
|
4
|
-
class Length
|
5
|
-
::GeneralUnits::Arithmetics.extend_class(self)
|
2
|
+
class Length < ::GeneralUnits::Base::Measurement
|
6
3
|
|
7
|
-
class Unit
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(code, name, short, millimeters)
|
11
|
-
@code = code
|
12
|
-
@name = name.to_s
|
13
|
-
@short = short.to_s
|
14
|
-
@millimeters = millimeters.to_d
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
name
|
19
|
-
end
|
20
|
-
|
21
|
-
def inspect
|
22
|
-
code
|
23
|
-
end
|
4
|
+
class Unit < ::GeneralUnits::Base::Unit
|
5
|
+
alias :millimeters :fractional
|
24
6
|
end
|
25
7
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
attr_reader :amount, :unit
|
37
|
-
delegate :to_f, :to => :amount
|
38
|
-
delegate :hash, :to => :attributes
|
39
|
-
|
40
|
-
def initialize(amount = 0, unit)
|
41
|
-
if unit = valid_unit?(unit)
|
42
|
-
@amount = amount.try(:to_d)||0.to_d
|
43
|
-
@unit = unit
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def attributes
|
48
|
-
{:amount => amount, :unit => unit}
|
49
|
-
end
|
8
|
+
self.units = [Unit.new(:mile_nautical, "Mile (nautical)", "mln", 1852000.0, :english),
|
9
|
+
Unit.new(:mile, "Mile", "ml", 1609344.0, :english),
|
10
|
+
Unit.new(:yard, "Yard", "yrd", 914.4, :english),
|
11
|
+
Unit.new(:foot, "Foot", "ft", 304.8, :english),
|
12
|
+
Unit.new(:inch, "Inch", "in", 25.4, :english),
|
13
|
+
Unit.new(:kilometer, "Kilometer", "km", 1000000.0),
|
14
|
+
Unit.new(:meter, "Meter", "m", 1000.0),
|
15
|
+
Unit.new(:centimeter, "Centimeter", "cm", 10.0),
|
16
|
+
Unit.new(:millimeter, "Millimeter", "mm", 1.0)]
|
50
17
|
|
51
18
|
def convert_to(unit)
|
52
19
|
if convert_unit = valid_unit?(unit)
|
@@ -54,27 +21,10 @@ module GeneralUnits
|
|
54
21
|
Length.new(convert_amount, unit)
|
55
22
|
end
|
56
23
|
end
|
57
|
-
|
58
|
-
def to_s(round = nil)
|
59
|
-
"#{to_f.divmod(1).last == 0 ? to_f.round(0) : to_f.round(round||2)}"
|
60
|
-
end
|
61
24
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
def to_length
|
67
|
-
self
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def valid_unit?(unit)
|
73
|
-
unit_object = case unit
|
74
|
-
when String, Symbol then UNITS.find {|u| u.code.to_s == unit.to_s}
|
75
|
-
when Unit then unit
|
76
|
-
end
|
77
|
-
unit_object || raise(TypeError, "Unprocessable unit #{unit.inspect}")
|
25
|
+
def to_volume(unit_code)
|
26
|
+
volume = GeneralUnits::Volume.new(amount, :"cubic_#{unit.code}")
|
27
|
+
unit_code ? volume.convert_to(unit_code) : volume
|
78
28
|
end
|
79
29
|
|
80
30
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GeneralUnits
|
2
|
+
class Volume < ::GeneralUnits::Base::Measurement
|
3
|
+
|
4
|
+
class Unit < ::GeneralUnits::Base::Unit
|
5
|
+
alias :cubic_millimeters :fractional
|
6
|
+
end
|
7
|
+
|
8
|
+
self.units = Length.units.map do |unit|
|
9
|
+
Unit.new("cubic_#{unit.code}", "Cubic #{unit.name}", "#{unit.short}", unit.fractional**3, unit.system)
|
10
|
+
end
|
11
|
+
|
12
|
+
def convert_to(unit)
|
13
|
+
if convert_unit = valid_unit?(unit)
|
14
|
+
convert_amount = amount * @unit.cubic_millimeters/convert_unit.cubic_millimeters
|
15
|
+
Volume.new(convert_amount, unit)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -1,51 +1,18 @@
|
|
1
|
-
require 'general_units/units/arithmetics/methods'
|
2
|
-
|
3
1
|
module GeneralUnits
|
4
|
-
class Weight
|
5
|
-
::GeneralUnits::Arithmetics.extend_class(self)
|
2
|
+
class Weight < ::GeneralUnits::Base::Measurement
|
6
3
|
|
7
|
-
class Unit
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(code, name, short, grams)
|
11
|
-
@code = code
|
12
|
-
@name = name.to_s
|
13
|
-
@short = short.to_s
|
14
|
-
@grams = grams.to_d
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
name
|
19
|
-
end
|
20
|
-
|
21
|
-
def inspect
|
22
|
-
code
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
UNITS = [Unit.new(:short_ton_us, "Short ton (US)", "Sht.", 907184.74),
|
27
|
-
Unit.new(:pound_us, "Pound (US)", "Pnd.", 453.59237),
|
28
|
-
Unit.new(:ounce_us, "Ounce (US)", "Ounce", 28.349523),
|
29
|
-
Unit.new(:stone, "Stone", "Stn", 6350.2932),
|
30
|
-
Unit.new(:long_ton_uk, "Long Ton (UK)", "Lngt.", 1016046.9),
|
31
|
-
Unit.new(:metric_ton, "Metric Ton", "Ton", 1000000.0),
|
32
|
-
Unit.new(:kilogram, "Kilogram", "Kg.", 1000.0),
|
33
|
-
Unit.new(:gram, "Gram", "g.", 1.0)]
|
34
|
-
|
35
|
-
attr_reader :amount, :unit
|
36
|
-
delegate :to_f, :to => :amount
|
37
|
-
delegate :hash, :to => :attributes
|
38
|
-
|
39
|
-
def initialize(amount = 0, unit)
|
40
|
-
if unit = valid_unit?(unit)
|
41
|
-
@amount = amount.try(:to_d)||0.to_d
|
42
|
-
@unit = unit
|
43
|
-
end
|
4
|
+
class Unit < ::GeneralUnits::Base::Unit
|
5
|
+
alias :grams :fractional
|
44
6
|
end
|
45
7
|
|
46
|
-
|
47
|
-
|
48
|
-
|
8
|
+
self.units = [Unit.new(:short_ton_us, "Short ton (US)", "Sht", 907184.74, :american),
|
9
|
+
Unit.new(:pound_us, "Pound (US)", "Pnd", 453.59237, :american),
|
10
|
+
Unit.new(:ounce_us, "Ounce (US)", "Ounce", 28.349523, :american),
|
11
|
+
Unit.new(:stone, "Stone", "Stn", 6350.2932, :english),
|
12
|
+
Unit.new(:long_ton_uk, "Long Ton (UK)", "Lngt", 1016046.9, :english),
|
13
|
+
Unit.new(:metric_ton, "Metric Ton", "Ton", 1000000.0),
|
14
|
+
Unit.new(:kilogram, "Kilogram", "Kg", 1000.0),
|
15
|
+
Unit.new(:gram, "Gram", "g.", 1.0)]
|
49
16
|
|
50
17
|
def convert_to(unit)
|
51
18
|
if convert_unit = valid_unit?(unit)
|
@@ -53,28 +20,6 @@ module GeneralUnits
|
|
53
20
|
Weight.new(convert_amount, unit)
|
54
21
|
end
|
55
22
|
end
|
56
|
-
|
57
|
-
def to_s(round = nil)
|
58
|
-
"#{to_f.divmod(1).last == 0 ? to_f.round(0) : to_f.round(round||2)}"
|
59
|
-
end
|
60
23
|
|
61
|
-
def formatted(round = nil)
|
62
|
-
"#{to_s(round)} #{unit.short}"
|
63
|
-
end
|
64
|
-
|
65
|
-
def to_weight
|
66
|
-
self
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def valid_unit?(unit)
|
72
|
-
unit_object = case unit
|
73
|
-
when String, Symbol then UNITS.find {|u| u.code.to_s == unit.to_s}
|
74
|
-
when Unit then unit
|
75
|
-
end
|
76
|
-
unit_object || raise(TypeError, "Unprocessable unit #{unit.inspect}")
|
77
|
-
end
|
78
|
-
|
79
24
|
end
|
80
25
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: general_units
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Valery Kvon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -38,14 +38,18 @@ files:
|
|
38
38
|
- Rakefile
|
39
39
|
- general_units.gemspec
|
40
40
|
- lib/general_units.rb
|
41
|
+
- lib/general_units/arithmetics/methods.rb
|
41
42
|
- lib/general_units/derivatives/box.rb
|
43
|
+
- lib/general_units/derivatives/box/packer.rb
|
42
44
|
- lib/general_units/engine.rb
|
43
45
|
- lib/general_units/helpers/action_view_extension.rb
|
44
46
|
- lib/general_units/models/active_record_extension.rb
|
45
47
|
- lib/general_units/numeric.rb
|
46
48
|
- lib/general_units/railtie.rb
|
47
|
-
- lib/general_units/units/
|
49
|
+
- lib/general_units/units/base/measurement.rb
|
50
|
+
- lib/general_units/units/base/unit.rb
|
48
51
|
- lib/general_units/units/length.rb
|
52
|
+
- lib/general_units/units/volume.rb
|
49
53
|
- lib/general_units/units/weight.rb
|
50
54
|
- lib/general_units/version.rb
|
51
55
|
homepage: http://vkvon.ru/projects/general_units
|
@@ -1,152 +0,0 @@
|
|
1
|
-
module GeneralUnits
|
2
|
-
|
3
|
-
module Arithmetics
|
4
|
-
def self.extend_class(klass)
|
5
|
-
unit_name = klass.name.split("::").last.underscore
|
6
|
-
klass.class_eval <<-EOV
|
7
|
-
delegate :to_f, :to_d, :to_i, :to => :amount
|
8
|
-
|
9
|
-
def -@
|
10
|
-
#{klass.name}.new(-amount, unit)
|
11
|
-
end
|
12
|
-
|
13
|
-
def ==(other_object)
|
14
|
-
other_object = other_object.to_#{unit_name} unless other_object.is_a?(#{klass.name})
|
15
|
-
amount == other_object.convert_to(unit).amount
|
16
|
-
rescue NoMethodError
|
17
|
-
false
|
18
|
-
end
|
19
|
-
|
20
|
-
def eql?(other_object)
|
21
|
-
self == other_object
|
22
|
-
end
|
23
|
-
|
24
|
-
def <=>(val)
|
25
|
-
val = val.to_#{unit_name}
|
26
|
-
unless amount == 0 || val.amount == 0 || unit == val.unit
|
27
|
-
val = val.convert_to(unit)
|
28
|
-
end
|
29
|
-
amount <=> val.amount
|
30
|
-
rescue NoMethodError
|
31
|
-
raise ArgumentError, "Comparison of #{self.class} with \#{val.inspect} failed"
|
32
|
-
end
|
33
|
-
|
34
|
-
def >(other_object)
|
35
|
-
other_object = other_object.is_a?(#{klass.name}) ? other_object.convert_to(unit) : other_object.to_#{unit_name}
|
36
|
-
amount > other_object.amount
|
37
|
-
end
|
38
|
-
|
39
|
-
def <(other_object)
|
40
|
-
other_object = other_object.is_a?(#{klass.name}) ? other_object.convert_to(unit) : other_object.to_#{unit_name}
|
41
|
-
amount < other_object.amount
|
42
|
-
end
|
43
|
-
|
44
|
-
def >=(other_object)
|
45
|
-
other_object = other_object.is_a?(#{klass.name}) ? other_object.convert_to(unit) : other_object.to_#{unit_name}
|
46
|
-
amount >= other_object.amount
|
47
|
-
end
|
48
|
-
|
49
|
-
def <=(other_object)
|
50
|
-
other_object = other_object.is_a?(#{klass.name}) ? other_object.convert_to(unit) : other_object.to_#{unit_name}
|
51
|
-
amount <= other_object.amount
|
52
|
-
end
|
53
|
-
|
54
|
-
def positive?
|
55
|
-
amount > 0
|
56
|
-
end
|
57
|
-
|
58
|
-
def negative?
|
59
|
-
amount < 0
|
60
|
-
end
|
61
|
-
|
62
|
-
def +(other_object)
|
63
|
-
other_object = other_object.is_a?(#{klass.name}) ? other_object.convert_to(unit) : other_object.to_#{unit_name}
|
64
|
-
#{klass.name}.new(amount + other_object.amount, unit)
|
65
|
-
end
|
66
|
-
|
67
|
-
def -(other_object)
|
68
|
-
other_object = other_object.is_a?(#{klass.name}) ? other_object.convert_to(unit) : other_object.to_#{unit_name}
|
69
|
-
#{klass.name}.new(amount - other_object.amount, unit)
|
70
|
-
end
|
71
|
-
|
72
|
-
def *(value)
|
73
|
-
case value
|
74
|
-
when Numeric then #{klass.name}.new(amount * value, unit)
|
75
|
-
when #{klass.name} then #{klass.name}.new(amount * value.convert_to(unit).amount, unit)
|
76
|
-
else raise ArgumentError, "Can't multiply a #{klass.name} by a \#{value.class.name}'s value"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def /(value)
|
81
|
-
case value
|
82
|
-
when Numeric then #{klass.name}.new(amount / value, unit)
|
83
|
-
when #{klass.name} then #{klass.name}.new(amount / value.convert_to(unit).amount, unit)
|
84
|
-
else raise ArgumentError, "Can't divide a #{klass.name} by a \#{value.class.name}'s value"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def div(value)
|
89
|
-
amount.div(value)
|
90
|
-
end
|
91
|
-
|
92
|
-
def divmod(val)
|
93
|
-
if val.is_a?(#{klass.name})
|
94
|
-
divmod_object(val)
|
95
|
-
else
|
96
|
-
divmod_other(val)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def divmod_object(val)
|
101
|
-
amount = val.convert_to(unit).amount
|
102
|
-
quotient, remainder = amount.divmod(amount)
|
103
|
-
[quotient, #{klass.name}.new(remainder, unit)]
|
104
|
-
end
|
105
|
-
private :divmod_object
|
106
|
-
|
107
|
-
def divmod_other(val)
|
108
|
-
quotient, remainder = amount.divmod(val.to_#{unit_name}(unit).amount)
|
109
|
-
[#{klass.name}.new(quotient, unit), #{klass.name}.new(remainder, unit)]
|
110
|
-
end
|
111
|
-
private :divmod_other
|
112
|
-
|
113
|
-
def modulo(val)
|
114
|
-
divmod(val)[1]
|
115
|
-
end
|
116
|
-
|
117
|
-
def %(val)
|
118
|
-
modulo(val)
|
119
|
-
end
|
120
|
-
|
121
|
-
def remainder(val)
|
122
|
-
if val.is_a?(#{klass.name}) && unit != val.unit
|
123
|
-
val = val.convert_to(unit)
|
124
|
-
end
|
125
|
-
|
126
|
-
if (amount < 0 && val < 0) || (amount > 0 && val > 0)
|
127
|
-
self.modulo(val)
|
128
|
-
else
|
129
|
-
self.modulo(val) - (val.is_a?(#{klass.name}) ? val : #{klass.name}.new(val, unit))
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def abs
|
134
|
-
#{klass.name}.new(amount.abs, unit)
|
135
|
-
end
|
136
|
-
|
137
|
-
def zero?
|
138
|
-
amount == 0
|
139
|
-
end
|
140
|
-
|
141
|
-
def nonzero?
|
142
|
-
amount != 0 ? self : nil
|
143
|
-
end
|
144
|
-
|
145
|
-
def coerce(other)
|
146
|
-
[self, other]
|
147
|
-
end
|
148
|
-
EOV
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|