openhab-scripting 2.16.2 → 2.16.3
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/openhab.rb +12 -16
- data/lib/openhab/core/entity_lookup.rb +162 -0
- data/lib/openhab/core/openhab_setup.rb +31 -0
- data/lib/openhab/core/osgi.rb +61 -0
- data/lib/openhab/dsl/actions.rb +105 -0
- data/lib/openhab/dsl/dsl.rb +47 -0
- data/lib/openhab/{core/dsl → dsl}/gems.rb +0 -1
- data/lib/openhab/dsl/group.rb +100 -0
- data/lib/openhab/dsl/items/items.rb +46 -0
- data/lib/openhab/dsl/items/number_item.rb +352 -0
- data/lib/openhab/dsl/items/string_item.rb +120 -0
- data/lib/openhab/dsl/monkey_patch/actions/actions.rb +4 -0
- data/lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb +32 -0
- data/lib/openhab/dsl/monkey_patch/events/events.rb +5 -0
- data/lib/openhab/dsl/monkey_patch/events/item_command.rb +23 -0
- data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +35 -0
- data/lib/openhab/dsl/monkey_patch/events/thing_status_info.rb +33 -0
- data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +61 -0
- data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +193 -0
- data/lib/openhab/dsl/monkey_patch/items/group_item.rb +37 -0
- data/lib/openhab/dsl/monkey_patch/items/items.rb +133 -0
- data/lib/openhab/dsl/monkey_patch/items/metadata.rb +281 -0
- data/lib/openhab/dsl/monkey_patch/items/persistence.rb +70 -0
- data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +95 -0
- data/lib/openhab/dsl/monkey_patch/ruby/number.rb +39 -0
- data/lib/openhab/dsl/monkey_patch/ruby/range.rb +47 -0
- data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +7 -0
- data/lib/openhab/dsl/monkey_patch/ruby/string.rb +41 -0
- data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +70 -0
- data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +51 -0
- data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +36 -0
- data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +32 -0
- data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +69 -0
- data/lib/openhab/dsl/monkey_patch/types/types.rb +8 -0
- data/lib/openhab/dsl/persistence.rb +25 -0
- data/lib/openhab/dsl/rules/automation_rule.rb +342 -0
- data/lib/openhab/dsl/rules/guard.rb +134 -0
- data/lib/openhab/dsl/rules/property.rb +102 -0
- data/lib/openhab/dsl/rules/rule.rb +116 -0
- data/lib/openhab/dsl/rules/rule_config.rb +151 -0
- data/lib/openhab/dsl/rules/triggers/changed.rb +143 -0
- data/lib/openhab/dsl/rules/triggers/channel.rb +53 -0
- data/lib/openhab/dsl/rules/triggers/command.rb +104 -0
- data/lib/openhab/dsl/rules/triggers/cron.rb +177 -0
- data/lib/openhab/dsl/rules/triggers/trigger.rb +124 -0
- data/lib/openhab/dsl/rules/triggers/updated.rb +98 -0
- data/lib/openhab/dsl/states.rb +61 -0
- data/lib/openhab/dsl/things.rb +91 -0
- data/lib/openhab/dsl/time_of_day.rb +228 -0
- data/lib/openhab/dsl/timers.rb +77 -0
- data/lib/openhab/dsl/types/quantity.rb +290 -0
- data/lib/openhab/dsl/units.rb +39 -0
- data/lib/openhab/log/configuration.rb +21 -0
- data/lib/openhab/log/logger.rb +172 -0
- data/lib/openhab/version.rb +1 -1
- metadata +55 -58
- data/lib/openhab/configuration.rb +0 -16
- data/lib/openhab/core/cron.rb +0 -27
- data/lib/openhab/core/debug.rb +0 -34
- data/lib/openhab/core/dsl.rb +0 -51
- data/lib/openhab/core/dsl/actions.rb +0 -107
- data/lib/openhab/core/dsl/entities.rb +0 -147
- data/lib/openhab/core/dsl/group.rb +0 -102
- data/lib/openhab/core/dsl/items/items.rb +0 -51
- data/lib/openhab/core/dsl/items/number_item.rb +0 -323
- data/lib/openhab/core/dsl/items/string_item.rb +0 -122
- data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +0 -4
- data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +0 -22
- data/lib/openhab/core/dsl/monkey_patch/events.rb +0 -5
- data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +0 -13
- data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +0 -25
- data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +0 -26
- data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +0 -54
- data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +0 -182
- data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +0 -27
- data/lib/openhab/core/dsl/monkey_patch/items/items.rb +0 -132
- data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +0 -283
- data/lib/openhab/core/dsl/monkey_patch/items/persistence.rb +0 -72
- data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +0 -87
- data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +0 -41
- data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +0 -47
- data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +0 -7
- data/lib/openhab/core/dsl/monkey_patch/ruby/string.rb +0 -43
- data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +0 -60
- data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +0 -41
- data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +0 -25
- data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +0 -23
- data/lib/openhab/core/dsl/monkey_patch/types/quantity_type.rb +0 -58
- data/lib/openhab/core/dsl/monkey_patch/types/types.rb +0 -8
- data/lib/openhab/core/dsl/persistence.rb +0 -27
- data/lib/openhab/core/dsl/property.rb +0 -96
- data/lib/openhab/core/dsl/rule/automation_rule.rb +0 -345
- data/lib/openhab/core/dsl/rule/guard.rb +0 -136
- data/lib/openhab/core/dsl/rule/rule.rb +0 -117
- data/lib/openhab/core/dsl/rule/rule_config.rb +0 -153
- data/lib/openhab/core/dsl/rule/triggers/changed.rb +0 -145
- data/lib/openhab/core/dsl/rule/triggers/channel.rb +0 -55
- data/lib/openhab/core/dsl/rule/triggers/command.rb +0 -106
- data/lib/openhab/core/dsl/rule/triggers/cron.rb +0 -160
- data/lib/openhab/core/dsl/rule/triggers/trigger.rb +0 -126
- data/lib/openhab/core/dsl/rule/triggers/updated.rb +0 -100
- data/lib/openhab/core/dsl/states.rb +0 -63
- data/lib/openhab/core/dsl/things.rb +0 -93
- data/lib/openhab/core/dsl/time_of_day.rb +0 -231
- data/lib/openhab/core/dsl/timers.rb +0 -79
- data/lib/openhab/core/dsl/types/quantity.rb +0 -292
- data/lib/openhab/core/dsl/units.rb +0 -41
- data/lib/openhab/core/log.rb +0 -170
- data/lib/openhab/core/patch_load_path.rb +0 -7
- data/lib/openhab/core/startup_delay.rb +0 -23
- data/lib/openhab/osgi.rb +0 -59
|
@@ -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,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
|