lib/fusuma/plugin/detectors/rotate_detector.rb in fusuma-2.0.0.pre vs lib/fusuma/plugin/detectors/rotate_detector.rb in fusuma-2.0.0.pre2
- old
+ new
@@ -1,111 +1,152 @@
# frozen_string_literal: true
-require_relative './detector.rb'
+require_relative './detector'
module Fusuma
module Plugin
module Detectors
class RotateDetector < Detector
+ SOURCES = ['gesture'].freeze
BUFFER_TYPE = 'gesture'
GESTURE_RECORD_TYPE = 'pinch'
FINGERS = [2, 3, 4].freeze
BASE_THERESHOLD = 0.5
- BASE_INTERVAL = 0.1
# @param buffers [Array<Buffer>]
- # @return [Event] if event is detected
+ # @return [Events::Event] if event is detected
# @return [NilClass] if event is NOT detected
def detect(buffers)
- buffer = buffers.find { |b| b.type == BUFFER_TYPE }
- .select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
+ gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
+ .select_from_last_begin
+ .select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
- return if buffer.empty?
+ updating_events = gesture_buffer.updating_events
+ return if updating_events.empty?
- angle = buffer.avg_attrs(:rotate)
+ updating_time = 100 * (updating_events.last.time - updating_events.first.time)
+ oneshot_angle = gesture_buffer.sum_attrs(:rotate) / updating_time
- finger = buffer.finger
- direction = Direction.new(angle: angle).to_s
- quantity = Quantity.new(angle: angle).to_f
+ return if updating_events.empty?
- index = create_index(gesture: type,
- finger: finger,
- direction: direction)
+ finger = gesture_buffer.finger
- return unless enough?(index: index, quantity: quantity)
+ status = case gesture_buffer.events.last.record.status
+ when 'end'
+ 'end'
+ when 'update'
+ if updating_events.length == 1
+ 'begin'
+ else
+ 'update'
+ end
+ else
+ gesture_buffer.events.last.record.status
+ end
- create_event(record: Events::Records::IndexRecord.new(index: index))
+ delta = if status == 'end'
+ gesture_buffer.events[-2].record.delta
+ else
+ gesture_buffer.events.last.record.delta
+ end
+
+ repeat_direction = Direction.new(angle: delta.rotate).to_s
+ repeat_quantity = Quantity.new(angle: delta.rotate).to_f
+
+ repeat_index = create_repeat_index(gesture: type, finger: finger,
+ direction: repeat_direction,
+ status: status)
+
+ if status == 'update'
+ return unless moved?(repeat_quantity)
+
+ oneshot_direction = Direction.new(angle: oneshot_angle).to_s
+ oneshot_quantity = Quantity.new(angle: oneshot_angle).to_f
+ oneshot_index = create_oneshot_index(gesture: type, finger: finger,
+ direction: oneshot_direction)
+ if enough_oneshot_threshold?(index: oneshot_index, quantity: oneshot_quantity)
+ return [
+ create_event(record: Events::Records::IndexRecord.new(
+ index: oneshot_index, trigger: :oneshot, args: delta.to_h
+ )),
+ create_event(record: Events::Records::IndexRecord.new(
+ index: repeat_index, trigger: :repeat, args: delta.to_h
+ ))
+ ]
+ end
+ end
+ create_event(record: Events::Records::IndexRecord.new(
+ index: repeat_index, trigger: :repeat, args: delta.to_h
+ ))
end
# @param [String] gesture
# @param [Integer] finger
# @param [String] direction
+ # @param [String] status
# @return [Config::Index]
- def create_index(gesture:, finger:, direction:)
+ def create_repeat_index(gesture:, finger:, direction:, status:)
Config::Index.new(
[
Config::Index::Key.new(gesture),
+ Config::Index::Key.new(finger.to_i),
+ Config::Index::Key.new(direction),
+ Config::Index::Key.new(status)
+ ]
+ )
+ end
+
+ # @param [String] gesture
+ # @param [Integer] finger
+ # @param [String] direction
+ # @return [Config::Index]
+ def create_oneshot_index(gesture:, finger:, direction:)
+ Config::Index.new(
+ [
+ Config::Index::Key.new(gesture),
Config::Index::Key.new(finger.to_i, skippable: true),
Config::Index::Key.new(direction)
]
)
end
private
- def enough?(index:, quantity:)
- enough_interval?(index: index) && enough_angle?(index: index, quantity: quantity)
+ def moved?(repeat_quantity)
+ repeat_quantity > 0.2
end
- def enough_angle?(index:, quantity:)
+ def enough_oneshot_threshold?(index:, quantity:)
quantity > threshold(index: index)
end
- def enough_interval?(index:)
- return true if first_time?
- return true if (Time.now - last_time) > interval_time(index: index)
-
- false
- end
-
def threshold(index:)
@threshold ||= {}
@threshold[index.cache_key] ||= begin
- keys_specific = Config::Index.new [*index.keys, 'threshold']
- keys_global = Config::Index.new ['threshold', type]
- config_value = Config.search(keys_specific) ||
- Config.search(keys_global) || 1
- BASE_THERESHOLD * config_value
- end
+ keys_specific = Config::Index.new [*index.keys, 'threshold']
+ keys_global = Config::Index.new ['threshold', type]
+ config_value = Config.search(keys_specific) ||
+ Config.search(keys_global) || 1
+ BASE_THERESHOLD * config_value
+ end
end
- def interval_time(index:)
- @interval_time ||= {}
- @interval_time[index.cache_key] ||= begin
- keys_specific = Config::Index.new [*index.keys, 'interval']
- keys_global = Config::Index.new ['interval', type]
- config_value = Config.search(keys_specific) ||
- Config.search(keys_global) || 1
- BASE_INTERVAL * config_value
- end
- end
-
# direction of gesture
class Direction
CLOCKWISE = 'clockwise'
COUNTERCLOCKWISE = 'counterclockwise'
def initialize(angle:)
- @angle = angle
+ @angle = angle.to_f
end
def to_s
calc
end
def calc
- if @angle > 0
+ if @angle.positive?
CLOCKWISE
else
COUNTERCLOCKWISE
end
end