openhab-scripting 2.16.2 → 2.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab.rb +12 -16
  3. data/lib/openhab/core/entity_lookup.rb +173 -0
  4. data/lib/openhab/core/openhab_setup.rb +31 -0
  5. data/lib/openhab/core/osgi.rb +61 -0
  6. data/lib/openhab/dsl/actions.rb +105 -0
  7. data/lib/openhab/dsl/dsl.rb +49 -0
  8. data/lib/openhab/{core/dsl → dsl}/gems.rb +0 -1
  9. data/lib/openhab/dsl/group.rb +100 -0
  10. data/lib/openhab/dsl/items/datetime_item.rb +97 -0
  11. data/lib/openhab/dsl/items/items.rb +46 -0
  12. data/lib/openhab/dsl/items/number_item.rb +352 -0
  13. data/lib/openhab/dsl/items/rollershutter_item.rb +179 -0
  14. data/lib/openhab/dsl/items/string_item.rb +120 -0
  15. data/lib/openhab/dsl/monkey_patch/actions/actions.rb +4 -0
  16. data/lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb +32 -0
  17. data/lib/openhab/dsl/monkey_patch/events/events.rb +5 -0
  18. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +23 -0
  19. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +35 -0
  20. data/lib/openhab/dsl/monkey_patch/events/thing_status_info.rb +33 -0
  21. data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +61 -0
  22. data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +193 -0
  23. data/lib/openhab/dsl/monkey_patch/items/group_item.rb +37 -0
  24. data/lib/openhab/dsl/monkey_patch/items/items.rb +133 -0
  25. data/lib/openhab/dsl/monkey_patch/items/metadata.rb +281 -0
  26. data/lib/openhab/dsl/monkey_patch/items/persistence.rb +70 -0
  27. data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +95 -0
  28. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +39 -0
  29. data/lib/openhab/dsl/monkey_patch/ruby/range.rb +47 -0
  30. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +8 -0
  31. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +41 -0
  32. data/lib/openhab/dsl/monkey_patch/ruby/time.rb +32 -0
  33. data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +70 -0
  34. data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +51 -0
  35. data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +36 -0
  36. data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +32 -0
  37. data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +69 -0
  38. data/lib/openhab/dsl/monkey_patch/types/types.rb +9 -0
  39. data/lib/openhab/dsl/monkey_patch/types/up_down_type.rb +33 -0
  40. data/lib/openhab/dsl/persistence.rb +25 -0
  41. data/lib/openhab/dsl/rules/automation_rule.rb +342 -0
  42. data/lib/openhab/dsl/rules/guard.rb +134 -0
  43. data/lib/openhab/dsl/rules/property.rb +102 -0
  44. data/lib/openhab/dsl/rules/rule.rb +116 -0
  45. data/lib/openhab/dsl/rules/rule_config.rb +151 -0
  46. data/lib/openhab/dsl/rules/triggers/changed.rb +143 -0
  47. data/lib/openhab/dsl/rules/triggers/channel.rb +53 -0
  48. data/lib/openhab/dsl/rules/triggers/command.rb +104 -0
  49. data/lib/openhab/dsl/rules/triggers/cron.rb +177 -0
  50. data/lib/openhab/dsl/rules/triggers/trigger.rb +124 -0
  51. data/lib/openhab/dsl/rules/triggers/updated.rb +98 -0
  52. data/lib/openhab/dsl/states.rb +61 -0
  53. data/lib/openhab/dsl/things.rb +91 -0
  54. data/lib/openhab/dsl/time_of_day.rb +232 -0
  55. data/lib/openhab/dsl/timers.rb +77 -0
  56. data/lib/openhab/dsl/types/datetime.rb +326 -0
  57. data/lib/openhab/dsl/types/quantity.rb +290 -0
  58. data/lib/openhab/dsl/units.rb +39 -0
  59. data/lib/openhab/log/configuration.rb +21 -0
  60. data/lib/openhab/log/logger.rb +172 -0
  61. data/lib/openhab/version.rb +1 -1
  62. metadata +60 -58
  63. data/lib/openhab/configuration.rb +0 -16
  64. data/lib/openhab/core/cron.rb +0 -27
  65. data/lib/openhab/core/debug.rb +0 -34
  66. data/lib/openhab/core/dsl.rb +0 -51
  67. data/lib/openhab/core/dsl/actions.rb +0 -107
  68. data/lib/openhab/core/dsl/entities.rb +0 -147
  69. data/lib/openhab/core/dsl/group.rb +0 -102
  70. data/lib/openhab/core/dsl/items/items.rb +0 -51
  71. data/lib/openhab/core/dsl/items/number_item.rb +0 -323
  72. data/lib/openhab/core/dsl/items/string_item.rb +0 -122
  73. data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +0 -4
  74. data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +0 -22
  75. data/lib/openhab/core/dsl/monkey_patch/events.rb +0 -5
  76. data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +0 -13
  77. data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +0 -25
  78. data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +0 -26
  79. data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +0 -54
  80. data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +0 -182
  81. data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +0 -27
  82. data/lib/openhab/core/dsl/monkey_patch/items/items.rb +0 -132
  83. data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +0 -283
  84. data/lib/openhab/core/dsl/monkey_patch/items/persistence.rb +0 -72
  85. data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +0 -87
  86. data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +0 -41
  87. data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +0 -47
  88. data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +0 -7
  89. data/lib/openhab/core/dsl/monkey_patch/ruby/string.rb +0 -43
  90. data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +0 -60
  91. data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +0 -41
  92. data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +0 -25
  93. data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +0 -23
  94. data/lib/openhab/core/dsl/monkey_patch/types/quantity_type.rb +0 -58
  95. data/lib/openhab/core/dsl/monkey_patch/types/types.rb +0 -8
  96. data/lib/openhab/core/dsl/persistence.rb +0 -27
  97. data/lib/openhab/core/dsl/property.rb +0 -96
  98. data/lib/openhab/core/dsl/rule/automation_rule.rb +0 -345
  99. data/lib/openhab/core/dsl/rule/guard.rb +0 -136
  100. data/lib/openhab/core/dsl/rule/rule.rb +0 -117
  101. data/lib/openhab/core/dsl/rule/rule_config.rb +0 -153
  102. data/lib/openhab/core/dsl/rule/triggers/changed.rb +0 -145
  103. data/lib/openhab/core/dsl/rule/triggers/channel.rb +0 -55
  104. data/lib/openhab/core/dsl/rule/triggers/command.rb +0 -106
  105. data/lib/openhab/core/dsl/rule/triggers/cron.rb +0 -160
  106. data/lib/openhab/core/dsl/rule/triggers/trigger.rb +0 -126
  107. data/lib/openhab/core/dsl/rule/triggers/updated.rb +0 -100
  108. data/lib/openhab/core/dsl/states.rb +0 -63
  109. data/lib/openhab/core/dsl/things.rb +0 -93
  110. data/lib/openhab/core/dsl/time_of_day.rb +0 -231
  111. data/lib/openhab/core/dsl/timers.rb +0 -79
  112. data/lib/openhab/core/dsl/types/quantity.rb +0 -292
  113. data/lib/openhab/core/dsl/units.rb +0 -41
  114. data/lib/openhab/core/log.rb +0 -170
  115. data/lib/openhab/core/patch_load_path.rb +0 -7
  116. data/lib/openhab/core/startup_delay.rb +0 -23
  117. data/lib/openhab/osgi.rb +0 -59
@@ -1,4 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'core/log'
4
3
  require 'bundler/inline'
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'delegate'
4
+ require 'forwardable'
5
+ require 'openhab/core/entity_lookup'
6
+
7
+ module OpenHAB
8
+ module DSL
9
+ #
10
+ # Provides access to OpenHAB Groups
11
+ #
12
+ module Groups
13
+ #
14
+ # Indicator struct interpreted by rules to trigger based on items contained in a group
15
+ #
16
+ GroupItems = Struct.new(:group, keyword_init: true)
17
+
18
+ #
19
+ # Provide access to groups as a set
20
+ #
21
+ class Groups < SimpleDelegator
22
+ #
23
+ # Get a OpenHAB Group by name
24
+ # @param [String] name of the group to retrieve
25
+ #
26
+ # @return [Set] of OpenHAB Groups
27
+ #
28
+ def[](name)
29
+ group = OpenHAB::Core::EntityLookup.lookup_item(name)
30
+ group.is_a?(Group) ? group : nil
31
+ end
32
+ end
33
+
34
+ #
35
+ # Retreive all OpenHAB groups
36
+ #
37
+ # @return [Set] of OpenHAB Groups
38
+ #
39
+ def groups
40
+ # rubocop: disable Style/GlobalVars
41
+ Groups.new(OpenHAB::Core::EntityLookup.decorate_items($ir.items.select { |item| item.is_a? GroupItem }))
42
+ # rubocop: enable Style/GlobalVars
43
+ end
44
+
45
+ # Group class that provides access to OpenHAB group object and delegates other methods to
46
+ # a set of group items
47
+ class Group < SimpleDelegator
48
+ extend Forwardable
49
+
50
+ java_import org.openhab.core.items.GroupItem
51
+
52
+ # @return [org.openhab.core.items.GroupItem] OpenHAB Java Group Item
53
+ attr_accessor :group
54
+
55
+ # @!macro [attach] def_delegators
56
+ # @!method $2
57
+ # Forwards to org.openhab.core.items.GroupItem
58
+ # @see org::openhab::core::items::GroupItem
59
+ def_delegator :@group, :name
60
+ def_delegator :@group, :label
61
+
62
+ #
63
+ # Gets members of this group that are themselves a group
64
+ #
65
+ # @return [Set] Set of members that are of type group
66
+ #
67
+ def groups
68
+ group.members.grep(org.openhab.core.items.GroupItem)
69
+ end
70
+
71
+ #
72
+ # Wraps the group in a struct, this method is intended to be called
73
+ # as an indicator to the rule method that the user wishes to trigger
74
+ # based on changes to group items
75
+ #
76
+ # @return [GroupItems] Indicator struct used by rules engine to trigger based on item changes
77
+ #
78
+ def items
79
+ GroupItems.new(group: group)
80
+ end
81
+
82
+ #
83
+ # @return [String] List of groups seperated by commas
84
+ #
85
+ def to_s
86
+ "[#{map(&:to_s).join(',')}]"
87
+ end
88
+
89
+ #
90
+ # Get an ID for the group, using the label if set, otherwise group name
91
+ #
92
+ # @return [String] label if set otherwise name
93
+ #
94
+ def id
95
+ label || name
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'java'
5
+ require 'time'
6
+ require 'openhab/dsl/types/datetime'
7
+
8
+ module OpenHAB
9
+ module DSL
10
+ module Items
11
+ #
12
+ # Delegation to OpenHAB DateTime Item
13
+ #
14
+ # @author Anders Alfredsson
15
+ #
16
+ class DateTimeItem
17
+ extend Forwardable
18
+ include Comparable
19
+
20
+ def_delegator :@datetime_item, :to_s
21
+
22
+ #
23
+ # Create a new DateTimeItem
24
+ #
25
+ # @param [Java::org::openhab::core::libarary::items::DateTimeItem] datetime_item Openhab DateTimeItem to
26
+ # delegate to
27
+ #
28
+ def initialize(datetime_item)
29
+ @datetime_item = datetime_item
30
+ end
31
+
32
+ #
33
+ # Return an instance of DateTime that wraps the DateTimeItem's state
34
+ #
35
+ # @return [OpenHAB::DSL::Types::DateTime] Wrapper for the Item's state, or nil if it has no state
36
+ #
37
+ def to_dt
38
+ OpenHAB::DSL::Types::DateTime.new(@datetime_item.state) if state?
39
+ end
40
+
41
+ #
42
+ # Compare the Item's state to another Item or object that can be compared
43
+ #
44
+ # @param [Object] other Other objet to compare against
45
+ #
46
+ # @return [Integer] -1, 0 or 1 depending on the result of the comparison
47
+ #
48
+ def <=>(other)
49
+ return unless state?
50
+
51
+ logger.trace("Comparing self (#{self.class}) to #{other} (#{other.class})")
52
+ other = other.to_dt if other.is_a? DateTimeItem
53
+ to_dt <=> other
54
+ end
55
+
56
+ #
57
+ # Get the time zone of the Item
58
+ #
59
+ # @return [String] The timezone in `[+-]hh:mm(:ss)` format or nil if the Item has no state
60
+ #
61
+ def zone
62
+ to_dt.zone if state?
63
+ end
64
+
65
+ #
66
+ # Check if missing method can be delegated to other contained objects
67
+ #
68
+ # @param [String, Symbol] meth The method name to check for
69
+ #
70
+ # @return [Boolean] true if DateTimeItem or DateTime responds to the method, false otherwise
71
+ #
72
+ def respond_to_missing?(meth, *)
73
+ @datetime_item.respond_to?(meth) || to_dt.respond_to?(meth)
74
+ end
75
+
76
+ #
77
+ # Forward missing methods to the OpenHAB Item, or a DateTime object wrapping its state
78
+ #
79
+ # @param [String] meth method name
80
+ # @param [Array] args arguments for method
81
+ # @param [Proc] block <description>
82
+ #
83
+ # @return [Object] Value from delegated method in OpenHAB NumberItem
84
+ #
85
+ def method_missing(meth, *args, &block)
86
+ if @datetime_item.respond_to?(meth)
87
+ @datetime_item.__send__(meth, *args, &block)
88
+ elsif state?
89
+ to_dt.send(meth, *args, &block)
90
+ else
91
+ raise NoMethodError, "undefined method `#{meth}' for #{self.class}"
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+ require 'openhab/core/entity_lookup'
5
+
6
+ module OpenHAB
7
+ module DSL
8
+ #
9
+ # Manages OpenHAB items
10
+ #
11
+ module Items
12
+ #
13
+ # Delegates to underlying set of all OpenHAB Items, provides convenience methods
14
+ #
15
+ class Items < SimpleDelegator
16
+ # Fetches the named item from the the ItemRegistry
17
+ # @param [String] name
18
+ # @return Item from registry, nil if item missing or requested item is a Group Type
19
+ def[](name)
20
+ OpenHAB::Core::EntityLookup.lookup_item(name)
21
+ rescue Java::OrgOpenhabCoreItems::ItemNotFoundException
22
+ nil
23
+ end
24
+
25
+ # Returns true if the given item name exists
26
+ # @param name [String] Item name to check
27
+ # @return [Boolean] true if the item exists, false otherwise
28
+ def include?(name)
29
+ # rubocop: disable Style/GlobalVars
30
+ !$ir.getItems(name).empty?
31
+ # rubocop: enable Style/GlobalVars
32
+ end
33
+ alias key? include?
34
+ end
35
+
36
+ java_import org.openhab.core.items.GroupItem
37
+ # Fetches all non-group items from the item registry
38
+ # @return [OpenHAB::DSL::Items::Items]
39
+ def items
40
+ # rubocop: disable Style/GlobalVars
41
+ Items.new(OpenHAB::Core::EntityLookup.decorate_items($ir.items.reject { |item| item.is_a? GroupItem }))
42
+ # rubocop: enable Style/GlobalVars
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,352 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bigdecimal'
4
+ require 'forwardable'
5
+ require 'java'
6
+ require 'openhab/dsl/types/quantity'
7
+
8
+ module OpenHAB
9
+ module DSL
10
+ module Items
11
+ #
12
+ # Delegation to OpenHAB Number Item
13
+ #
14
+ # rubocop: disable Metrics/ClassLength
15
+ # Disabled because this class has a single responsibility, there does not appear a logical
16
+ # way of breaking it up into multiple classes
17
+ class NumberItem < Numeric
18
+ extend Forwardable
19
+
20
+ def_delegator :@number_item, :to_s
21
+
22
+ java_import org.openhab.core.library.types.DecimalType
23
+ java_import org.openhab.core.library.types.QuantityType
24
+ java_import 'tec.uom.se.format.SimpleUnitFormat'
25
+ java_import 'tec.uom.se.AbstractUnit'
26
+
27
+ #
28
+ # Create a new NumberItem
29
+ #
30
+ # @param [Java::Org::openhab::core::library::items::NumberItem] number_item OpenHAB number item to delegate to
31
+ #
32
+ def initialize(number_item)
33
+ @number_item = number_item
34
+ super()
35
+ end
36
+
37
+ #
38
+ # Check if NumberItem is truthy? as per defined by library
39
+ #
40
+ # @return [Boolean] True if item is not in state UNDEF or NULL and value is not zero.
41
+ #
42
+ def truthy?
43
+ @number_item.state? && @number_item.state != DecimalType::ZERO
44
+ end
45
+
46
+ #
47
+ # Coerce objects into a NumberItem
48
+ #
49
+ # @param [Object] other object to coerce to a NumberItem if possible
50
+ #
51
+ # @return [Object] NumberItem, QuantityTypes, BigDecimal or nil depending on NumberItem configuration
52
+ # and/or supplied object
53
+ #
54
+ def coerce(other)
55
+ logger.trace("Coercing #{self} as a request from #{other.class}")
56
+ case other
57
+ when Quantity then coerce_from_quantity(other)
58
+ when Numeric then coerce_from_numeric(other)
59
+ else
60
+ logger.trace("#{self} cannot be coerced to #{other.class}")
61
+ nil
62
+ end
63
+ end
64
+
65
+ #
66
+ # Compare NumberItem to supplied object
67
+ #
68
+ # @param [Object] other object to compare to
69
+ #
70
+ # @return [Integer] -1,0,1 or nil depending on value supplied,
71
+ # nil comparison to supplied object is not possible.
72
+ #
73
+ def <=>(other)
74
+ logger.trace("NumberItem #{self} <=> #{other} (#{other.class})")
75
+ case other
76
+ when NumberItem then number_item_compare(other)
77
+ when Numeric then numeric_compare(other)
78
+ when String then string_compare(other)
79
+ else state_compare(other)
80
+ end
81
+ end
82
+
83
+ #
84
+ # Convert NumberItem to a Quantity
85
+ #
86
+ # @param [Object] other String or Unit representing an OpenHAB Unit
87
+ #
88
+ # @return [OpenHAB::DSL::Types::Quantity] NumberItem converted to supplied Unit
89
+ #
90
+ def |(other)
91
+ other = SimpleUnitFormat.instance.unitFor(other) if other.is_a? String
92
+
93
+ if dimension
94
+ to_qt | other
95
+ else
96
+ Quantity.new(QuantityType.new(to_d.to_java, other))
97
+ end
98
+ end
99
+
100
+ #
101
+ # Convert NumberItem to a Quantity
102
+ #
103
+ # @return [OpenHAB::DSL::Types::Quantity] NumberItem converted to a QuantityUnit
104
+ #
105
+ def to_qt
106
+ if dimension
107
+ Quantity.new(@number_item.get_state_as(QuantityType))
108
+ else
109
+ Quantity.new(QuantityType.new(to_d.to_java, AbstractUnit::ONE))
110
+ end
111
+ end
112
+
113
+ #
114
+ # Converts the NumberItem to an Integer
115
+ #
116
+ # @return [Integer] NumberItem as an integer
117
+ #
118
+ def to_i
119
+ to_d&.to_i
120
+ end
121
+
122
+ #
123
+ # Converts the NumberItem to a float
124
+ #
125
+ # @return [Float] NumberItem as a float
126
+ #
127
+ def to_f
128
+ to_d&.to_f
129
+ end
130
+
131
+ #
132
+ # Converts the NumberItem to a BigDecimal
133
+ #
134
+ # @return [BigDecimal] NumberItem as a BigDecimal
135
+ #
136
+ def to_d
137
+ @number_item.state.to_big_decimal.to_d if @number_item.state.respond_to? :to_big_decimal
138
+ end
139
+
140
+ #
141
+ # Get the Dimension attached to the NumberItem
142
+ #
143
+ # @return [Java::org::openhab::core::library::types::QuantityType] dimension
144
+ #
145
+ def dimension
146
+ @number_item.dimension
147
+ end
148
+
149
+ #
150
+ # Forward missing methods to Openhab Number Item if they are defined
151
+ #
152
+ # @param [String] meth method name
153
+ # @param [Array] args arguments for method
154
+ # @param [Proc] block <description>
155
+ #
156
+ # @return [Object] Value from delegated method in OpenHAB NumberItem
157
+ #
158
+ def method_missing(meth, *args, &block)
159
+ logger.trace("Method missing, performing dynamic lookup for: #{meth}")
160
+ if @number_item.respond_to?(meth)
161
+ @number_item.__send__(meth, *args, &block)
162
+ elsif ::Kernel.method_defined?(meth) || ::Kernel.private_method_defined?(meth)
163
+ ::Kernel.instance_method(meth).bind_call(self, *args, &block)
164
+ else
165
+ super(meth, *args, &block)
166
+ end
167
+ end
168
+
169
+ #
170
+ # Checks if this method responds to the missing method
171
+ #
172
+ # @param [String] method_name Name of the method to check
173
+ # @param [Boolean] _include_private boolean if private methods should be checked
174
+ #
175
+ # @return [Boolean] true if this object will respond to the supplied method, false otherwise
176
+ #
177
+ def respond_to_missing?(method_name, _include_private = false)
178
+ @number_item.respond_to?(method_name) ||
179
+ ::Kernel.method_defined?(method_name) ||
180
+ ::Kernel.private_method_defined?(method_name)
181
+ end
182
+
183
+ %w[+ - * /].each do |operation|
184
+ define_method(operation) do |other|
185
+ logger.trace("Execution math operation '#{operation}' on #{inspect} with #{other.inspect}")
186
+ left_operand, right_operand = operands_for_operation(other)
187
+ left_operand.public_send(operation, right_operand)
188
+ end
189
+ end
190
+
191
+ private
192
+
193
+ #
194
+ # Compare if other responds to state
195
+ #
196
+ # @param [Object] other object to compare to
197
+ #
198
+ # @return [Integer] -1,0,1 depending on less than, equal to or greater than other
199
+ #
200
+ def state_compare(other)
201
+ other = other.state if other.respond_to? :state
202
+ @number_item.state <=> other
203
+ end
204
+
205
+ #
206
+ # Compare if other is a String
207
+ #
208
+ # @param [String] other object to compare to
209
+ #
210
+ # @return [Integer] -1,0,1,nil depending on less than, equal to or greater than other
211
+ # nil if this number item does not have a dimension
212
+ #
213
+ def string_compare(other)
214
+ @number_item.state <=> QuantityType.new(other) if dimension
215
+ end
216
+
217
+ #
218
+ # Compare if other is a Numeric
219
+ #
220
+ # @param [String] other to compare to
221
+ #
222
+ # @return [Integer] -1,0,1 depending on less than, equal to or greater than other
223
+ #
224
+ def numeric_compare(other)
225
+ @number_item.state.to_big_decimal.to_d <=> other.to_d
226
+ end
227
+
228
+ #
229
+ # Get the operands for any operation
230
+ #
231
+ # @param [Object] other object to convert to a compatible operand
232
+ #
233
+ # @return [Array[Object,Object]] of operands where the first value is the left operand
234
+ # and the second value is the right operand
235
+ #
236
+ def operands_for_operation(other)
237
+ case other
238
+ when NumberItem then number_item_operands(other)
239
+ when Numeric then [to_d, other.to_d]
240
+ when String then string_operands(other)
241
+ else
242
+ return other.coerce(to_d) if other.respond_to? :coerce
243
+
244
+ raise ArgumentError, "#{other.class} can't be coerced into a NumberItem"
245
+ end
246
+ end
247
+
248
+ #
249
+ # Get operands for an operation when the right operand is provided as a string
250
+ #
251
+ # @param [String] other right operand
252
+ #
253
+ # @return [Array[QuantityType,QuantiyType]] of operands where the first value is the left operand
254
+ # and the second value is the right operand
255
+ #
256
+ def string_operands(other)
257
+ return [to_qt, Quantity.new(other)] if dimension
258
+
259
+ raise ArgumentError, 'Strings are only valid operands if NumberItem is dimensions=ed.'
260
+ end
261
+
262
+ #
263
+ # Get operands for an operation when the right operand is provided is another number item
264
+ #
265
+ # @param [NumberItem] other right operand
266
+ #
267
+ # @return [Array<QuantityType,QuantityType>,Array<BigDecimal,BigDecimal>] of operands depending on
268
+ # if the left or right operand has a dimensions
269
+ #
270
+ def number_item_operands(other)
271
+ if dimension || other.dimension
272
+ dimensioned_operands(other)
273
+ else
274
+ logger.trace("Both objects lack dimension, self='#{self}' other='#{other}'")
275
+ # If nothing has a dimension, just use BigDecimals
276
+ [to_d, other.to_d]
277
+ end
278
+ end
279
+
280
+ #
281
+ # Get operands for an operation when the left or right operand has a dimension
282
+ #
283
+ # @param [NumberItem] other right operand
284
+ #
285
+ # @return [Array<QuantityType,QuantityType>] of operands
286
+ #
287
+ def dimensioned_operands(other)
288
+ logger.trace("Dimensions self='#{dimension}' other='#{other.dimension}'")
289
+ if dimension
290
+ if other.dimension
291
+ # If both numbers have dimensions, do the math on the quantity types.
292
+ [to_qt, other.to_qt]
293
+ else
294
+ # If this number has dimension and the other does not,
295
+ # do math with this quantity type and the other as a big decimal
296
+ [to_qt, other]
297
+ end
298
+ else
299
+ # If this number has no dimension and the other does, convert this into a dimensionless quantity
300
+ [to_qt, other]
301
+ end
302
+ end
303
+
304
+ #
305
+ # Compare two number items, taking into account any dimensions
306
+ #
307
+ # @param [NumberItem] other number item
308
+ #
309
+ # @return [-1,0,1] depending on if other object is less than, equal to or greater than self
310
+ #
311
+ def number_item_compare(other)
312
+ if other.dimension
313
+ logger.trace('Other is dimensioned, converting self and other to QuantityTypes to compare')
314
+ to_qt <=> other.to_qt
315
+ else
316
+ @number_item.state <=> other.state
317
+ end
318
+ end
319
+
320
+ #
321
+ # Coerce from a numberic object depnding on dimension and state
322
+ #
323
+ # @param [Numeric] other numeric object to convert
324
+ #
325
+ # @return [Array<QuantityType,QuantityType>,Array<BigDecimal,BigDecimal>,nil] depending on
326
+ # if this object has a dimension or state
327
+ #
328
+ def coerce_from_numeric(other)
329
+ if dimension
330
+ [Quantity.new(other), to_qt]
331
+ elsif @number_item.state?
332
+ [other.to_d, @number_item.state.to_big_decimal.to_d]
333
+ end
334
+ end
335
+
336
+ #
337
+ # Coerce when other is a quantity
338
+ #
339
+ # @param [QuantityType] other
340
+ #
341
+ # @return [Array<QuanityType,QuantityType] other and self as a quantity type
342
+ #
343
+ def coerce_from_quantity(other)
344
+ as_qt = to_qt
345
+ logger.trace("Converted #{self} to a Quantity #{as_qt}")
346
+ [other, as_qt]
347
+ end
348
+ end
349
+ end
350
+ end
351
+ end
352
+ # rubocop: enable Metrics/ClassLength