unit_measurements 4.8.0 → 4.10.0
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/.github/workflows/main.yml +12 -11
- data/.github/workflows/pages.yml +31 -0
- data/CHANGELOG.md +19 -1
- data/Gemfile.lock +1 -1
- data/README.md +36 -69
- data/lib/unit_measurements/arithmetic.rb +91 -20
- data/lib/unit_measurements/base.rb +56 -0
- data/lib/unit_measurements/comparison.rb +45 -4
- data/lib/unit_measurements/conversion.rb +40 -10
- data/lib/unit_measurements/errors/parse_error.rb +20 -0
- data/lib/unit_measurements/errors/primitive_unit_already_set_error.rb +11 -0
- data/lib/unit_measurements/errors/unit_already_defined_error.rb +20 -0
- data/lib/unit_measurements/errors/unit_error.rb +19 -0
- data/lib/unit_measurements/formatter.rb +31 -9
- data/lib/unit_measurements/math.rb +51 -14
- data/lib/unit_measurements/measurement.rb +251 -8
- data/lib/unit_measurements/normalizer.rb +92 -3
- data/lib/unit_measurements/parser.rb +169 -7
- data/lib/unit_measurements/unit.rb +128 -1
- data/lib/unit_measurements/unit_group.rb +160 -11
- data/lib/unit_measurements/unit_group_builder.rb +133 -0
- data/lib/unit_measurements/unit_groups/all.rb +1 -6
- data/lib/unit_measurements/unit_groups/information_entropy.rb +15 -0
- data/lib/unit_measurements/version.rb +2 -1
- data/lib/unit_measurements.rb +16 -0
- data/unit_measurements.gemspec +1 -0
- data/units.md +13 -0
- metadata +5 -2
@@ -5,9 +5,54 @@
|
|
5
5
|
require "set"
|
6
6
|
|
7
7
|
module UnitMeasurements
|
8
|
+
# The +UnitMeasurements::Unit+ class represents a unit of measurement and
|
9
|
+
# provides methods to interact with its properties and conversion factors.
|
10
|
+
#
|
11
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
12
|
+
# @since 1.0.0
|
8
13
|
class Unit
|
9
|
-
|
14
|
+
# The name of the unit.
|
15
|
+
#
|
16
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
17
|
+
# @since 1.0.0
|
18
|
+
attr_reader :name
|
10
19
|
|
20
|
+
# The conversion value of the unit. It can be a numeric value or a string in
|
21
|
+
# the form of a number followed by a unit name (e.g., “10 m”).
|
22
|
+
#
|
23
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
24
|
+
# @since 1.0.0
|
25
|
+
attr_reader :value
|
26
|
+
|
27
|
+
# A set of alternative names for the unit.
|
28
|
+
#
|
29
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
30
|
+
# @since 1.0.0
|
31
|
+
attr_reader :aliases
|
32
|
+
|
33
|
+
# The system to which the unit belongs (e.g., “metric”, “imperial”).
|
34
|
+
#
|
35
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
36
|
+
# @since 4.0.0
|
37
|
+
attr_reader :system
|
38
|
+
|
39
|
+
# The unit group to which the unit belongs.
|
40
|
+
#
|
41
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
42
|
+
# @since 1.0.0
|
43
|
+
attr_reader :unit_group
|
44
|
+
|
45
|
+
# Initializes a new +Unit+ instance.
|
46
|
+
#
|
47
|
+
# @param [String|Symbol] name The name of the unit.
|
48
|
+
# @param [String|Numeric] value The conversion value of the unit.
|
49
|
+
# @param [Array<String|Symbol>] aliases Alternative names for the unit.
|
50
|
+
# @param [String|Symbol|NilClass] system The system to which the unit belongs.
|
51
|
+
# @param [UnitGroup|NilClass] unit_group The unit group to which the unit belongs.
|
52
|
+
#
|
53
|
+
# @see UnitGroup
|
54
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
55
|
+
# @since 1.0.0
|
11
56
|
def initialize(name, value:, aliases:, system:, unit_group: nil)
|
12
57
|
@name = name.to_s.freeze
|
13
58
|
@value = value
|
@@ -16,6 +61,19 @@ module UnitMeasurements
|
|
16
61
|
@unit_group = unit_group
|
17
62
|
end
|
18
63
|
|
64
|
+
# Returns a new +Unit+ instance with specified attributes.
|
65
|
+
#
|
66
|
+
# @param [String|Symbol] name The new name of the unit.
|
67
|
+
# @param [String|Numeric] value The new conversion value of the unit.
|
68
|
+
# @param [Set<String>] aliases New alternative names for the unit.
|
69
|
+
# @param [String|Symbol|NilClass] system The new system to which the unit belongs.
|
70
|
+
# @param [UnitGroup|NilClass] unit_group The new unit group to which the unit belongs.
|
71
|
+
#
|
72
|
+
# @return [Unit] A new unit with specified parameters.
|
73
|
+
#
|
74
|
+
# @see UnitGroup
|
75
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
76
|
+
# @since 1.0.0
|
19
77
|
def with(name: nil, value: nil, aliases: nil, system: nil, unit_group: nil)
|
20
78
|
self.class.new(
|
21
79
|
(name || self.name),
|
@@ -26,19 +84,58 @@ module UnitMeasurements
|
|
26
84
|
)
|
27
85
|
end
|
28
86
|
|
87
|
+
# Returns an array containing the name of the unit and its aliases, sorted
|
88
|
+
# alphabetically.
|
89
|
+
#
|
90
|
+
# @example
|
91
|
+
# UnitMeasurements::Length.new(1, "m").unit.names
|
92
|
+
# => ["m", "meter", "meters", "metre", "metres"]
|
93
|
+
#
|
94
|
+
# @return [Array<String>] An array of unit names.
|
95
|
+
#
|
96
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
97
|
+
# @since 1.0.0
|
29
98
|
def names
|
30
99
|
(aliases + [name]).sort.freeze
|
31
100
|
end
|
32
101
|
|
102
|
+
# Returns the name of the unit as a string.
|
103
|
+
#
|
104
|
+
# @example
|
105
|
+
# UnitMeasurements::Length.new(1, "m").unit.to_s
|
106
|
+
# => "m"
|
107
|
+
#
|
108
|
+
# @return [String] The name of the unit.
|
109
|
+
#
|
110
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
111
|
+
# @since 1.0.0
|
33
112
|
def to_s
|
34
113
|
name
|
35
114
|
end
|
36
115
|
|
116
|
+
# Returns an object representation of the unit, including its aliases if present.
|
117
|
+
#
|
118
|
+
# @return [Object] An object representation of the +unit+.
|
119
|
+
#
|
120
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
121
|
+
# @since 1.0.0
|
37
122
|
def inspect
|
38
123
|
aliases = "(#{@aliases.join(", ")})" if @aliases.any?
|
39
124
|
"#<#{self.class.name}: #{name} #{aliases}>"
|
40
125
|
end
|
41
126
|
|
127
|
+
# Calculates the conversion factor for the unit. This method is recursively
|
128
|
+
# invoked to calculate the conversion factor of the unit, if unit conversion
|
129
|
+
# +value+ is specified with respect to the other unit.
|
130
|
+
#
|
131
|
+
# This method uses +parse_value+ method to extract the conversion value and
|
132
|
+
# the unit.
|
133
|
+
#
|
134
|
+
# @return [Numeric] The conversion factor as a numeric value.
|
135
|
+
#
|
136
|
+
# @see #parse_value
|
137
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
138
|
+
# @since 1.0.0
|
42
139
|
def conversion_factor
|
43
140
|
return value if value.is_a?(Numeric)
|
44
141
|
|
@@ -50,6 +147,10 @@ module UnitMeasurements
|
|
50
147
|
|
51
148
|
private
|
52
149
|
|
150
|
+
# Decimal prefixes for SI units.
|
151
|
+
#
|
152
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
153
|
+
# @since 1.0.0
|
53
154
|
SI_DECIMAL_PREFIXES = [
|
54
155
|
["q", %w(quecto), 1e-30],
|
55
156
|
["r", %w(ronto), 1e-27],
|
@@ -77,6 +178,32 @@ module UnitMeasurements
|
|
77
178
|
["Q", %w(quetta), 1e+30]
|
78
179
|
].map(&:freeze).freeze
|
79
180
|
|
181
|
+
# Parses tokens and returns a +conversion value+ and the +unit+.
|
182
|
+
#
|
183
|
+
# This method is used internally to parse the conversion value of the unit
|
184
|
+
# while calculating the conversion factor. It handles cases where the value
|
185
|
+
# can be provided as a string or an array containing a number and a unit.
|
186
|
+
#
|
187
|
+
# For example, if the value is provided as a string in the form of "10 m",
|
188
|
+
# it will be parsed to return 10.0 as the conversion value and "m" as the
|
189
|
+
# unit.
|
190
|
+
#
|
191
|
+
# This method returns conversion value in +rational+ number to avoid precision
|
192
|
+
# errors and frozen string of unit name.
|
193
|
+
#
|
194
|
+
# @param [String|Array] tokens
|
195
|
+
# The value to be parsed. It can be either a string or an array containing
|
196
|
+
# a number and a unit.
|
197
|
+
#
|
198
|
+
# @return [Array<Numeric, String>] The array of conversion value and the unit.
|
199
|
+
#
|
200
|
+
# @raise [BaseError]
|
201
|
+
# if +tokens+ is not an instance of +Array+ or +String+, or +tokens+ array
|
202
|
+
# contains more than two elements.
|
203
|
+
#
|
204
|
+
# @see #conversion_factor
|
205
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
206
|
+
# @since 1.2.0
|
80
207
|
def parse_value(tokens)
|
81
208
|
case tokens
|
82
209
|
when String
|
@@ -3,18 +3,89 @@
|
|
3
3
|
# -*- warn_indent: true -*-
|
4
4
|
|
5
5
|
module UnitMeasurements
|
6
|
+
# The +UnitMeasurements::UnitGroup+ class provides a collection of units with
|
7
|
+
# methods to retrieve units by name, check if a unit is defined, and much more.
|
8
|
+
#
|
9
|
+
# It serves as a container for organizing and working with units within the
|
10
|
+
# unit group.
|
11
|
+
#
|
12
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
13
|
+
# @since 1.0.0
|
6
14
|
class UnitGroup
|
7
|
-
|
15
|
+
# The primitive unit of the unit group.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# UnitMeasurements::Length.primitive
|
19
|
+
# => #<UnitMeasurements::Unit: m (meter, meters, metre, metres)>
|
20
|
+
#
|
21
|
+
# @return [Unit] The primitive unit of the unit group.
|
22
|
+
#
|
23
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
24
|
+
# @since 1.0.0
|
25
|
+
attr_reader :primitive
|
8
26
|
|
27
|
+
# An array of units within the unit group.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# UnitMeasurements::Length.units
|
31
|
+
# => [#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>, ...]
|
32
|
+
#
|
33
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
34
|
+
# @since 1.0.0
|
35
|
+
attr_reader :units
|
36
|
+
|
37
|
+
# Initializes a new +UnitGroup+ instance.
|
38
|
+
#
|
39
|
+
# @param [String|Symbol, optional] primitive The name of the primitive unit.
|
40
|
+
# @param [Array<Unit>] units An array of +Unit+ instances.
|
41
|
+
#
|
42
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
43
|
+
# @since 1.0.0
|
9
44
|
def initialize(primitive, units)
|
10
45
|
@units = units.map { |unit| unit.with(unit_group: self) }
|
11
46
|
@primitive = unit_for!(primitive) if primitive
|
12
47
|
end
|
13
48
|
|
49
|
+
# Returns the unit instance for a given unit name. It returns +nil+ if unit
|
50
|
+
# is not defined within the unit group.
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
# UnitMeasurements::Length.unit_for("m")
|
54
|
+
# => #<UnitMeasurements::Unit: m (meter, meters, metre, metres)>
|
55
|
+
#
|
56
|
+
# UnitMeasurements::Length.unit_for("z")
|
57
|
+
# => nil
|
58
|
+
#
|
59
|
+
# @param [String|Symbol] name The name of the unit.
|
60
|
+
#
|
61
|
+
# @return [Unit|NilClass] A +Unit+ instance or +nil+ if the unit is not found.
|
62
|
+
#
|
63
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
64
|
+
# @since 1.0.0
|
14
65
|
def unit_for(name)
|
15
66
|
unit_name_to_unit(name)
|
16
67
|
end
|
17
68
|
|
69
|
+
# This method works same as +unit_for+ but it raises +UnitError+ if the
|
70
|
+
# unit is not defined within the unit group.
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# UnitMeasurements::Length.unit_for!("m")
|
74
|
+
# => #<UnitMeasurements::Unit: m (meter, meters, metre, metres)>
|
75
|
+
#
|
76
|
+
# UnitMeasurements::Length.unit_for!("z")
|
77
|
+
# => Invalid unit: 'z'. (UnitMeasurements::UnitError)
|
78
|
+
#
|
79
|
+
# @param [String|Symbol] name The name of the unit to look for.
|
80
|
+
#
|
81
|
+
# @return [Unit] A +Unit+ instance.
|
82
|
+
#
|
83
|
+
# @raise [UnitError] If the unit is not found.
|
84
|
+
#
|
85
|
+
# @see #unit_for
|
86
|
+
# @see UnitError
|
87
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
88
|
+
# @since 1.0.0
|
18
89
|
def unit_for!(name)
|
19
90
|
unit = unit_for(name)
|
20
91
|
raise UnitError, name unless unit
|
@@ -23,32 +94,110 @@ module UnitMeasurements
|
|
23
94
|
end
|
24
95
|
alias_method :[], :unit_for!
|
25
96
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
97
|
+
# Returns an array of names of all the units defined within the unit group,
|
98
|
+
# sorted alphabetically.
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# UnitMeasurements::Length.unit_names
|
102
|
+
# => ["ft", "in", "m", "mi", "yd"]
|
103
|
+
#
|
104
|
+
# @return [Array<String>] An array of unit names.
|
105
|
+
#
|
106
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
107
|
+
# @since 1.0.0
|
32
108
|
def unit_names
|
33
109
|
units.map(&:name).sort
|
34
110
|
end
|
35
111
|
|
112
|
+
# Returns an array of names and aliases of all the units defined within the
|
113
|
+
# unit group, sorted alphabetically.
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
# UnitMeasurements::Length.unit_names_with_aliases
|
117
|
+
# => ["\"", "'", "feet", "foot", "ft", "in", "inch", "inches", "m", "meter", "meters", "metre", "metres", "mi", "mile", "miles", "yard", "yards", "yd"]
|
118
|
+
#
|
119
|
+
# @return [Array<String>] An array of unit names and aliases.
|
120
|
+
#
|
121
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
122
|
+
# @since 1.0.0
|
36
123
|
def unit_names_with_aliases
|
37
124
|
units.flat_map(&:names).sort
|
38
125
|
end
|
39
126
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
127
|
+
# Checks if a unit with a given name is defined within the unit group.
|
128
|
+
#
|
129
|
+
# @example
|
130
|
+
# UnitMeasurements::Length.defined?("m")
|
131
|
+
# => true
|
132
|
+
#
|
133
|
+
# UnitMeasurements::Length.defined?("metre")
|
134
|
+
# => false
|
135
|
+
#
|
136
|
+
# @param [String|Symbol] name The name of the unit to look for.
|
137
|
+
#
|
138
|
+
# @return [TrueClass|FalseClass] +true+
|
139
|
+
# if the unit is defined, +false+ otherwise.
|
140
|
+
#
|
141
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
142
|
+
# @since 1.0.0
|
44
143
|
def defined?(name)
|
45
144
|
unit = unit_for(name)
|
46
145
|
|
47
146
|
unit ? unit.name == name.to_s : false
|
48
147
|
end
|
49
148
|
|
149
|
+
# Checks if a given name corresponds to a defined unit or an alias of any
|
150
|
+
# defined unit.
|
151
|
+
#
|
152
|
+
# @example
|
153
|
+
# UnitMeasurements::Length.unit_or_alias?("m")
|
154
|
+
# => true
|
155
|
+
#
|
156
|
+
# UnitMeasurements::Length.unit_or_alias?("metre")
|
157
|
+
# => true
|
158
|
+
#
|
159
|
+
# @param [String|Symbol] name The name or alias of the unit to look for.
|
160
|
+
#
|
161
|
+
# @return [TrueClass|FalseClass] +true+
|
162
|
+
# if the name corresponds to a unit or alias, +false+ otherwise.
|
163
|
+
#
|
164
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
165
|
+
# @since 1.0.0
|
50
166
|
def unit_or_alias?(name)
|
51
167
|
!!unit_for(name)
|
52
168
|
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
# @private
|
173
|
+
# Returns a hash where keys are unit names (including aliases) and values
|
174
|
+
# are corresponding +Unit+ instances.
|
175
|
+
#
|
176
|
+
# @example
|
177
|
+
# UnitMeasurements::Length.unit_with_name_and_aliases
|
178
|
+
# => {"m"=>#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>, ...}
|
179
|
+
#
|
180
|
+
# @return [Hash] A hash containing unit +names+ as keys and +Unit+ objects as values.
|
181
|
+
#
|
182
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
183
|
+
# @since 1.0.0
|
184
|
+
def unit_with_name_and_aliases
|
185
|
+
units.each_with_object({}) do |unit, hash|
|
186
|
+
unit.names.each { |name| hash[name.to_s] = unit }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# @private
|
191
|
+
# Returns the +Unit+ instance for a given unit name.
|
192
|
+
#
|
193
|
+
# @param [String|Symbol] name The name of the unit.
|
194
|
+
#
|
195
|
+
# @return [Unit|NilClass] A +Unit+ instance or +nil+ if the unit is not found.
|
196
|
+
#
|
197
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
198
|
+
# @since 1.0.0
|
199
|
+
def unit_name_to_unit(name)
|
200
|
+
unit_with_name_and_aliases[name.to_s]
|
201
|
+
end
|
53
202
|
end
|
54
203
|
end
|
@@ -3,25 +3,101 @@
|
|
3
3
|
# -*- warn_indent: true -*-
|
4
4
|
|
5
5
|
module UnitMeasurements
|
6
|
+
# The +UnitMeasurements::UnitGroupBuilder+ class provides a flexible and
|
7
|
+
# configurable way to define units and create unit groups with specific systems
|
8
|
+
# and primitive unit.
|
9
|
+
#
|
10
|
+
# It provides methods like +primitive+, +system+, +unit+, and +si_unit+ to define
|
11
|
+
# units and their conversions within the unit group.
|
12
|
+
#
|
13
|
+
# @see UnitGroup
|
14
|
+
# @see PrimitiveUnitAlreadySetError
|
15
|
+
# @see UnitAlreadyDefinedError
|
16
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
17
|
+
# @since 1.0.0
|
6
18
|
class UnitGroupBuilder
|
19
|
+
# An array to store the units defined using the builder.
|
20
|
+
#
|
21
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
22
|
+
# @since 1.0.0
|
7
23
|
attr_reader :units
|
8
24
|
|
25
|
+
# Initializes a new +UnitGroupBuilder+ instance.
|
26
|
+
#
|
27
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
28
|
+
# @since 1.0.0
|
9
29
|
def initialize
|
10
30
|
@units = []
|
11
31
|
end
|
12
32
|
|
33
|
+
# Defines a +unit+ and adds it to the list of units.
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# unit "in", value: "25.4 mm", aliases: ['"', "inch", "inches"]
|
37
|
+
#
|
38
|
+
# @param [String|Symbol] name The name of the unit.
|
39
|
+
# @param [Numeric|String] value The conversion value of the unit.
|
40
|
+
# @param [Array<String|Symbol>, optional] aliases An array of alternative names for the unit.
|
41
|
+
#
|
42
|
+
# @return [Unit] An instance of +Unit+.
|
43
|
+
#
|
44
|
+
# @see #build_unit
|
45
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
46
|
+
# @since 1.0.0
|
13
47
|
def unit(name, value: 1.0, aliases: [])
|
14
48
|
@units << build_unit(name, value: value, aliases: aliases)
|
15
49
|
end
|
16
50
|
|
51
|
+
# Builds a set of +SI units+ and adds them to the list of units. This method
|
52
|
+
# defines unit defined using +name+ along with all the SI prefixes.
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# si_unit "m", aliases: ["meter", "metre", "meters", "metres"]
|
56
|
+
#
|
57
|
+
# @param [String|Symbol] name The name of the unit.
|
58
|
+
# @param [Numeric|String] value The conversion value of the unit.
|
59
|
+
# @param [Array<String|Symbol>, optional] aliases An array of alternative names for the unit.
|
60
|
+
#
|
61
|
+
# @return [Array<Unit>] An array of +Unit+ instances.
|
62
|
+
#
|
63
|
+
# @see #build_si_units
|
64
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
65
|
+
# @since 1.0.0
|
17
66
|
def si_unit(name, value: 1.0, aliases: [])
|
18
67
|
@units += build_si_units(name, value: value, aliases: aliases)
|
19
68
|
end
|
20
69
|
|
70
|
+
# Constructs and returns a +UnitGroup+ object based on the units defined
|
71
|
+
# using the builder.
|
72
|
+
#
|
73
|
+
# @return [UnitGroup]
|
74
|
+
# An instance of +UnitGroup+ containing units and their conversions.
|
75
|
+
#
|
76
|
+
# @see UnitGroup
|
77
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
78
|
+
# @since 1.0.0
|
21
79
|
def build
|
22
80
|
UnitGroup.new(@primitive, @units)
|
23
81
|
end
|
24
82
|
|
83
|
+
# Defines the +unit system+ within the unit group and evaluates the provided
|
84
|
+
# block in the context of the builder.
|
85
|
+
#
|
86
|
+
# This method is used to group multiple units within the certain unit system,
|
87
|
+
# viz., metric, imperial, etc.
|
88
|
+
#
|
89
|
+
# @example Defining an imperial system with inches and feet:
|
90
|
+
# system :imperial do
|
91
|
+
# unit "in", value: "25.4 mm", aliases: ['"', "inch", "inches"]
|
92
|
+
# unit "ft", value: "12 in", aliases: ["'", "foot", "feet"]
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# @param [String|Symbol] system_name
|
96
|
+
# The name of the unit system in which the units are to be grouped.
|
97
|
+
# @param block A block of code to be executed in the context of the builder.
|
98
|
+
#
|
99
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
100
|
+
# @since 4.0.0
|
25
101
|
def system(system_name, &block)
|
26
102
|
@system = system_name
|
27
103
|
instance_eval(&block) if block_given?
|
@@ -29,6 +105,20 @@ module UnitMeasurements
|
|
29
105
|
@system = nil
|
30
106
|
end
|
31
107
|
|
108
|
+
# Sets the +primitive+ unit for the unit group. It raises +PrimitiveUnitAlreadySetError+
|
109
|
+
# if the primitive unit has already been set for the unit group.
|
110
|
+
#
|
111
|
+
# @example
|
112
|
+
# primitive "m"
|
113
|
+
#
|
114
|
+
# @param [String|Symbol] primitive The name of the primitive unit.
|
115
|
+
#
|
116
|
+
# @raise [PrimitiveUnitAlreadySetError]
|
117
|
+
# If the primitive unit has already been set for the unit group.
|
118
|
+
#
|
119
|
+
# @see PrimitiveUnitAlreadySetError
|
120
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
121
|
+
# @since 4.0.0
|
32
122
|
def primitive(primitive)
|
33
123
|
raise PrimitiveUnitAlreadySetError if @primitive
|
34
124
|
|
@@ -37,6 +127,20 @@ module UnitMeasurements
|
|
37
127
|
|
38
128
|
private
|
39
129
|
|
130
|
+
# @private
|
131
|
+
# Builds an array of +Unit+ instances with one instance of +Unit+ with name
|
132
|
+
# +name+ along with all SI prefixed +Unit+ instances for it.
|
133
|
+
#
|
134
|
+
# @param [String|Symbol] name The name of the unit.
|
135
|
+
# @param [Numeric|String] value The conversion value of the unit.
|
136
|
+
# @param [Array<String|Symbol>, optional] aliases
|
137
|
+
# An array of alternative names for the unit.
|
138
|
+
#
|
139
|
+
# @return [Array<Unit>] An array of +Unit+ instances.
|
140
|
+
#
|
141
|
+
# @see #build_unit
|
142
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
143
|
+
# @since 1.0.0
|
40
144
|
def build_si_units(name, value:, aliases:)
|
41
145
|
si_units = [build_unit(name, value: value, aliases: aliases)]
|
42
146
|
|
@@ -50,6 +154,19 @@ module UnitMeasurements
|
|
50
154
|
si_units
|
51
155
|
end
|
52
156
|
|
157
|
+
# @private
|
158
|
+
# Builds an instance of +Unit+ with name +name+, and specified conversion
|
159
|
+
# value, and alternate names.
|
160
|
+
#
|
161
|
+
# @param [String|Symbol] name The name of the unit.
|
162
|
+
# @param [Numeric|String] value The conversion value of the unit.
|
163
|
+
# @param [Array<String|Symbol>, optional] aliases
|
164
|
+
# An array of alternative names for the unit.
|
165
|
+
#
|
166
|
+
# @return [Unit] An instance of +Unit+.
|
167
|
+
#
|
168
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
169
|
+
# @since 1.0.0
|
53
170
|
def build_unit(name, value:, aliases:)
|
54
171
|
unit = Unit.new(name, value: value, aliases: aliases, system: @system)
|
55
172
|
check_for_duplicate_unit_names!(unit)
|
@@ -57,6 +174,22 @@ module UnitMeasurements
|
|
57
174
|
unit
|
58
175
|
end
|
59
176
|
|
177
|
+
# @private
|
178
|
+
# Checks for duplicate unit names within the list of units.
|
179
|
+
#
|
180
|
+
# This method ensures that there are no duplicate unit names within the list
|
181
|
+
# of units. If a duplicate name is found, it raises a +UnitAlreadyDefinedError+.
|
182
|
+
#
|
183
|
+
# This method is used internally by the +UnitGroupBuilder+ class to build units
|
184
|
+
# and handle unit definitions.
|
185
|
+
#
|
186
|
+
# @param [Unit] unit The unit to be checked.
|
187
|
+
#
|
188
|
+
# @raise [UnitAlreadyDefinedError]
|
189
|
+
# If the unit name is already defined in the list of units.
|
190
|
+
#
|
191
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
192
|
+
# @since 1.0.0
|
60
193
|
def check_for_duplicate_unit_names!(unit)
|
61
194
|
names = @units.flat_map(&:names)
|
62
195
|
|
@@ -2,8 +2,6 @@
|
|
2
2
|
# -*- frozen_string_literal: true -*-
|
3
3
|
# -*- warn_indent: true -*-
|
4
4
|
|
5
|
-
## Fundamental SI units
|
6
|
-
|
7
5
|
require_relative "amount_of_substance"
|
8
6
|
require_relative "electric_current"
|
9
7
|
require_relative "length"
|
@@ -12,8 +10,6 @@ require_relative "temperature"
|
|
12
10
|
require_relative "time"
|
13
11
|
require_relative "weight"
|
14
12
|
|
15
|
-
## Derived units
|
16
|
-
|
17
13
|
require_relative "area"
|
18
14
|
require_relative "volume"
|
19
15
|
require_relative "density"
|
@@ -50,8 +46,7 @@ require_relative "radioactivity"
|
|
50
46
|
require_relative "radiation_exposure"
|
51
47
|
require_relative "radiation_absorbed_dose"
|
52
48
|
require_relative "radiation_equivalent_dose"
|
53
|
-
|
54
|
-
## Other units
|
49
|
+
require_relative "information_entropy"
|
55
50
|
|
56
51
|
require_relative "sound_level"
|
57
52
|
require_relative "plane_angle"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# -*- frozen_string_literal: true -*-
|
3
|
+
# -*- warn_indent: true -*-
|
4
|
+
|
5
|
+
UnitMeasurements::InformationEntropy = UnitMeasurements.build do
|
6
|
+
primitive "nat"
|
7
|
+
|
8
|
+
si_unit "b", value: "1 Sh", aliases: ["bit", "bits"]
|
9
|
+
si_unit "B", value: [2.pow(3), "b"], aliases: ["byte", "bytes"]
|
10
|
+
|
11
|
+
unit "Sh", value: [Math.log(2), "nat"], aliases: ["shannon", "shannons"]
|
12
|
+
unit "nat", aliases: ["nit", "nepit", "natural unit of information"]
|
13
|
+
unit "nybl", value: [2.pow(2), "b"], aliases: ["nibble", "nibbles", "nybble", "nyble"]
|
14
|
+
unit "Hart", value: [Math.log(10), "nat"], aliases: ["hartley", "ban", "dit"]
|
15
|
+
end
|
data/lib/unit_measurements.rb
CHANGED
@@ -2,7 +2,23 @@
|
|
2
2
|
# -*- frozen_string_literal: true -*-
|
3
3
|
# -*- warn_indent: true -*-
|
4
4
|
|
5
|
+
# The +UnitMeasurements+ module serves as a container for various functionalities
|
6
|
+
# related to unit measurements. It provides methods for creating custom unit
|
7
|
+
# groups, defining units, performing arithmetic operations, comparison between
|
8
|
+
# measurements, conversions, normalization of input strings, parsing measurements
|
9
|
+
# from strings, and more. It is a fundamental part of the unit measurements library.
|
10
|
+
#
|
11
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
12
|
+
# @since 0.1.0
|
5
13
|
module UnitMeasurements
|
14
|
+
# This is the base class for custom errors in the +UnitMeasurements+ module.
|
15
|
+
#
|
16
|
+
# @see ParseError
|
17
|
+
# @see PrimitiveUnitAlreadySetError
|
18
|
+
# @see UnitAlreadyDefinedError
|
19
|
+
# @see UnitError
|
20
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
21
|
+
# @since 1.1.0
|
6
22
|
class BaseError < StandardError; end
|
7
23
|
end
|
8
24
|
|
data/unit_measurements.gemspec
CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
23
23
|
|
24
24
|
spec.metadata["homepage_uri"] = spec.homepage
|
25
|
+
spec.metadata["documentation_uri"] = "https://shivam091.github.io/unit_measurements"
|
25
26
|
spec.metadata["source_code_uri"] = "https://github.com/shivam091/unit_measurements"
|
26
27
|
spec.metadata["changelog_uri"] = "https://github.com/shivam091/unit_measurements/blob/main/CHANGELOG.md"
|
27
28
|
spec.metadata["bug_tracker_uri"] = "https://github.com/shivam091/unit_measurements/issues"
|
data/units.md
CHANGED
@@ -553,3 +553,16 @@ These units are defined in `UnitMeasurements::RadiationEquivalentDose`.
|
|
553
553
|
|:--|:--|:--|
|
554
554
|
| _1_ | _Sv*_ | _sievert, sieverts_ |
|
555
555
|
| 2 | rem | röntgen equivalent man, roentgen equivalent man |
|
556
|
+
|
557
|
+
## 48. Information entropy
|
558
|
+
|
559
|
+
These units are defined in `UnitMeasurements::InformationEntropy`.
|
560
|
+
|
561
|
+
| # | Name | Aliases |
|
562
|
+
|:--|:--|:--|
|
563
|
+
| 1 | b* | bit, bits |
|
564
|
+
| 2 | B* | byte, bytes |
|
565
|
+
| 3 | Sh | shannon, shannons |
|
566
|
+
| _4_ | _nat_ | _nit, nepit, natural unit of information_ |
|
567
|
+
| 5 | nybl | nibble, nibbles, nybble, nyble |
|
568
|
+
| 6 | Hart | hartley, ban, dit |
|