Skip to content

Commit

Permalink
feat: support comparisons between various numeric item/state types
Browse files Browse the repository at this point in the history
Former-commit-id: 510d6db
  • Loading branch information
jimtng committed Feb 9, 2021
1 parent 255814e commit a85b189
Show file tree
Hide file tree
Showing 10 changed files with 517 additions and 14 deletions.
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
AllCops:
TargetRubyVersion: 2.5
NewCops: enable
SuggestExtensions: false
341 changes: 341 additions & 0 deletions features/comparisons.feature

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions lib/openhab/core/dsl/items/number_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def coerce(other)
when Quantity then coerce_from_quantity(other)
when Numeric then coerce_from_numeric(other)
else
logger.trace("#{self} cannot be coereced to #{other.class}")
logger.trace("#{self} cannot be coerced to #{other.class}")
nil
end
end
Expand All @@ -71,14 +71,19 @@ def coerce(other)
# @return [Integer] -1,0,1 or nil depending on value supplied,
# nil comparison to supplied object is not possible.
#
# rubocop: disable Metrics/AbcSize
def <=>(other)
logger.trace("Comparing #{self} to #{other}")
logger.trace("NumberItem #{self} <=> #{other} (#{other.class})")
case other
when NumberItem then number_item_compare(other)
when Numeric then @number_item.state.to_big_decimal.to_d <=> other.to_d
when String then @number_item.state <=> QuantityType.new(other) if dimension
when Numeric then @number_item.state.to_big_decimal.to_d <=> other.to_d
when String then @number_item.state <=> QuantityType.new(other) if dimension
else
other = other.state if other.respond_to? :state
@number_item.state <=> other
end
end
# rubocop: enable Metrics/AbcSize

#
# Convert NumberItem to a Quantity
Expand Down
2 changes: 2 additions & 0 deletions lib/openhab/core/dsl/items/string_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ def <=>(other)
@string_item.state <=> other.state
when String
@string_item.state.to_s <=> other
else
@string_item.state <=> other
end
end

Expand Down
25 changes: 20 additions & 5 deletions lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,27 @@ def brighten(amount = 1)
def <=>(other)
logger.trace("Comparing #{self} to #{other}")
case other
when DimmerItem, NumberItem
state <=> other.state
when DecimalType
state <=> other
when Java::OrgOpenhabCoreItems::GenericItem, NumberItem then state <=> other.state
when DecimalType then state <=> other
when Numeric then state.to_big_decimal.to_d <=> other.to_d
else compare_to(other)
end
end

#
# Coerce objects into a DimmerItem
#
# @param [Object] other object to coerce to a DimmerItem if possible
#
# @return [Object] Numeric when applicable
#
def coerce(other)
logger.trace("Coercing #{self} as a request from #{other.class}")
case other
when Numeric
[other, state.to_big_decimal.to_d]
else
to_i <=> other.to_i
[other, state]
end
end

Expand Down
1 change: 1 addition & 0 deletions lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
# Monkey patch ruby
require 'openhab/core/dsl/monkey_patch/ruby/range'
require 'openhab/core/dsl/monkey_patch/ruby/number'
require 'openhab/core/dsl/monkey_patch/ruby/string'
require 'bigdecimal/util'
43 changes: 43 additions & 0 deletions lib/openhab/core/dsl/monkey_patch/ruby/string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

require 'openhab/core/dsl/types/quantity'

module OpenHAB
module Core
module DSL
module MonkeyPatch
module Ruby
#
# Extend String class
#
module StringExtensions
include OpenHAB::Core

#
# Compares String to another object
#
# @param [Object] other object to compare to
#
# @return [Boolean] true if the two objects contain the same value, false otherwise
#
def ==(other)
case other
when OpenHAB::Core::DSL::Types::Quantity, QuantityType
other == self
else
super
end
end
end
end
end
end
end
end

#
# Prepend String class with comparison extensions
#
class String
prepend OpenHAB::Core::DSL::MonkeyPatch::Ruby::StringExtensions
end
46 changes: 41 additions & 5 deletions lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,51 @@ class Java::OrgOpenhabCoreLibraryTypes::DecimalType
# rubocop:enable Style/ClassAndModuleChildren

#
# Compare self to other using Java BigDecimal compare method
# Compare DecimalType to supplied object
#
# @param [Object] other object to compare to
#
# @return [Boolean] True if have the same BigDecimal representation, false otherwise
# @return [Integer] -1,0,1 or nil depending on value supplied, nil comparison to supplied object is not possible.
#
def ==(other)
return equals(other) unless other.is_a? Integer
def <=>(other)
logger.trace("#{self.class} #{self} <=> #{other} (#{other.class})")
case other
when Numeric
to_big_decimal.compare_to(other.to_d)
when Java::OrgOpenhabCoreTypes::UnDefType
1
else
other = other.state if other.respond_to? :state
compare_to(other)
end
end

#
# Coerce objects into a DecimalType
#
# @param [Object] other object to coerce to a DecimalType if possible
#
# @return [Object] Numeric when applicable
#
def coerce(other)
logger.trace("Coercing #{self} as a request from #{other.class}")
case other
when Numeric
[other.to_d, to_big_decimal]
else
[other, self]
end
end

to_big_decimal.compare_to(Java::JavaMath::BigDecimal.new(other)).zero?
#
# Compare self to other through the spaceship operator
#
# @param [Object] other object to compare to
#
# @return [Boolean] True if equals
#
def ==(other)
logger.trace("#{self.class} #{self} == #{other} (#{other.class})")
(self <=> other).zero?
end
end
58 changes: 58 additions & 0 deletions lib/openhab/core/dsl/monkey_patch/types/quantity_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true

require 'java'

#
# MonkeyPatching QuantityType
#
# rubocop:disable Style/ClassAndModuleChildren
class Java::OrgOpenhabCoreLibraryTypes::QuantityType
# rubocop:enable Style/ClassAndModuleChildren

#
# Compare QuantityType to supplied object
#
# @param [Object] other object to compare to
#
# @return [Integer] -1,0,1 or nil depending on value supplied, nil comparison to supplied object is not possible.
#
def <=>(other)
logger.trace("#{self.class} #{self} <=> #{other} (#{other.class})")
case other
when Java::OrgOpenhabCoreTypes::UnDefType then 1
when String then self <=> Quantity.new(other)
when OpenHAB::Core::DSL::Types::Quantity then self <=> other.quantity
else
other = other.state if other.respond_to? :state
compare_to(other)
end
end

#
# Coerce objects into a QuantityType
#
# @param [Object] other object to coerce to a QuantityType if possible
#
# @return [Object] Numeric when applicable
#
def coerce(other)
logger.trace("Coercing #{self} as a request from #{other.class}")
case other
when String
[Quantity.new(other), self]
else
[other, self]
end
end

#
# Compare self to other using the spaceship operator
#
# @param [Object] other object to compare to
#
# @return [Boolean] True if equals
#
def ==(other)
(self <=> other).zero?
end
end
1 change: 1 addition & 0 deletions lib/openhab/core/dsl/monkey_patch/types/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
require 'core/dsl/monkey_patch/types/on_off_type'
require 'core/dsl/monkey_patch/types/decimal_type'
require 'core/dsl/monkey_patch/types/percent_type'
require 'core/dsl/monkey_patch/types/quantity_type'

0 comments on commit a85b189

Please sign in to comment.