fusuma 3.9.0 → 3.10.0
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/README.md +27 -1
 - data/lib/fusuma/config/index.rb +12 -7
 - data/lib/fusuma/config/searcher.rb +17 -6
 - data/lib/fusuma/config/yaml_duplication_checker.rb +6 -0
 - data/lib/fusuma/config.rb +17 -3
 - data/lib/fusuma/custom_process.rb +3 -0
 - data/lib/fusuma/device.rb +15 -0
 - data/lib/fusuma/environment.rb +4 -0
 - data/lib/fusuma/hash_support.rb +6 -1
 - data/lib/fusuma/libinput_command.rb +11 -3
 - data/lib/fusuma/multi_logger.rb +15 -4
 - data/lib/fusuma/plugin/base.rb +11 -1
 - data/lib/fusuma/plugin/buffers/buffer.rb +6 -0
 - data/lib/fusuma/plugin/buffers/gesture_buffer.rb +15 -9
 - data/lib/fusuma/plugin/buffers/timer_buffer.rb +2 -1
 - data/lib/fusuma/plugin/detectors/detector.rb +15 -15
 - data/lib/fusuma/plugin/detectors/hold_detector.rb +10 -2
 - data/lib/fusuma/plugin/detectors/pinch_detector.rb +13 -1
 - data/lib/fusuma/plugin/detectors/rotate_detector.rb +11 -0
 - data/lib/fusuma/plugin/detectors/swipe_detector.rb +12 -0
 - data/lib/fusuma/plugin/events/event.rb +5 -2
 - data/lib/fusuma/plugin/events/records/gesture_record.rb +2 -0
 - data/lib/fusuma/plugin/events/records/index_record.rb +2 -0
 - data/lib/fusuma/plugin/events/records/record.rb +1 -0
 - data/lib/fusuma/plugin/events/records/text_record.rb +3 -0
 - data/lib/fusuma/plugin/executors/command_executor.rb +5 -1
 - data/lib/fusuma/plugin/executors/executor.rb +6 -0
 - data/lib/fusuma/plugin/filters/filter.rb +2 -0
 - data/lib/fusuma/plugin/filters/libinput_device_filter.rb +10 -0
 - data/lib/fusuma/plugin/inputs/input.rb +5 -0
 - data/lib/fusuma/plugin/inputs/libinput_command_input.rb +10 -3
 - data/lib/fusuma/plugin/inputs/timer_input.rb +4 -0
 - data/lib/fusuma/plugin/manager.rb +11 -1
 - data/lib/fusuma/plugin/parsers/libinput_gesture_parser.rb +9 -0
 - data/lib/fusuma/plugin/parsers/parser.rb +4 -0
 - data/lib/fusuma/string_support.rb +1 -0
 - data/lib/fusuma/version.rb +1 -1
 - data/lib/fusuma.rb +10 -1
 - metadata +2 -2
 
    
        data/lib/fusuma/multi_logger.rb
    CHANGED
    
    | 
         @@ -1,9 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            require "logger"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "singleton"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
       3 
6 
     | 
    
         
             
            # module as namespace
         
     | 
| 
       4 
7 
     | 
    
         
             
            module Fusuma
         
     | 
| 
       5 
     | 
    
         
            -
              require "logger"
         
     | 
| 
       6 
     | 
    
         
            -
              require "singleton"
         
     | 
| 
       7 
8 
     | 
    
         
             
              # logger separate between stdout and strerr
         
     | 
| 
       8 
9 
     | 
    
         
             
              class MultiLogger < Logger
         
     | 
| 
       9 
10 
     | 
    
         
             
                include Singleton
         
     | 
| 
         @@ -14,23 +15,28 @@ module Fusuma 
     | 
|
| 
       14 
15 
     | 
    
         
             
                class << self
         
     | 
| 
       15 
16 
     | 
    
         
             
                  attr_writer :filepath
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
      
 18 
     | 
    
         
            +
                  #: (untyped) -> void
         
     | 
| 
       17 
19 
     | 
    
         
             
                  def info(msg)
         
     | 
| 
       18 
20 
     | 
    
         
             
                    instance.info(msg)
         
     | 
| 
       19 
21 
     | 
    
         
             
                  end
         
     | 
| 
       20 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
                  #: (untyped) -> void
         
     | 
| 
       21 
24 
     | 
    
         
             
                  def debug(msg)
         
     | 
| 
       22 
25 
     | 
    
         
             
                    instance.debug(msg)
         
     | 
| 
       23 
26 
     | 
    
         
             
                  end
         
     | 
| 
       24 
27 
     | 
    
         | 
| 
      
 28 
     | 
    
         
            +
                  #: (untyped) -> void
         
     | 
| 
       25 
29 
     | 
    
         
             
                  def warn(msg)
         
     | 
| 
       26 
30 
     | 
    
         
             
                    instance.warn(msg)
         
     | 
| 
       27 
31 
     | 
    
         
             
                  end
         
     | 
| 
       28 
32 
     | 
    
         | 
| 
      
 33 
     | 
    
         
            +
                  #: (untyped) -> void
         
     | 
| 
       29 
34 
     | 
    
         
             
                  def error(msg)
         
     | 
| 
       30 
35 
     | 
    
         
             
                    instance.error(msg)
         
     | 
| 
       31 
36 
     | 
    
         
             
                  end
         
     | 
| 
       32 
37 
     | 
    
         
             
                end
         
     | 
| 
       33 
38 
     | 
    
         | 
| 
      
 39 
     | 
    
         
            +
                #: () -> void
         
     | 
| 
       34 
40 
     | 
    
         
             
                def initialize
         
     | 
| 
       35 
41 
     | 
    
         
             
                  filepath = self.class.instance_variable_get(:@filepath)
         
     | 
| 
       36 
42 
     | 
    
         
             
                  if filepath
         
     | 
| 
         @@ -45,28 +51,33 @@ module Fusuma 
     | 
|
| 
       45 
51 
     | 
    
         
             
                  @debug_mode = false
         
     | 
| 
       46 
52 
     | 
    
         
             
                end
         
     | 
| 
       47 
53 
     | 
    
         | 
| 
      
 54 
     | 
    
         
            +
                #: (untyped) -> void
         
     | 
| 
       48 
55 
     | 
    
         
             
                def debug(msg)
         
     | 
| 
       49 
56 
     | 
    
         
             
                  return unless debug_mode?
         
     | 
| 
       50 
57 
     | 
    
         | 
| 
       51 
58 
     | 
    
         
             
                  return if ignore_pattern?(msg)
         
     | 
| 
       52 
59 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                  super 
     | 
| 
      
 60 
     | 
    
         
            +
                  super
         
     | 
| 
       54 
61 
     | 
    
         
             
                end
         
     | 
| 
       55 
62 
     | 
    
         | 
| 
      
 63 
     | 
    
         
            +
                #: (untyped) -> void
         
     | 
| 
       56 
64 
     | 
    
         
             
                def warn(msg)
         
     | 
| 
       57 
65 
     | 
    
         
             
                  err_logger.warn(msg)
         
     | 
| 
       58 
66 
     | 
    
         
             
                end
         
     | 
| 
       59 
67 
     | 
    
         | 
| 
      
 68 
     | 
    
         
            +
                #: (untyped) -> void
         
     | 
| 
       60 
69 
     | 
    
         
             
                def error(msg)
         
     | 
| 
       61 
70 
     | 
    
         
             
                  err_logger.error(msg)
         
     | 
| 
       62 
71 
     | 
    
         
             
                end
         
     | 
| 
       63 
72 
     | 
    
         | 
| 
      
 73 
     | 
    
         
            +
                #: () -> bool
         
     | 
| 
       64 
74 
     | 
    
         
             
                def debug_mode?
         
     | 
| 
       65 
75 
     | 
    
         
             
                  debug_mode
         
     | 
| 
       66 
76 
     | 
    
         
             
                end
         
     | 
| 
       67 
77 
     | 
    
         | 
| 
       68 
78 
     | 
    
         
             
                private
         
     | 
| 
       69 
79 
     | 
    
         | 
| 
      
 80 
     | 
    
         
            +
                #: (String) -> bool
         
     | 
| 
       70 
81 
     | 
    
         
             
                def ignore_pattern?(msg)
         
     | 
| 
       71 
82 
     | 
    
         
             
                  # TODO: configurable from config.yml
         
     | 
| 
       72 
83 
     | 
    
         
             
                  # pattern = /timer_input|remap_touchpad_input|thumbsense context|libinput_command_input/
         
     | 
| 
         @@ -74,7 +85,7 @@ module Fusuma 
     | 
|
| 
       74 
85 
     | 
    
         
             
                  case msg
         
     | 
| 
       75 
86 
     | 
    
         
             
                  when Hash
         
     | 
| 
       76 
87 
     | 
    
         
             
                    e = msg.values.find { |v| v.is_a? Fusuma::Plugin::Events::Event }
         
     | 
| 
       77 
     | 
    
         
            -
                    return unless e
         
     | 
| 
      
 88 
     | 
    
         
            +
                    return false unless e
         
     | 
| 
       78 
89 
     | 
    
         | 
| 
       79 
90 
     | 
    
         
             
                    e.tag.match?(pattern)
         
     | 
| 
       80 
91 
     | 
    
         
             
                  when String
         
     | 
    
        data/lib/fusuma/plugin/base.rb
    CHANGED
    
    | 
         @@ -11,7 +11,13 @@ module Fusuma 
     | 
|
| 
       11 
11 
     | 
    
         
             
                  # when inherited from subclass
         
     | 
| 
       12 
12 
     | 
    
         
             
                  def self.inherited(subclass)
         
     | 
| 
       13 
13 
     | 
    
         
             
                    super
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    locations = Kernel.caller_locations(1..1)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    if locations.nil? || locations.empty?
         
     | 
| 
      
 17 
     | 
    
         
            +
                      raise "Plugin class #{subclass.name} must be defined in a file."
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    subclass_path = locations.first.path
         
     | 
| 
       15 
21 
     | 
    
         
             
                    Manager.add(plugin_class: subclass, plugin_path: subclass_path)
         
     | 
| 
       16 
22 
     | 
    
         
             
                  end
         
     | 
| 
       17 
23 
     | 
    
         | 
| 
         @@ -22,11 +28,13 @@ module Fusuma 
     | 
|
| 
       22 
28 
     | 
    
         
             
                  end
         
     | 
| 
       23 
29 
     | 
    
         | 
| 
       24 
30 
     | 
    
         
             
                  # @abstract override `#shutdown` to implement
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #: () -> nil
         
     | 
| 
       25 
32 
     | 
    
         
             
                  def shutdown
         
     | 
| 
       26 
33 
     | 
    
         
             
                  end
         
     | 
| 
       27 
34 
     | 
    
         | 
| 
       28 
35 
     | 
    
         
             
                  # config parameter name and Type of the value of parameter
         
     | 
| 
       29 
36 
     | 
    
         
             
                  # @return [Hash]
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #: () -> Hash[Symbol, Array[Class] | Class]
         
     | 
| 
       30 
38 
     | 
    
         
             
                  def config_param_types
         
     | 
| 
       31 
39 
     | 
    
         
             
                    raise NotImplementedError, "override #{self.class.name}##{__method__}"
         
     | 
| 
       32 
40 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -34,6 +42,7 @@ module Fusuma 
     | 
|
| 
       34 
42 
     | 
    
         
             
                  # @param key [Symbol]
         
     | 
| 
       35 
43 
     | 
    
         
             
                  # @param base [Config::Index]
         
     | 
| 
       36 
44 
     | 
    
         
             
                  # @return [Object]
         
     | 
| 
      
 45 
     | 
    
         
            +
                  #: (?Symbol?) -> (String | Hash[untyped, untyped] | Float | bool)?
         
     | 
| 
       37 
46 
     | 
    
         
             
                  def config_params(key = nil)
         
     | 
| 
       38 
47 
     | 
    
         
             
                    @config_params ||= {}
         
     | 
| 
       39 
48 
     | 
    
         
             
                    if @config_params["#{config_index.cache_key},#{key}"]
         
     | 
| 
         @@ -59,6 +68,7 @@ module Fusuma 
     | 
|
| 
       59 
68 
     | 
    
         
             
                      end
         
     | 
| 
       60 
69 
     | 
    
         
             
                  end
         
     | 
| 
       61 
70 
     | 
    
         | 
| 
      
 71 
     | 
    
         
            +
                  #: () -> Fusuma::Config::Index
         
     | 
| 
       62 
72 
     | 
    
         
             
                  def config_index
         
     | 
| 
       63 
73 
     | 
    
         
             
                    @config_index ||= Config::Index.new(self.class.name.gsub("Fusuma::", "").underscore.split("/"))
         
     | 
| 
       64 
74 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -7,6 +7,7 @@ module Fusuma 
     | 
|
| 
       7 
7 
     | 
    
         
             
                module Buffers
         
     | 
| 
       8 
8 
     | 
    
         
             
                  # buffer events and output
         
     | 
| 
       9 
9 
     | 
    
         
             
                  class Buffer < Base
         
     | 
| 
      
 10 
     | 
    
         
            +
                    #: (*nil | Array[untyped]) -> void
         
     | 
| 
       10 
11 
     | 
    
         
             
                    def initialize(*args)
         
     | 
| 
       11 
12 
     | 
    
         
             
                      super()
         
     | 
| 
       12 
13 
     | 
    
         
             
                      @events = Array.new(*args)
         
     | 
| 
         @@ -15,11 +16,13 @@ module Fusuma 
     | 
|
| 
       15 
16 
     | 
    
         
             
                    attr_reader :events
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
18 
     | 
    
         
             
                    # @return [String]
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #: () -> String
         
     | 
| 
       18 
20 
     | 
    
         
             
                    def type
         
     | 
| 
       19 
21 
     | 
    
         
             
                      @type ||= self.class.name.underscore.split("/").last.gsub("_buffer", "")
         
     | 
| 
       20 
22 
     | 
    
         
             
                    end
         
     | 
| 
       21 
23 
     | 
    
         | 
| 
       22 
24 
     | 
    
         
             
                    # @param event [Event]
         
     | 
| 
      
 25 
     | 
    
         
            +
                    #: (Fusuma::Plugin::Events::Event) -> Array[untyped]?
         
     | 
| 
       23 
26 
     | 
    
         
             
                    def buffer(event)
         
     | 
| 
       24 
27 
     | 
    
         
             
                      return if event&.tag != source
         
     | 
| 
       25 
28 
     | 
    
         | 
| 
         @@ -32,17 +35,20 @@ module Fusuma 
     | 
|
| 
       32 
35 
     | 
    
         
             
                    end
         
     | 
| 
       33 
36 
     | 
    
         | 
| 
       34 
37 
     | 
    
         
             
                    # @return [TrueClass, FalseClass]
         
     | 
| 
      
 38 
     | 
    
         
            +
                    #: () -> bool
         
     | 
| 
       35 
39 
     | 
    
         
             
                    def empty?
         
     | 
| 
       36 
40 
     | 
    
         
             
                      @events.empty?
         
     | 
| 
       37 
41 
     | 
    
         
             
                    end
         
     | 
| 
       38 
42 
     | 
    
         | 
| 
       39 
43 
     | 
    
         
             
                    # clear buffer
         
     | 
| 
      
 44 
     | 
    
         
            +
                    #: () -> void
         
     | 
| 
       40 
45 
     | 
    
         
             
                    def clear
         
     | 
| 
       41 
46 
     | 
    
         
             
                      @events.clear
         
     | 
| 
       42 
47 
     | 
    
         
             
                    end
         
     | 
| 
       43 
48 
     | 
    
         | 
| 
       44 
49 
     | 
    
         
             
                    # Set source for tag from config.yml.
         
     | 
| 
       45 
50 
     | 
    
         
             
                    # DEFAULT_SOURCE is defined in each plugins.
         
     | 
| 
      
 51 
     | 
    
         
            +
                    #: () -> String
         
     | 
| 
       46 
52 
     | 
    
         
             
                    def source
         
     | 
| 
       47 
53 
     | 
    
         
             
                      @source ||= config_params(:source) || self.class.const_get(:DEFAULT_SOURCE)
         
     | 
| 
       48 
54 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -11,6 +11,7 @@ module Fusuma 
     | 
|
| 
       11 
11 
     | 
    
         
             
                    DEFAULT_SOURCE = "libinput_gesture_parser"
         
     | 
| 
       12 
12 
     | 
    
         
             
                    DEFAULT_SECONDS_TO_KEEP = 100
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
      
 14 
     | 
    
         
            +
                    #: (*nil | Array[untyped]) -> void
         
     | 
| 
       14 
15 
     | 
    
         
             
                    def initialize(*args)
         
     | 
| 
       15 
16 
     | 
    
         
             
                      super
         
     | 
| 
       16 
17 
     | 
    
         
             
                      @cache = {}
         
     | 
| 
         @@ -18,6 +19,7 @@ module Fusuma 
     | 
|
| 
       18 
19 
     | 
    
         
             
                      @cache_sum10 = {}
         
     | 
| 
       19 
20 
     | 
    
         
             
                    end
         
     | 
| 
       20 
21 
     | 
    
         | 
| 
      
 22 
     | 
    
         
            +
                    #: () -> Hash[untyped, untyped]
         
     | 
| 
       21 
23 
     | 
    
         
             
                    def clear
         
     | 
| 
       22 
24 
     | 
    
         
             
                      super.clear
         
     | 
| 
       23 
25 
     | 
    
         
             
                      @cache = {}
         
     | 
| 
         @@ -25,6 +27,7 @@ module Fusuma 
     | 
|
| 
       25 
27 
     | 
    
         
             
                      @cache_sum10 = {}
         
     | 
| 
       26 
28 
     | 
    
         
             
                    end
         
     | 
| 
       27 
29 
     | 
    
         | 
| 
      
 30 
     | 
    
         
            +
                    #: () -> Hash[Symbol, Array[Class] | Class]
         
     | 
| 
       28 
31 
     | 
    
         
             
                    def config_param_types
         
     | 
| 
       29 
32 
     | 
    
         
             
                      {
         
     | 
| 
       30 
33 
     | 
    
         
             
                        source: [String],
         
     | 
| 
         @@ -34,6 +37,7 @@ module Fusuma 
     | 
|
| 
       34 
37 
     | 
    
         | 
| 
       35 
38 
     | 
    
         
             
                    # @param event [Event]
         
     | 
| 
       36 
39 
     | 
    
         
             
                    # @return [Buffer, FalseClass]
         
     | 
| 
      
 40 
     | 
    
         
            +
                    #: (Fusuma::Plugin::Events::Event) -> Fusuma::Plugin::Buffers::GestureBuffer?
         
     | 
| 
       37 
41 
     | 
    
         
             
                    def buffer(event)
         
     | 
| 
       38 
42 
     | 
    
         
             
                      # TODO: buffering events into buffer plugins
         
     | 
| 
       39 
43 
     | 
    
         
             
                      # - gesture event buffer
         
     | 
| 
         @@ -45,10 +49,11 @@ module Fusuma 
     | 
|
| 
       45 
49 
     | 
    
         
             
                      self
         
     | 
| 
       46 
50 
     | 
    
         
             
                    end
         
     | 
| 
       47 
51 
     | 
    
         | 
| 
      
 52 
     | 
    
         
            +
                    #: (?current_time: Time) -> void
         
     | 
| 
       48 
53 
     | 
    
         
             
                    def clear_expired(current_time: Time.now)
         
     | 
| 
       49 
54 
     | 
    
         
             
                      clear if ended?
         
     | 
| 
       50 
55 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
                      @seconds_to_keep ||=  
     | 
| 
      
 56 
     | 
    
         
            +
                      @seconds_to_keep ||= config_params(:seconds_to_keep) || DEFAULT_SECONDS_TO_KEEP
         
     | 
| 
       52 
57 
     | 
    
         
             
                      @events.each do |e|
         
     | 
| 
       53 
58 
     | 
    
         
             
                        break if current_time - e.time < @seconds_to_keep
         
     | 
| 
       54 
59 
     | 
    
         | 
| 
         @@ -61,6 +66,7 @@ module Fusuma 
     | 
|
| 
       61 
66 
     | 
    
         
             
                      end
         
     | 
| 
       62 
67 
     | 
    
         
             
                    end
         
     | 
| 
       63 
68 
     | 
    
         | 
| 
      
 69 
     | 
    
         
            +
                    #: () -> bool
         
     | 
| 
       64 
70 
     | 
    
         
             
                    def ended?
         
     | 
| 
       65 
71 
     | 
    
         
             
                      return false if empty?
         
     | 
| 
       66 
72 
     | 
    
         | 
| 
         @@ -74,6 +80,7 @@ module Fusuma 
     | 
|
| 
       74 
80 
     | 
    
         | 
| 
       75 
81 
     | 
    
         
             
                    # @param attr [Symbol]
         
     | 
| 
       76 
82 
     | 
    
         
             
                    # @return [Float]
         
     | 
| 
      
 83 
     | 
    
         
            +
                    #: (Symbol) -> Float
         
     | 
| 
       77 
84 
     | 
    
         
             
                    def sum_attrs(attr)
         
     | 
| 
       78 
85 
     | 
    
         
             
                      updating_events.map do |gesture_event|
         
     | 
| 
       79 
86 
     | 
    
         
             
                        gesture_event.record.delta[attr].to_f
         
     | 
| 
         @@ -82,6 +89,7 @@ module Fusuma 
     | 
|
| 
       82 
89 
     | 
    
         | 
| 
       83 
90 
     | 
    
         
             
                    # @param attr [Symbol]
         
     | 
| 
       84 
91 
     | 
    
         
             
                    # @return [Float]
         
     | 
| 
      
 92 
     | 
    
         
            +
                    #: (Symbol) -> Float
         
     | 
| 
       85 
93 
     | 
    
         
             
                    def sum_last10_attrs(attr) # sums last 10 values of attr (or all if length < 10)
         
     | 
| 
       86 
94 
     | 
    
         
             
                      cache_entry = (@cache_sum10[attr] ||= CacheEntry.new(0, 0))
         
     | 
| 
       87 
95 
     | 
    
         
             
                      upd_ev = updating_events
         
     | 
| 
         @@ -90,7 +98,7 @@ module Fusuma 
     | 
|
| 
       90 
98 
     | 
    
         
             
                          gesture_event.record.delta[attr].to_f
         
     | 
| 
       91 
99 
     | 
    
         
             
                        end.reduce(:+)
         
     | 
| 
       92 
100 
     | 
    
         
             
                      elsif upd_ev.length > cache_entry.checked
         
     | 
| 
       93 
     | 
    
         
            -
                        cache_entry.value = cache_entry.value + upd_ev[-1].record.delta[attr].to_f - 
     | 
| 
      
 101 
     | 
    
         
            +
                        cache_entry.value = cache_entry.value + upd_ev[-1].record.delta[attr].to_f -
         
     | 
| 
       94 
102 
     | 
    
         
             
                          ((upd_ev.length > 10) ? upd_ev[-11].record.delta[attr].to_f : 0)
         
     | 
| 
       95 
103 
     | 
    
         
             
                      else
         
     | 
| 
       96 
104 
     | 
    
         
             
                        return cache_entry.value
         
     | 
| 
         @@ -99,6 +107,7 @@ module Fusuma 
     | 
|
| 
       99 
107 
     | 
    
         
             
                      cache_entry.value
         
     | 
| 
       100 
108 
     | 
    
         
             
                    end
         
     | 
| 
       101 
109 
     | 
    
         | 
| 
      
 110 
     | 
    
         
            +
                    #: () -> Array[untyped]
         
     | 
| 
       102 
111 
     | 
    
         
             
                    def updating_events
         
     | 
| 
       103 
112 
     | 
    
         
             
                      cache_entry = (@cache[:updating_events] ||= CacheEntry.new(0, []))
         
     | 
| 
       104 
113 
     | 
    
         
             
                      cache_entry.checked.upto(@events.length - 1).each do |i|
         
     | 
| 
         @@ -110,11 +119,13 @@ module Fusuma 
     | 
|
| 
       110 
119 
     | 
    
         | 
| 
       111 
120 
     | 
    
         
             
                    # @param attr [Symbol]
         
     | 
| 
       112 
121 
     | 
    
         
             
                    # @return [Float]
         
     | 
| 
      
 122 
     | 
    
         
            +
                    #: (Symbol) -> Float
         
     | 
| 
       113 
123 
     | 
    
         
             
                    def avg_attrs(attr)
         
     | 
| 
       114 
124 
     | 
    
         
             
                      sum_attrs(attr).to_f / updating_events.length
         
     | 
| 
       115 
125 
     | 
    
         
             
                    end
         
     | 
| 
       116 
126 
     | 
    
         | 
| 
       117 
127 
     | 
    
         
             
                    # return [Integer]
         
     | 
| 
      
 128 
     | 
    
         
            +
                    #: () -> Integer
         
     | 
| 
       118 
129 
     | 
    
         
             
                    def finger
         
     | 
| 
       119 
130 
     | 
    
         
             
                      @events.last.record.finger.to_i
         
     | 
| 
       120 
131 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -127,13 +138,7 @@ module Fusuma 
     | 
|
| 
       127 
138 
     | 
    
         
             
                      @events.last.record.gesture
         
     | 
| 
       128 
139 
     | 
    
         
             
                    end
         
     | 
| 
       129 
140 
     | 
    
         | 
| 
       130 
     | 
    
         
            -
                     
     | 
| 
       131 
     | 
    
         
            -
                      return enum_for(:select_by_events) unless block
         
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
                      events = @events.select(&block)
         
     | 
| 
       134 
     | 
    
         
            -
                      self.class.new events
         
     | 
| 
       135 
     | 
    
         
            -
                    end
         
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
      
 141 
     | 
    
         
            +
                    #: (String) -> Fusuma::Plugin::Buffers::GestureBuffer
         
     | 
| 
       137 
142 
     | 
    
         
             
                    def select_by_type(type)
         
     | 
| 
       138 
143 
     | 
    
         
             
                      cache_entry = (@cache_select_by[type] ||= CacheEntry.new(0, self.class.new([])))
         
     | 
| 
       139 
144 
     | 
    
         
             
                      cache_entry.checked.upto(@events.length - 1).each do |i|
         
     | 
| 
         @@ -143,6 +148,7 @@ module Fusuma 
     | 
|
| 
       143 
148 
     | 
    
         
             
                      cache_entry.value
         
     | 
| 
       144 
149 
     | 
    
         
             
                    end
         
     | 
| 
       145 
150 
     | 
    
         | 
| 
      
 151 
     | 
    
         
            +
                    #: () -> Fusuma::Plugin::Buffers::GestureBuffer
         
     | 
| 
       146 
152 
     | 
    
         
             
                    def select_from_last_begin
         
     | 
| 
       147 
153 
     | 
    
         
             
                      return self if empty?
         
     | 
| 
       148 
154 
     | 
    
         
             
                      cache_entry = (@cache[:last_begin] ||= CacheEntry.new(0, nil))
         
     | 
| 
         @@ -19,6 +19,7 @@ module Fusuma 
     | 
|
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                    # @param event [Event]
         
     | 
| 
       21 
21 
     | 
    
         
             
                    # @return [Buffer, NilClass]
         
     | 
| 
      
 22 
     | 
    
         
            +
                    #: (Fusuma::Plugin::Events::Event) -> Fusuma::Plugin::Buffers::TimerBuffer?
         
     | 
| 
       22 
23 
     | 
    
         
             
                    def buffer(event)
         
     | 
| 
       23 
24 
     | 
    
         
             
                      return if event&.tag != source
         
     | 
| 
       24 
25 
     | 
    
         | 
| 
         @@ -27,7 +28,7 @@ module Fusuma 
     | 
|
| 
       27 
28 
     | 
    
         
             
                    end
         
     | 
| 
       28 
29 
     | 
    
         | 
| 
       29 
30 
     | 
    
         
             
                    def clear_expired(current_time: Time.now)
         
     | 
| 
       30 
     | 
    
         
            -
                      @seconds_to_keep ||=  
     | 
| 
      
 31 
     | 
    
         
            +
                      @seconds_to_keep ||= config_params(:seconds_to_keep) || DEFAULT_SECONDS_TO_KEEP
         
     | 
| 
       31 
32 
     | 
    
         
             
                      @events.each do |e|
         
     | 
| 
       32 
33 
     | 
    
         
             
                        break if current_time - e.time < @seconds_to_keep
         
     | 
| 
       33 
34 
     | 
    
         | 
| 
         @@ -8,22 +8,29 @@ module Fusuma 
     | 
|
| 
       8 
8 
     | 
    
         
             
                module Detectors
         
     | 
| 
       9 
9 
     | 
    
         
             
                  # Inherite this base
         
     | 
| 
       10 
10 
     | 
    
         
             
                  class Detector < Base
         
     | 
| 
      
 11 
     | 
    
         
            +
                    def self.type(tag_name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      tag_name.gsub("_detector", "")
         
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    #: (*nil) -> void
         
     | 
| 
       11 
16 
     | 
    
         
             
                    def initialize(*args)
         
     | 
| 
       12 
17 
     | 
    
         
             
                      super
         
     | 
| 
       13 
     | 
    
         
            -
                      @tag = self.class. 
     | 
| 
       14 
     | 
    
         
            -
                      @type = self.class.type
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @tag = self.class.name.split("Detectors::").last.underscore
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @type = self.class.type(@tag)
         
     | 
| 
       15 
20 
     | 
    
         
             
                    end
         
     | 
| 
       16 
21 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                    attr_reader :tag
         
     | 
| 
       18 
     | 
    
         
            -
                    attr_reader :type
         
     | 
| 
      
 22 
     | 
    
         
            +
                    attr_reader :tag #: String
         
     | 
| 
      
 23 
     | 
    
         
            +
                    attr_reader :type #: String
         
     | 
| 
       19 
24 
     | 
    
         | 
| 
       20 
25 
     | 
    
         
             
                    # @return [Array<String>]
         
     | 
| 
      
 26 
     | 
    
         
            +
                    #: () -> Array[String]
         
     | 
| 
       21 
27 
     | 
    
         
             
                    def sources
         
     | 
| 
       22 
28 
     | 
    
         
             
                      @sources ||= self.class.const_get(:SOURCES)
         
     | 
| 
       23 
29 
     | 
    
         
             
                    end
         
     | 
| 
       24 
30 
     | 
    
         | 
| 
       25 
31 
     | 
    
         
             
                    # Always watch buffers and detect them or not
         
     | 
| 
       26 
32 
     | 
    
         
             
                    # @return [TrueClass,FalseClass]
         
     | 
| 
      
 33 
     | 
    
         
            +
                    #: () -> bool
         
     | 
| 
       27 
34 
     | 
    
         
             
                    def watch?
         
     | 
| 
       28 
35 
     | 
    
         
             
                      false
         
     | 
| 
       29 
36 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -39,28 +46,21 @@ module Fusuma 
     | 
|
| 
       39 
46 
     | 
    
         | 
| 
       40 
47 
     | 
    
         
             
                    # @param record [Events::Records::Record]
         
     | 
| 
       41 
48 
     | 
    
         
             
                    # @return [Events::Event]
         
     | 
| 
      
 49 
     | 
    
         
            +
                    #: (record: Fusuma::Plugin::Events::Records::IndexRecord) -> Fusuma::Plugin::Events::Event
         
     | 
| 
       42 
50 
     | 
    
         
             
                    def create_event(record:)
         
     | 
| 
       43 
51 
     | 
    
         
             
                      @last_time = Time.now
         
     | 
| 
       44 
     | 
    
         
            -
                      Events::Event.new(time: @last_time, tag: tag, record: record)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      Events::Event.new(time: @last_time, tag: @tag, record: record)
         
     | 
| 
       45 
53 
     | 
    
         
             
                    end
         
     | 
| 
       46 
54 
     | 
    
         | 
| 
      
 55 
     | 
    
         
            +
                    #: () -> Time
         
     | 
| 
       47 
56 
     | 
    
         
             
                    def last_time
         
     | 
| 
       48 
57 
     | 
    
         
             
                      @last_time ||= Time.now
         
     | 
| 
       49 
58 
     | 
    
         
             
                    end
         
     | 
| 
       50 
59 
     | 
    
         | 
| 
      
 60 
     | 
    
         
            +
                    #: () -> bool
         
     | 
| 
       51 
61 
     | 
    
         
             
                    def first_time?
         
     | 
| 
       52 
62 
     | 
    
         
             
                      @last_time.nil?
         
     | 
| 
       53 
63 
     | 
    
         
             
                    end
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                    class << self
         
     | 
| 
       56 
     | 
    
         
            -
                      def tag
         
     | 
| 
       57 
     | 
    
         
            -
                        name.split("Detectors::").last.underscore
         
     | 
| 
       58 
     | 
    
         
            -
                      end
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
                      def type(tag_name = tag)
         
     | 
| 
       61 
     | 
    
         
            -
                        tag_name.gsub("_detector", "")
         
     | 
| 
       62 
     | 
    
         
            -
                      end
         
     | 
| 
       63 
     | 
    
         
            -
                    end
         
     | 
| 
       64 
64 
     | 
    
         
             
                  end
         
     | 
| 
       65 
65 
     | 
    
         
             
                end
         
     | 
| 
       66 
66 
     | 
    
         
             
              end
         
     | 
| 
         @@ -14,6 +14,7 @@ module Fusuma 
     | 
|
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                    BASE_THRESHOLD = 0.7
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
      
 17 
     | 
    
         
            +
                    #: (*nil) -> void
         
     | 
| 
       17 
18 
     | 
    
         
             
                    def initialize(*args)
         
     | 
| 
       18 
19 
     | 
    
         
             
                      super
         
     | 
| 
       19 
20 
     | 
    
         
             
                      @timer = Inputs::TimerInput.instance
         
     | 
| 
         @@ -23,6 +24,7 @@ module Fusuma 
     | 
|
| 
       23 
24 
     | 
    
         
             
                    # @return [Events::Event] if event is detected
         
     | 
| 
       24 
25 
     | 
    
         
             
                    # @return [Array<Events::Event>] if hold end event is detected
         
     | 
| 
       25 
26 
     | 
    
         
             
                    # @return [NilClass] if event is NOT detected
         
     | 
| 
      
 27 
     | 
    
         
            +
                    #: (Array[untyped]) -> Fusuma::Plugin::Events::Event?
         
     | 
| 
       26 
28 
     | 
    
         
             
                    def detect(buffers)
         
     | 
| 
       27 
29 
     | 
    
         
             
                      hold_buffer = find_hold_buffer(buffers)
         
     | 
| 
       28 
30 
     | 
    
         
             
                      return if hold_buffer.empty?
         
     | 
| 
         @@ -77,6 +79,7 @@ module Fusuma 
     | 
|
| 
       77 
79 
     | 
    
         | 
| 
       78 
80 
     | 
    
         
             
                    # @param [Integer] finger
         
     | 
| 
       79 
81 
     | 
    
         
             
                    # @return [Config::Index]
         
     | 
| 
      
 82 
     | 
    
         
            +
                    #: (finger: Integer) -> Fusuma::Config::Index
         
     | 
| 
       80 
83 
     | 
    
         
             
                    def create_oneshot_index(finger:)
         
     | 
| 
       81 
84 
     | 
    
         
             
                      Config::Index.new(
         
     | 
| 
       82 
85 
     | 
    
         
             
                        [
         
     | 
| 
         @@ -88,6 +91,7 @@ module Fusuma 
     | 
|
| 
       88 
91 
     | 
    
         | 
| 
       89 
92 
     | 
    
         
             
                    # @param [Integer] finger
         
     | 
| 
       90 
93 
     | 
    
         
             
                    # @return [Config::Index]
         
     | 
| 
      
 94 
     | 
    
         
            +
                    #: (finger: Integer, status: String) -> Fusuma::Config::Index
         
     | 
| 
       91 
95 
     | 
    
         
             
                    def create_repeat_index(finger:, status:)
         
     | 
| 
       92 
96 
     | 
    
         
             
                      Config::Index.new(
         
     | 
| 
       93 
97 
     | 
    
         
             
                        [
         
     | 
| 
         @@ -102,12 +106,14 @@ module Fusuma 
     | 
|
| 
       102 
106 
     | 
    
         | 
| 
       103 
107 
     | 
    
         
             
                    # @param buffers [Array<Buffers::Buffer>]
         
     | 
| 
       104 
108 
     | 
    
         
             
                    # @return [Buffers::GestureBuffer]
         
     | 
| 
      
 109 
     | 
    
         
            +
                    #: (Array[untyped]) -> Fusuma::Plugin::Buffers::GestureBuffer
         
     | 
| 
       105 
110 
     | 
    
         
             
                    def find_hold_buffer(buffers)
         
     | 
| 
       106 
111 
     | 
    
         
             
                      buffers.find { |b| b.type == BUFFER_TYPE }
         
     | 
| 
       107 
112 
     | 
    
         
             
                        .select_from_last_begin
         
     | 
| 
       108 
113 
     | 
    
         
             
                        .select_by_type(GESTURE_RECORD_TYPE)
         
     | 
| 
       109 
114 
     | 
    
         
             
                    end
         
     | 
| 
       110 
115 
     | 
    
         | 
| 
      
 116 
     | 
    
         
            +
                    #: (hold_events: Array[untyped], last_timer: nil | Fusuma::Plugin::Events::Event) -> Float
         
     | 
| 
       111 
117 
     | 
    
         
             
                    def calc_holding_time(hold_events:, last_timer:)
         
     | 
| 
       112 
118 
     | 
    
         
             
                      last_time = if last_timer && (hold_events.last.time < last_timer.time)
         
     | 
| 
       113 
119 
     | 
    
         
             
                        last_timer.time
         
     | 
| 
         @@ -117,16 +123,18 @@ module Fusuma 
     | 
|
| 
       117 
123 
     | 
    
         
             
                      last_time - hold_events.first.time
         
     | 
| 
       118 
124 
     | 
    
         
             
                    end
         
     | 
| 
       119 
125 
     | 
    
         | 
| 
      
 126 
     | 
    
         
            +
                    #: (index: Fusuma::Config::Index, holding_time: Float) -> bool
         
     | 
| 
       120 
127 
     | 
    
         
             
                    def enough?(index:, holding_time:)
         
     | 
| 
       121 
128 
     | 
    
         
             
                      diff = threshold(index: index) - holding_time
         
     | 
| 
       122 
129 
     | 
    
         
             
                      if diff < 0
         
     | 
| 
       123 
     | 
    
         
            -
                        true
         
     | 
| 
      
 130 
     | 
    
         
            +
                        return true
         
     | 
| 
       124 
131 
     | 
    
         
             
                      elsif diff < @timer.interval
         
     | 
| 
       125 
132 
     | 
    
         
             
                        @timer.wake_early(Time.now + diff)
         
     | 
| 
       126 
     | 
    
         
            -
                        false
         
     | 
| 
       127 
133 
     | 
    
         
             
                      end
         
     | 
| 
      
 134 
     | 
    
         
            +
                      false
         
     | 
| 
       128 
135 
     | 
    
         
             
                    end
         
     | 
| 
       129 
136 
     | 
    
         | 
| 
      
 137 
     | 
    
         
            +
                    #: (index: Fusuma::Config::Index) -> Float
         
     | 
| 
       130 
138 
     | 
    
         
             
                    def threshold(index:)
         
     | 
| 
       131 
139 
     | 
    
         
             
                      @threshold ||= {}
         
     | 
| 
       132 
140 
     | 
    
         
             
                      @threshold[index.cache_key] ||= begin
         
     | 
| 
         @@ -16,6 +16,7 @@ module Fusuma 
     | 
|
| 
       16 
16 
     | 
    
         
             
                    # @param buffers [Array<Buffer>]
         
     | 
| 
       17 
17 
     | 
    
         
             
                    # @return [Events::Event] if event is detected
         
     | 
| 
       18 
18 
     | 
    
         
             
                    # @return [NilClass] if event is NOT detected
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #: (Array[untyped]) -> (Fusuma::Plugin::Events::Event | Array[untyped])?
         
     | 
| 
       19 
20 
     | 
    
         
             
                    def detect(buffers)
         
     | 
| 
       20 
21 
     | 
    
         
             
                      gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
         
     | 
| 
       21 
22 
     | 
    
         
             
                        .select_from_last_begin
         
     | 
| 
         @@ -53,7 +54,7 @@ module Fusuma 
     | 
|
| 
       53 
54 
     | 
    
         
             
                      delta = event.record.delta
         
     | 
| 
       54 
55 
     | 
    
         
             
                      prev_delta = prev_event.record.delta
         
     | 
| 
       55 
56 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                      repeat_direction = Direction.new(target: delta.zoom, base:  
     | 
| 
      
 57 
     | 
    
         
            +
                      repeat_direction = Direction.new(target: delta.zoom, base: prev_delta&.zoom || 1.0).to_s
         
     | 
| 
       57 
58 
     | 
    
         
             
                      # repeat_quantity = Quantity.new(target: delta.zoom, base: (prev_delta&.zoom || 1.0)).to_f
         
     | 
| 
       58 
59 
     | 
    
         | 
| 
       59 
60 
     | 
    
         
             
                      repeat_index = create_repeat_index(gesture: type, finger: finger,
         
     | 
| 
         @@ -97,6 +98,7 @@ module Fusuma 
     | 
|
| 
       97 
98 
     | 
    
         
             
                    # @param [String] direction
         
     | 
| 
       98 
99 
     | 
    
         
             
                    # @param [String] status
         
     | 
| 
       99 
100 
     | 
    
         
             
                    # @return [Config::Index]
         
     | 
| 
      
 101 
     | 
    
         
            +
                    #: (gesture: String, finger: Integer, direction: String, status: String) -> Fusuma::Config::Index
         
     | 
| 
       100 
102 
     | 
    
         
             
                    def create_repeat_index(gesture:, finger:, direction:, status:)
         
     | 
| 
       101 
103 
     | 
    
         
             
                      Config::Index.new(
         
     | 
| 
       102 
104 
     | 
    
         
             
                        [
         
     | 
| 
         @@ -112,6 +114,7 @@ module Fusuma 
     | 
|
| 
       112 
114 
     | 
    
         
             
                    # @param [Integer] finger
         
     | 
| 
       113 
115 
     | 
    
         
             
                    # @param [String] direction
         
     | 
| 
       114 
116 
     | 
    
         
             
                    # @return [Config::Index]
         
     | 
| 
      
 117 
     | 
    
         
            +
                    #: (gesture: String, finger: Integer, direction: String) -> Fusuma::Config::Index
         
     | 
| 
       115 
118 
     | 
    
         
             
                    def create_oneshot_index(gesture:, finger:, direction:)
         
     | 
| 
       116 
119 
     | 
    
         
             
                      Config::Index.new(
         
     | 
| 
       117 
120 
     | 
    
         
             
                        [
         
     | 
| 
         @@ -124,16 +127,19 @@ module Fusuma 
     | 
|
| 
       124 
127 
     | 
    
         | 
| 
       125 
128 
     | 
    
         
             
                    private
         
     | 
| 
       126 
129 
     | 
    
         | 
| 
      
 130 
     | 
    
         
            +
                    #: (Fusuma::Plugin::Events::Event, Fusuma::Plugin::Events::Event) -> bool
         
     | 
| 
       127 
131 
     | 
    
         
             
                    def moved?(prev_event, event)
         
     | 
| 
       128 
132 
     | 
    
         
             
                      zoom_delta = (event.record.delta.zoom - prev_event.record.delta.zoom).abs
         
     | 
| 
       129 
133 
     | 
    
         
             
                      updating_time = (event.time - prev_event.time) * 100
         
     | 
| 
       130 
134 
     | 
    
         
             
                      zoom_delta / updating_time > 0.01
         
     | 
| 
       131 
135 
     | 
    
         
             
                    end
         
     | 
| 
       132 
136 
     | 
    
         | 
| 
      
 137 
     | 
    
         
            +
                    #: (index: Fusuma::Config::Index, quantity: Float) -> bool
         
     | 
| 
       133 
138 
     | 
    
         
             
                    def enough_oneshot_threshold?(index:, quantity:)
         
     | 
| 
       134 
139 
     | 
    
         
             
                      quantity >= threshold(index: index)
         
     | 
| 
       135 
140 
     | 
    
         
             
                    end
         
     | 
| 
       136 
141 
     | 
    
         | 
| 
      
 142 
     | 
    
         
            +
                    #: (index: Fusuma::Config::Index) -> Float
         
     | 
| 
       137 
143 
     | 
    
         
             
                    def threshold(index:)
         
     | 
| 
       138 
144 
     | 
    
         
             
                      @threshold ||= {}
         
     | 
| 
       139 
145 
     | 
    
         
             
                      @threshold[index.cache_key] ||= begin
         
     | 
| 
         @@ -150,15 +156,18 @@ module Fusuma 
     | 
|
| 
       150 
156 
     | 
    
         
             
                      IN = "in"
         
     | 
| 
       151 
157 
     | 
    
         
             
                      OUT = "out"
         
     | 
| 
       152 
158 
     | 
    
         | 
| 
      
 159 
     | 
    
         
            +
                      #: (target: Float, base: Integer | Float) -> void
         
     | 
| 
       153 
160 
     | 
    
         
             
                      def initialize(target:, base:)
         
     | 
| 
       154 
161 
     | 
    
         
             
                        @target = target.to_f
         
     | 
| 
       155 
162 
     | 
    
         
             
                        @base = base.to_f
         
     | 
| 
       156 
163 
     | 
    
         
             
                      end
         
     | 
| 
       157 
164 
     | 
    
         | 
| 
      
 165 
     | 
    
         
            +
                      #: () -> String
         
     | 
| 
       158 
166 
     | 
    
         
             
                      def to_s
         
     | 
| 
       159 
167 
     | 
    
         
             
                        calc
         
     | 
| 
       160 
168 
     | 
    
         
             
                      end
         
     | 
| 
       161 
169 
     | 
    
         | 
| 
      
 170 
     | 
    
         
            +
                      #: () -> String
         
     | 
| 
       162 
171 
     | 
    
         
             
                      def calc
         
     | 
| 
       163 
172 
     | 
    
         
             
                        if @target > @base
         
     | 
| 
       164 
173 
     | 
    
         
             
                          OUT
         
     | 
| 
         @@ -170,15 +179,18 @@ module Fusuma 
     | 
|
| 
       170 
179 
     | 
    
         | 
| 
       171 
180 
     | 
    
         
             
                    # quantity of gesture
         
     | 
| 
       172 
181 
     | 
    
         
             
                    class Quantity
         
     | 
| 
      
 182 
     | 
    
         
            +
                      #: (target: Float, base: Float) -> void
         
     | 
| 
       173 
183 
     | 
    
         
             
                      def initialize(target:, base:)
         
     | 
| 
       174 
184 
     | 
    
         
             
                        @target = target.to_f
         
     | 
| 
       175 
185 
     | 
    
         
             
                        @base = base.to_f
         
     | 
| 
       176 
186 
     | 
    
         
             
                      end
         
     | 
| 
       177 
187 
     | 
    
         | 
| 
      
 188 
     | 
    
         
            +
                      #: () -> Float
         
     | 
| 
       178 
189 
     | 
    
         
             
                      def to_f
         
     | 
| 
       179 
190 
     | 
    
         
             
                        calc.to_f
         
     | 
| 
       180 
191 
     | 
    
         
             
                      end
         
     | 
| 
       181 
192 
     | 
    
         | 
| 
      
 193 
     | 
    
         
            +
                      #: () -> Float
         
     | 
| 
       182 
194 
     | 
    
         
             
                      def calc
         
     | 
| 
       183 
195 
     | 
    
         
             
                        if @target > @base
         
     | 
| 
       184 
196 
     | 
    
         
             
                          @target / @base
         
     | 
| 
         @@ -16,6 +16,7 @@ module Fusuma 
     | 
|
| 
       16 
16 
     | 
    
         
             
                    # @param buffers [Array<Buffer>]
         
     | 
| 
       17 
17 
     | 
    
         
             
                    # @return [Events::Event] if event is detected
         
     | 
| 
       18 
18 
     | 
    
         
             
                    # @return [NilClass] if event is NOT detected
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #: (Array[untyped]) -> (Fusuma::Plugin::Events::Event | Array[untyped])?
         
     | 
| 
       19 
20 
     | 
    
         
             
                    def detect(buffers)
         
     | 
| 
       20 
21 
     | 
    
         
             
                      gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
         
     | 
| 
       21 
22 
     | 
    
         
             
                        .select_from_last_begin
         
     | 
| 
         @@ -84,6 +85,7 @@ module Fusuma 
     | 
|
| 
       84 
85 
     | 
    
         
             
                    # @param [String] direction
         
     | 
| 
       85 
86 
     | 
    
         
             
                    # @param [String] status
         
     | 
| 
       86 
87 
     | 
    
         
             
                    # @return [Config::Index]
         
     | 
| 
      
 88 
     | 
    
         
            +
                    #: (gesture: String, finger: Integer, direction: String, status: String) -> Fusuma::Config::Index
         
     | 
| 
       87 
89 
     | 
    
         
             
                    def create_repeat_index(gesture:, finger:, direction:, status:)
         
     | 
| 
       88 
90 
     | 
    
         
             
                      Config::Index.new(
         
     | 
| 
       89 
91 
     | 
    
         
             
                        [
         
     | 
| 
         @@ -99,6 +101,7 @@ module Fusuma 
     | 
|
| 
       99 
101 
     | 
    
         
             
                    # @param [Integer] finger
         
     | 
| 
       100 
102 
     | 
    
         
             
                    # @param [String] direction
         
     | 
| 
       101 
103 
     | 
    
         
             
                    # @return [Config::Index]
         
     | 
| 
      
 104 
     | 
    
         
            +
                    #: (gesture: String, finger: Integer, direction: String) -> Fusuma::Config::Index
         
     | 
| 
       102 
105 
     | 
    
         
             
                    def create_oneshot_index(gesture:, finger:, direction:)
         
     | 
| 
       103 
106 
     | 
    
         
             
                      Config::Index.new(
         
     | 
| 
       104 
107 
     | 
    
         
             
                        [
         
     | 
| 
         @@ -111,14 +114,17 @@ module Fusuma 
     | 
|
| 
       111 
114 
     | 
    
         | 
| 
       112 
115 
     | 
    
         
             
                    private
         
     | 
| 
       113 
116 
     | 
    
         | 
| 
      
 117 
     | 
    
         
            +
                    #: (Float) -> bool
         
     | 
| 
       114 
118 
     | 
    
         
             
                    def moved?(repeat_quantity)
         
     | 
| 
       115 
119 
     | 
    
         
             
                      repeat_quantity > 0.2
         
     | 
| 
       116 
120 
     | 
    
         
             
                    end
         
     | 
| 
       117 
121 
     | 
    
         | 
| 
      
 122 
     | 
    
         
            +
                    #: (index: Fusuma::Config::Index, quantity: Float) -> bool
         
     | 
| 
       118 
123 
     | 
    
         
             
                    def enough_oneshot_threshold?(index:, quantity:)
         
     | 
| 
       119 
124 
     | 
    
         
             
                      quantity > threshold(index: index)
         
     | 
| 
       120 
125 
     | 
    
         
             
                    end
         
     | 
| 
       121 
126 
     | 
    
         | 
| 
      
 127 
     | 
    
         
            +
                    #: (index: Fusuma::Config::Index) -> Float
         
     | 
| 
       122 
128 
     | 
    
         
             
                    def threshold(index:)
         
     | 
| 
       123 
129 
     | 
    
         
             
                      @threshold ||= {}
         
     | 
| 
       124 
130 
     | 
    
         
             
                      @threshold[index.cache_key] ||= begin
         
     | 
| 
         @@ -135,14 +141,17 @@ module Fusuma 
     | 
|
| 
       135 
141 
     | 
    
         
             
                      CLOCKWISE = "clockwise"
         
     | 
| 
       136 
142 
     | 
    
         
             
                      COUNTERCLOCKWISE = "counterclockwise"
         
     | 
| 
       137 
143 
     | 
    
         | 
| 
      
 144 
     | 
    
         
            +
                      #: (angle: Float) -> void
         
     | 
| 
       138 
145 
     | 
    
         
             
                      def initialize(angle:)
         
     | 
| 
       139 
146 
     | 
    
         
             
                        @angle = angle.to_f
         
     | 
| 
       140 
147 
     | 
    
         
             
                      end
         
     | 
| 
       141 
148 
     | 
    
         | 
| 
      
 149 
     | 
    
         
            +
                      #: () -> String
         
     | 
| 
       142 
150 
     | 
    
         
             
                      def to_s
         
     | 
| 
       143 
151 
     | 
    
         
             
                        calc
         
     | 
| 
       144 
152 
     | 
    
         
             
                      end
         
     | 
| 
       145 
153 
     | 
    
         | 
| 
      
 154 
     | 
    
         
            +
                      #: () -> String
         
     | 
| 
       146 
155 
     | 
    
         
             
                      def calc
         
     | 
| 
       147 
156 
     | 
    
         
             
                        if @angle.positive?
         
     | 
| 
       148 
157 
     | 
    
         
             
                          CLOCKWISE
         
     | 
| 
         @@ -154,10 +163,12 @@ module Fusuma 
     | 
|
| 
       154 
163 
     | 
    
         | 
| 
       155 
164 
     | 
    
         
             
                    # quantity of gesture
         
     | 
| 
       156 
165 
     | 
    
         
             
                    class Quantity
         
     | 
| 
      
 166 
     | 
    
         
            +
                      #: (angle: Float) -> void
         
     | 
| 
       157 
167 
     | 
    
         
             
                      def initialize(angle:)
         
     | 
| 
       158 
168 
     | 
    
         
             
                        @angle = angle.abs
         
     | 
| 
       159 
169 
     | 
    
         
             
                      end
         
     | 
| 
       160 
170 
     | 
    
         | 
| 
      
 171 
     | 
    
         
            +
                      #: () -> Float
         
     | 
| 
       161 
172 
     | 
    
         
             
                      def to_f
         
     | 
| 
       162 
173 
     | 
    
         
             
                        @angle.to_f
         
     | 
| 
       163 
174 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -16,6 +16,7 @@ module Fusuma 
     | 
|
| 
       16 
16 
     | 
    
         
             
                    # @param buffers [Array<Buffers::Buffer>]
         
     | 
| 
       17 
17 
     | 
    
         
             
                    # @return [Events::Event] if event is detected
         
     | 
| 
       18 
18 
     | 
    
         
             
                    # @return [NilClass] if event is NOT detected
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #: (Array[untyped]) -> (Fusuma::Plugin::Events::Event | Array[untyped])?
         
     | 
| 
       19 
20 
     | 
    
         
             
                    def detect(buffers)
         
     | 
| 
       20 
21 
     | 
    
         
             
                      gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
         
     | 
| 
       21 
22 
     | 
    
         
             
                        .select_from_last_begin
         
     | 
| 
         @@ -82,6 +83,7 @@ module Fusuma 
     | 
|
| 
       82 
83 
     | 
    
         
             
                    # @param [String] direction
         
     | 
| 
       83 
84 
     | 
    
         
             
                    # @param [String] status
         
     | 
| 
       84 
85 
     | 
    
         
             
                    # @return [Config::Index]
         
     | 
| 
      
 86 
     | 
    
         
            +
                    #: (gesture: String, finger: Integer, direction: String, status: String) -> Fusuma::Config::Index
         
     | 
| 
       85 
87 
     | 
    
         
             
                    def create_repeat_index(gesture:, finger:, direction:, status:)
         
     | 
| 
       86 
88 
     | 
    
         
             
                      Config::Index.new(
         
     | 
| 
       87 
89 
     | 
    
         
             
                        [
         
     | 
| 
         @@ -97,6 +99,7 @@ module Fusuma 
     | 
|
| 
       97 
99 
     | 
    
         
             
                    # @param [Integer] finger
         
     | 
| 
       98 
100 
     | 
    
         
             
                    # @param [String] direction
         
     | 
| 
       99 
101 
     | 
    
         
             
                    # @return [Config::Index]
         
     | 
| 
      
 102 
     | 
    
         
            +
                    #: (gesture: String, finger: Integer, direction: String) -> Fusuma::Config::Index
         
     | 
| 
       100 
103 
     | 
    
         
             
                    def create_oneshot_index(gesture:, finger:, direction:)
         
     | 
| 
       101 
104 
     | 
    
         
             
                      Config::Index.new(
         
     | 
| 
       102 
105 
     | 
    
         
             
                        [
         
     | 
| 
         @@ -109,14 +112,17 @@ module Fusuma 
     | 
|
| 
       109 
112 
     | 
    
         | 
| 
       110 
113 
     | 
    
         
             
                    private
         
     | 
| 
       111 
114 
     | 
    
         | 
| 
      
 115 
     | 
    
         
            +
                    #: (Float) -> bool
         
     | 
| 
       112 
116 
     | 
    
         
             
                    def moved?(repeat_quantity)
         
     | 
| 
       113 
117 
     | 
    
         
             
                      repeat_quantity > 0.3
         
     | 
| 
       114 
118 
     | 
    
         
             
                    end
         
     | 
| 
       115 
119 
     | 
    
         | 
| 
      
 120 
     | 
    
         
            +
                    #: (index: Fusuma::Config::Index, quantity: Float) -> bool
         
     | 
| 
       116 
121 
     | 
    
         
             
                    def enough_oneshot_threshold?(index:, quantity:)
         
     | 
| 
       117 
122 
     | 
    
         
             
                      quantity > threshold(index: index)
         
     | 
| 
       118 
123 
     | 
    
         
             
                    end
         
     | 
| 
       119 
124 
     | 
    
         | 
| 
      
 125 
     | 
    
         
            +
                    #: (index: Fusuma::Config::Index) -> Integer
         
     | 
| 
       120 
126 
     | 
    
         
             
                    def threshold(index:)
         
     | 
| 
       121 
127 
     | 
    
         
             
                      @threshold ||= {}
         
     | 
| 
       122 
128 
     | 
    
         
             
                      @threshold[index.cache_key] ||= begin
         
     | 
| 
         @@ -135,15 +141,18 @@ module Fusuma 
     | 
|
| 
       135 
141 
     | 
    
         
             
                      DOWN = "down"
         
     | 
| 
       136 
142 
     | 
    
         
             
                      UP = "up"
         
     | 
| 
       137 
143 
     | 
    
         | 
| 
      
 144 
     | 
    
         
            +
                      #: (move_x: Integer | Float, move_y: Integer | Float) -> void
         
     | 
| 
       138 
145 
     | 
    
         
             
                      def initialize(move_x:, move_y:)
         
     | 
| 
       139 
146 
     | 
    
         
             
                        @move_x = move_x.to_f
         
     | 
| 
       140 
147 
     | 
    
         
             
                        @move_y = move_y.to_f
         
     | 
| 
       141 
148 
     | 
    
         
             
                      end
         
     | 
| 
       142 
149 
     | 
    
         | 
| 
      
 150 
     | 
    
         
            +
                      #: () -> String
         
     | 
| 
       143 
151 
     | 
    
         
             
                      def to_s
         
     | 
| 
       144 
152 
     | 
    
         
             
                        calc
         
     | 
| 
       145 
153 
     | 
    
         
             
                      end
         
     | 
| 
       146 
154 
     | 
    
         | 
| 
      
 155 
     | 
    
         
            +
                      #: () -> String
         
     | 
| 
       147 
156 
     | 
    
         
             
                      def calc
         
     | 
| 
       148 
157 
     | 
    
         
             
                        if @move_x.abs > @move_y.abs
         
     | 
| 
       149 
158 
     | 
    
         
             
                          @move_x.positive? ? RIGHT : LEFT
         
     | 
| 
         @@ -157,15 +166,18 @@ module Fusuma 
     | 
|
| 
       157 
166 
     | 
    
         | 
| 
       158 
167 
     | 
    
         
             
                    # quantity of gesture
         
     | 
| 
       159 
168 
     | 
    
         
             
                    class Quantity
         
     | 
| 
      
 169 
     | 
    
         
            +
                      #: (move_x: Integer | Float, move_y: Integer | Float) -> void
         
     | 
| 
       160 
170 
     | 
    
         
             
                      def initialize(move_x:, move_y:)
         
     | 
| 
       161 
171 
     | 
    
         
             
                        @x = move_x.to_f.abs
         
     | 
| 
       162 
172 
     | 
    
         
             
                        @y = move_y.to_f.abs
         
     | 
| 
       163 
173 
     | 
    
         
             
                      end
         
     | 
| 
       164 
174 
     | 
    
         | 
| 
      
 175 
     | 
    
         
            +
                      #: () -> Float
         
     | 
| 
       165 
176 
     | 
    
         
             
                      def to_f
         
     | 
| 
       166 
177 
     | 
    
         
             
                        calc.to_f
         
     | 
| 
       167 
178 
     | 
    
         
             
                      end
         
     | 
| 
       168 
179 
     | 
    
         | 
| 
      
 180 
     | 
    
         
            +
                      #: () -> Float
         
     | 
| 
       169 
181 
     | 
    
         
             
                      def calc
         
     | 
| 
       170 
182 
     | 
    
         
             
                        (@x > @y) ? @x.abs : @y.abs
         
     | 
| 
       171 
183 
     | 
    
         
             
                      end
         
     |