# frozen_string_literal: true require_relative './detector.rb' module Fusuma module Plugin module Detectors class RotateDetector < Detector BUFFER_TYPE = 'gesture' GESTURE_RECORD_TYPE = 'pinch' FINGERS = [2, 3, 4].freeze BASE_THERESHOLD = 0.5 BASE_INTERVAL = 0.1 # @param buffers [Array] # @return [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 } return if buffer.empty? angle = buffer.avg_attrs(:rotate) finger = buffer.finger direction = Direction.new(angle: angle).to_s quantity = Quantity.new(angle: angle).to_f index = create_index(gesture: type, finger: finger, direction: direction) return unless enough?(index: index, quantity: quantity) create_event(record: Events::Records::IndexRecord.new(index: index)) end # @param [String] gesture # @param [Integer] finger # @param [String] direction # @return [Config::Index] def create_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) end def enough_angle?(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 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 end def to_s calc end def calc if @angle > 0 CLOCKWISE else COUNTERCLOCKWISE end end end # quantity of gesture class Quantity def initialize(angle:) @angle = angle.abs end def to_f @angle.to_f end end end end end end