lib/fusuma/plugin/detectors/swipe_detector.rb in fusuma-2.0.0.pre vs lib/fusuma/plugin/detectors/swipe_detector.rb in fusuma-2.0.0.pre2
- old
+ new
@@ -1,129 +1,166 @@
# frozen_string_literal: true
-require_relative './detector.rb'
+require_relative './detector'
module Fusuma
module Plugin
module Detectors
class SwipeDetector < Detector
+ SOURCES = ['gesture'].freeze
BUFFER_TYPE = 'gesture'
GESTURE_RECORD_TYPE = 'swipe'
FINGERS = [3, 4].freeze
- BASE_THERESHOLD = 10
- BASE_INTERVAL = 0.5
+ BASE_THERESHOLD = 25
# @param buffers [Array<Buffers::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?
- move_x = buffer.avg_attrs(:move_x)
- move_y = buffer.avg_attrs(:move_y)
+ updating_time = 100 * (updating_events.last.time - updating_events.first.time)
+ oneshot_move_x = gesture_buffer.sum_attrs(:move_x) / updating_time
+ oneshot_move_y = gesture_buffer.sum_attrs(:move_y) / updating_time
- finger = buffer.finger
- direction = Direction.new(move_x: move_x.to_f, move_y: move_y.to_f).to_s
- quantity = Quantity.new(move_x: move_x.to_f, move_y: move_y.to_f).to_f
+ finger = gesture_buffer.finger
+ 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
- index = create_index(gesture: type,
- finger: finger,
- direction: direction)
+ delta = if status == 'end'
+ gesture_buffer.events[-2].record.delta
+ else
+ gesture_buffer.events.last.record.delta
+ end
- return unless enough?(index: index, quantity: quantity)
+ repeat_direction = Direction.new(move_x: delta.move_x, move_y: delta.move_y).to_s
+ repeat_quantity = Quantity.new(move_x: delta.move_x, move_y: delta.move_y).to_f
- create_event(record: Events::Records::IndexRecord.new(index: index))
+ 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(move_x: oneshot_move_x, move_y: oneshot_move_y).to_s
+ oneshot_quantity = Quantity.new(move_x: oneshot_move_x, move_y: oneshot_move_y).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, skippable: true),
+ 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_distance?(index: index, quantity: quantity)
+ def moved?(repeat_quantity)
+ repeat_quantity > 0.3
end
- def enough_distance?(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
RIGHT = 'right'
LEFT = 'left'
DOWN = 'down'
UP = 'up'
def initialize(move_x:, move_y:)
- @move_x = move_x
- @move_y = move_y
+ @move_x = move_x.to_f
+ @move_y = move_y.to_f
end
def to_s
calc
end
def calc
if @move_x.abs > @move_y.abs
- @move_x > 0 ? RIGHT : LEFT
- elsif @move_y > 0
+ @move_x.positive? ? RIGHT : LEFT
+ elsif @move_y.positive?
DOWN
else
UP
end
end
end
# quantity of gesture
class Quantity
def initialize(move_x:, move_y:)
- @x = move_x.abs
- @y = move_y.abs
+ @x = move_x.to_f.abs
+ @y = move_y.to_f.abs
end
def to_f
calc.to_f
end