fusuma 2.0.0.pre → 2.0.3
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 +50 -11
- data/fusuma.gemspec +5 -6
- data/lib/fusuma.rb +87 -33
- data/lib/fusuma/config.rb +33 -40
- data/lib/fusuma/config/index.rb +34 -8
- data/lib/fusuma/config/searcher.rb +80 -4
- data/lib/fusuma/custom_process.rb +13 -0
- data/lib/fusuma/device.rb +19 -6
- data/lib/fusuma/environment.rb +4 -3
- data/lib/fusuma/hash_support.rb +40 -0
- data/lib/fusuma/libinput_command.rb +10 -15
- data/lib/fusuma/multi_logger.rb +2 -6
- data/lib/fusuma/plugin/base.rb +18 -15
- data/lib/fusuma/plugin/buffers/buffer.rb +3 -2
- data/lib/fusuma/plugin/buffers/gesture_buffer.rb +34 -25
- data/lib/fusuma/plugin/buffers/timer_buffer.rb +3 -3
- data/lib/fusuma/plugin/detectors/detector.rb +26 -5
- data/lib/fusuma/plugin/detectors/pinch_detector.rb +109 -58
- data/lib/fusuma/plugin/detectors/rotate_detector.rb +91 -50
- data/lib/fusuma/plugin/detectors/swipe_detector.rb +93 -56
- data/lib/fusuma/plugin/events/event.rb +5 -4
- data/lib/fusuma/plugin/events/records/context_record.rb +27 -0
- data/lib/fusuma/plugin/events/records/gesture_record.rb +9 -6
- data/lib/fusuma/plugin/events/records/index_record.rb +46 -14
- data/lib/fusuma/plugin/events/records/record.rb +1 -1
- data/lib/fusuma/plugin/events/records/text_record.rb +2 -1
- data/lib/fusuma/plugin/executors/command_executor.rb +21 -4
- data/lib/fusuma/plugin/executors/executor.rb +45 -3
- data/lib/fusuma/plugin/filters/filter.rb +1 -1
- data/lib/fusuma/plugin/filters/libinput_device_filter.rb +6 -7
- data/lib/fusuma/plugin/filters/libinput_timeout_filter.rb +2 -2
- data/lib/fusuma/plugin/inputs/input.rb +20 -7
- data/lib/fusuma/plugin/inputs/libinput_command_input.rb +17 -5
- data/lib/fusuma/plugin/inputs/timer_input.rb +7 -7
- data/lib/fusuma/plugin/manager.rb +22 -29
- data/lib/fusuma/plugin/parsers/libinput_gesture_parser.rb +10 -8
- data/lib/fusuma/plugin/parsers/parser.rb +8 -9
- data/lib/fusuma/string_support.rb +16 -0
- data/lib/fusuma/version.rb +1 -1
- data/spec/helpers/config_helper.rb +20 -0
- data/spec/lib/config/searcher_spec.rb +97 -0
- data/spec/lib/config_spec.rb +112 -0
- data/spec/lib/custom_process_spec.rb +28 -0
- data/spec/lib/device_spec.rb +96 -0
- data/spec/lib/dummy_config.yml +31 -0
- data/spec/lib/fusuma_spec.rb +103 -0
- data/spec/lib/libinput-list-devices_iberianpig-XPS-9360.txt +181 -0
- data/spec/lib/libinput-list-devices_magic_trackpad.txt +51 -0
- data/spec/lib/libinput-list-devices_razer_razer_blade.txt +252 -0
- data/spec/lib/libinput-list-devices_thejinx0r.txt +361 -0
- data/spec/lib/libinput-list-devices_unavailable.txt +36 -0
- data/spec/lib/libinput_command_spec.rb +160 -0
- data/spec/lib/plugin/base_spec.rb +74 -0
- data/spec/lib/plugin/buffers/buffer_spec.rb +80 -0
- data/spec/lib/plugin/buffers/dummy_buffer.rb +20 -0
- data/spec/lib/plugin/buffers/gesture_buffer_spec.rb +172 -0
- data/spec/lib/plugin/detectors/detector_spec.rb +43 -0
- data/spec/lib/plugin/detectors/dummy_detector.rb +24 -0
- data/spec/lib/plugin/detectors/pinch_detector_spec.rb +119 -0
- data/spec/lib/plugin/detectors/rotate_detector_spec.rb +125 -0
- data/spec/lib/plugin/detectors/swipe_detector_spec.rb +118 -0
- data/spec/lib/plugin/events/event_spec.rb +30 -0
- data/spec/lib/plugin/events/records/gesture_record_spec.rb +22 -0
- data/spec/lib/plugin/events/records/record_spec.rb +31 -0
- data/spec/lib/plugin/events/records/text_record_spec.rb +26 -0
- data/spec/lib/plugin/executors/command_executor_spec.rb +57 -0
- data/spec/lib/plugin/executors/executor_spec.rb +160 -0
- data/spec/lib/plugin/filters/filter_spec.rb +92 -0
- data/spec/lib/plugin/filters/libinput_filter_spec.rb +120 -0
- data/spec/lib/plugin/inputs/input_spec.rb +70 -0
- data/spec/lib/plugin/inputs/libinput_command_input_spec.rb +121 -0
- data/spec/lib/plugin/inputs/timer_input_spec.rb +40 -0
- data/spec/lib/plugin/manager_spec.rb +27 -0
- data/spec/lib/plugin/parsers/parser_spec.rb +45 -0
- data/spec/spec_helper.rb +20 -0
- metadata +84 -38
- data/.github/FUNDING.yml +0 -8
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -32
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
- data/.github/pull_request_template.md +0 -9
- data/.github/stale.yml +0 -18
- data/.gitignore +0 -17
- data/.reek.yml +0 -96
- data/.rspec +0 -2
- data/.rubocop.yml +0 -40
- data/.rubocop_todo.yml +0 -40
- data/.travis.yml +0 -11
- data/CHANGELOG.md +0 -456
- data/CODE_OF_CONDUCT.md +0 -74
- data/CONTRIBUTING.md +0 -72
- data/Gemfile +0 -18
- data/Rakefile +0 -15
@@ -6,7 +6,7 @@ module Fusuma
|
|
6
6
|
# Search config.yml
|
7
7
|
class Searcher
|
8
8
|
def initialize
|
9
|
-
@cache
|
9
|
+
@cache = nil
|
10
10
|
end
|
11
11
|
|
12
12
|
# @param index [Index]
|
@@ -31,9 +31,25 @@ module Fusuma
|
|
31
31
|
value
|
32
32
|
end
|
33
33
|
|
34
|
+
def search_with_context(index, location:, context:)
|
35
|
+
return nil if location.nil?
|
36
|
+
|
37
|
+
return search(index, location: location[0]) if context == {}
|
38
|
+
|
39
|
+
new_location = location.find do |conf|
|
40
|
+
search(index, location: conf) if conf[:context] == context
|
41
|
+
end
|
42
|
+
search(index, location: new_location)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param index [Index]
|
46
|
+
# @param location [Hash]
|
47
|
+
# @return [NilClass]
|
48
|
+
# @return [Hash]
|
49
|
+
# @return [Object]
|
34
50
|
def search_with_cache(index, location:)
|
35
|
-
cache([index.cache_key, Searcher.skip?, Searcher.fallback?]) do
|
36
|
-
|
51
|
+
cache([index.cache_key, Searcher.context, Searcher.skip?, Searcher.fallback?]) do
|
52
|
+
search_with_context(index, location: location, context: Searcher.context)
|
37
53
|
end
|
38
54
|
end
|
39
55
|
|
@@ -56,12 +72,72 @@ module Fusuma
|
|
56
72
|
def next_location_cadidates(location, key)
|
57
73
|
[
|
58
74
|
location[key.symbol],
|
59
|
-
Searcher.fallback? && key.fallback && location[key.fallback],
|
60
75
|
Searcher.skip? && key.skippable && location
|
61
76
|
].compact
|
62
77
|
end
|
63
78
|
|
64
79
|
class << self
|
80
|
+
# @return [Hash]
|
81
|
+
def conditions(&block)
|
82
|
+
{
|
83
|
+
nothing: -> { block.call },
|
84
|
+
skip: -> { Config::Searcher.skip { block.call } }
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
# Execute block with specified conditions
|
89
|
+
# @param conidtion [Symbol]
|
90
|
+
# @return [Object]
|
91
|
+
def with_condition(condition, &block)
|
92
|
+
conditions(&block)[condition].call
|
93
|
+
end
|
94
|
+
|
95
|
+
# Execute block with all conditions
|
96
|
+
# @return [Array<Symbol, Object>]
|
97
|
+
def find_condition(&block)
|
98
|
+
conditions(&block).find do |c, l|
|
99
|
+
result = l.call
|
100
|
+
return [c, result] if result
|
101
|
+
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Search with context from load_streamed Config
|
107
|
+
# @param context [Hash]
|
108
|
+
# @return [Object]
|
109
|
+
def with_context(context, &block)
|
110
|
+
@context = context || {}
|
111
|
+
result = block.call
|
112
|
+
@context = {}
|
113
|
+
result
|
114
|
+
end
|
115
|
+
|
116
|
+
# Return a matching context from config
|
117
|
+
# @params request_context [Hash]
|
118
|
+
# @return [Hash]
|
119
|
+
def find_context(request_context, &block)
|
120
|
+
# Search in blocks in the following order.
|
121
|
+
# 1. complete match config[:context] == request_context
|
122
|
+
# 2. partial match config[:context] =~ request_context
|
123
|
+
# 3. no context
|
124
|
+
Config.instance.keymap.each do |config|
|
125
|
+
next unless config[:context] == request_context
|
126
|
+
return config[:context] if with_context(config[:context]) { block.call }
|
127
|
+
end
|
128
|
+
if request_context.keys.size > 1
|
129
|
+
Config.instance.keymap.each do |config|
|
130
|
+
next if config[:context].nil?
|
131
|
+
|
132
|
+
next unless config[:context].all? { |k, v| request_context[k] == v }
|
133
|
+
return config[:context] if with_context(config[:context]) { block.call }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
return {} if with_context({}) { block.call }
|
137
|
+
end
|
138
|
+
|
139
|
+
attr_reader :context
|
140
|
+
|
65
141
|
def fallback?
|
66
142
|
@fallback
|
67
143
|
end
|
data/lib/fusuma/device.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative './multi_logger'
|
4
|
-
require_relative './libinput_command
|
4
|
+
require_relative './libinput_command'
|
5
5
|
|
6
6
|
module Fusuma
|
7
7
|
# detect input device
|
8
8
|
class Device
|
9
|
-
attr_reader :available
|
10
|
-
attr_reader :name
|
11
|
-
attr_reader :id
|
9
|
+
attr_reader :id, :name, :capabilities, :available
|
12
10
|
|
13
|
-
def initialize(id: nil, name: nil, available: nil)
|
11
|
+
def initialize(id: nil, name: nil, capabilities: nil, available: nil)
|
14
12
|
@id = id
|
15
13
|
@name = name
|
14
|
+
@capabilities = capabilities
|
16
15
|
@available = available
|
17
16
|
end
|
18
17
|
|
@@ -24,6 +23,8 @@ module Fusuma
|
|
24
23
|
@id = v
|
25
24
|
when :name
|
26
25
|
@name = v
|
26
|
+
when :capabilities
|
27
|
+
@capabilities = v
|
27
28
|
when :available
|
28
29
|
@available = v
|
29
30
|
end
|
@@ -31,9 +32,13 @@ module Fusuma
|
|
31
32
|
end
|
32
33
|
|
33
34
|
class << self
|
35
|
+
# Return devices
|
36
|
+
# sort devices by capabilities of gesture
|
34
37
|
# @return [Array]
|
35
38
|
def all
|
36
|
-
@all ||= fetch_devices
|
39
|
+
@all ||= fetch_devices.partition do |d|
|
40
|
+
d.capabilities.match?(/gesture/)
|
41
|
+
end.flatten
|
37
42
|
end
|
38
43
|
|
39
44
|
# @raise [SystemExit]
|
@@ -104,6 +109,8 @@ module Fusuma
|
|
104
109
|
{ id: id }
|
105
110
|
elsif (name = name_from(line))
|
106
111
|
{ name: name }
|
112
|
+
elsif (capabilities = capabilities_from(line))
|
113
|
+
{ capabilities: capabilities }
|
107
114
|
elsif (available = available_from(line))
|
108
115
|
{ available: available }
|
109
116
|
else
|
@@ -123,6 +130,12 @@ module Fusuma
|
|
123
130
|
end
|
124
131
|
end
|
125
132
|
|
133
|
+
def capabilities_from(line)
|
134
|
+
line.match('^Capabilities:[[:space:]]*') do |m|
|
135
|
+
m.post_match.strip
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
126
139
|
def available_from(line)
|
127
140
|
# NOTE: is natural scroll available?
|
128
141
|
if line =~ /^Nat.scrolling: /
|
data/lib/fusuma/environment.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './version
|
4
|
-
require_relative './libinput_command
|
5
|
-
require_relative './multi_logger
|
3
|
+
require_relative './version'
|
4
|
+
require_relative './libinput_command'
|
5
|
+
require_relative './multi_logger'
|
6
6
|
|
7
7
|
module Fusuma
|
8
8
|
# Output Environment information
|
@@ -20,6 +20,7 @@ module Fusuma
|
|
20
20
|
libinput_command = Plugin::Inputs::LibinputCommandInput.new.command
|
21
21
|
MultiLogger.info "Fusuma: #{VERSION}"
|
22
22
|
MultiLogger.info "libinput: #{libinput_command.version}"
|
23
|
+
MultiLogger.info "ruby #{ RUBY_VERSION }p#{ RUBY_PATCHLEVEL }"
|
23
24
|
MultiLogger.info "OS: #{`uname -rsv`}".strip
|
24
25
|
MultiLogger.info "Distribution: #{`cat /etc/issue`}".strip
|
25
26
|
MultiLogger.info "Desktop session: #{`echo $DESKTOP_SESSION $XDG_SESSION_TYPE`}".strip
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Patch to hash
|
4
|
+
class Hash
|
5
|
+
# activesupport-4.1.1/lib/active_support/core_ext/hash/keys.rb
|
6
|
+
def deep_symbolize_keys
|
7
|
+
deep_transform_keys do |key|
|
8
|
+
key.to_sym
|
9
|
+
rescue StandardError
|
10
|
+
key
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def deep_transform_keys(&block)
|
15
|
+
result = {}
|
16
|
+
each do |key, value|
|
17
|
+
result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
|
18
|
+
end
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
# activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb
|
23
|
+
def deep_transform_values(&block)
|
24
|
+
_deep_transform_values_in_object(self, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Support methods for deep transforming nested hashes and arrays.
|
30
|
+
def _deep_transform_values_in_object(object, &block)
|
31
|
+
case object
|
32
|
+
when Hash
|
33
|
+
object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
|
34
|
+
when Array
|
35
|
+
object.map { |e| _deep_transform_values_in_object(e, &block) }
|
36
|
+
else
|
37
|
+
yield(object)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'open3'
|
4
4
|
|
5
5
|
module Fusuma
|
6
6
|
# Execute libinput command
|
@@ -30,24 +30,19 @@ module Fusuma
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# @yieldparam [String] gives a line in libinput list-devices output to the block
|
33
|
-
def list_devices
|
33
|
+
def list_devices(&block)
|
34
34
|
cmd = list_devices_command
|
35
35
|
MultiLogger.debug(list_devices: cmd)
|
36
|
-
|
36
|
+
i, o, e, _w = Open3.popen3(cmd)
|
37
|
+
MultiLogger.error(e.read) if o.eof?
|
37
38
|
i.close
|
38
|
-
|
39
|
-
|
40
|
-
[i, o, e].each { |io| io.close unless io.closed? }
|
41
|
-
Process.waitpid(p)
|
39
|
+
e.close
|
40
|
+
o.each(&block)
|
42
41
|
end
|
43
42
|
|
44
|
-
# @return [
|
45
|
-
def debug_events
|
46
|
-
@debug_events ||=
|
47
|
-
_p, i, o, _e = POSIX::Spawn.popen4(debug_events_with_options)
|
48
|
-
i.close
|
49
|
-
o
|
50
|
-
end
|
43
|
+
# @return [Integer] return a latest line libinput debug-events
|
44
|
+
def debug_events(writer)
|
45
|
+
@debug_events ||= Process.spawn(debug_events_with_options, out: writer, in: '/dev/null')
|
51
46
|
end
|
52
47
|
|
53
48
|
# @return [String] command
|
@@ -60,7 +55,7 @@ module Fusuma
|
|
60
55
|
elsif which('libinput-list-devices')
|
61
56
|
'libinput-list-devices --version'
|
62
57
|
else
|
63
|
-
MultiLogger.error 'install libinput-tools'
|
58
|
+
MultiLogger.error 'Please install libinput-tools'
|
64
59
|
exit 1
|
65
60
|
end
|
66
61
|
end
|
data/lib/fusuma/multi_logger.rb
CHANGED
@@ -12,15 +12,11 @@ module Fusuma
|
|
12
12
|
attr_accessor :debug_mode
|
13
13
|
|
14
14
|
def initialize
|
15
|
-
super(
|
16
|
-
@err_logger = Logger.new(
|
15
|
+
super($stdout)
|
16
|
+
@err_logger = Logger.new($stderr)
|
17
17
|
@debug_mode = false
|
18
18
|
end
|
19
19
|
|
20
|
-
def info(msg)
|
21
|
-
super(msg)
|
22
|
-
end
|
23
|
-
|
24
20
|
def debug(msg)
|
25
21
|
return unless debug_mode?
|
26
22
|
|
data/lib/fusuma/plugin/base.rb
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './manager
|
4
|
-
require_relative '../config
|
3
|
+
require_relative './manager'
|
4
|
+
require_relative '../config'
|
5
|
+
require_relative '../custom_process'
|
5
6
|
|
6
7
|
module Fusuma
|
7
8
|
module Plugin
|
8
9
|
# Create a Plugin Class with extending this class
|
9
10
|
class Base
|
11
|
+
include CustomProcess
|
10
12
|
# when inherited from subclass
|
11
13
|
def self.inherited(subclass)
|
14
|
+
super
|
12
15
|
subclass_path = caller_locations(1..1).first.path
|
13
16
|
Manager.add(plugin_class: subclass, plugin_path: subclass_path)
|
14
17
|
end
|
15
18
|
|
16
|
-
# get
|
17
|
-
# @
|
18
|
-
# [Vectors::Vector]
|
19
|
-
# @return [Array]
|
19
|
+
# get subclasses
|
20
|
+
# @return [Array<Class>]
|
20
21
|
def self.plugins
|
21
22
|
Manager.plugins[name]
|
22
23
|
end
|
@@ -33,19 +34,21 @@ module Fusuma
|
|
33
34
|
|
34
35
|
return params unless key
|
35
36
|
|
36
|
-
|
37
|
-
|
37
|
+
@config_params ||= {}
|
38
|
+
@config_params["#{base.cache_key},#{key}"] ||=
|
39
|
+
params.fetch(key, nil).tap do |val|
|
40
|
+
next if val.nil?
|
38
41
|
|
39
|
-
|
40
|
-
|
42
|
+
# NOTE: Type checking for config.yml
|
43
|
+
param_types = Array(config_param_types.fetch(key))
|
41
44
|
|
42
|
-
|
45
|
+
next if param_types.any? { |klass| val.is_a?(klass) }
|
43
46
|
|
44
|
-
|
45
|
-
|
47
|
+
MultiLogger.error('Please fix config.yml.')
|
48
|
+
MultiLogger.error(":#{base.keys.map(&:symbol)
|
46
49
|
.join(' => :')} => :#{key} should be #{param_types.join(' OR ')}.")
|
47
|
-
|
48
|
-
|
50
|
+
exit 1
|
51
|
+
end
|
49
52
|
end
|
50
53
|
|
51
54
|
def config_index
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../base
|
3
|
+
require_relative '../base'
|
4
4
|
|
5
5
|
module Fusuma
|
6
6
|
module Plugin
|
@@ -8,6 +8,7 @@ module Fusuma
|
|
8
8
|
# buffer events and output
|
9
9
|
class Buffer < Base
|
10
10
|
def initialize(*args)
|
11
|
+
super()
|
11
12
|
@events = Array.new(*args)
|
12
13
|
end
|
13
14
|
|
@@ -15,7 +16,7 @@ module Fusuma
|
|
15
16
|
|
16
17
|
# @return [String]
|
17
18
|
def type
|
18
|
-
self.class.name.underscore.split('/').last.gsub('_buffer', '')
|
19
|
+
@type ||= self.class.name.underscore.split('/').last.gsub('_buffer', '')
|
19
20
|
end
|
20
21
|
|
21
22
|
# @param event [Event]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './buffer
|
3
|
+
require_relative './buffer'
|
4
4
|
|
5
5
|
module Fusuma
|
6
6
|
module Plugin
|
@@ -8,17 +8,17 @@ module Fusuma
|
|
8
8
|
# manage events and generate command
|
9
9
|
class GestureBuffer < Buffer
|
10
10
|
DEFAULT_SOURCE = 'libinput_gesture_parser'
|
11
|
-
DEFAULT_SECONDS_TO_KEEP =
|
11
|
+
DEFAULT_SECONDS_TO_KEEP = 100
|
12
12
|
|
13
13
|
def config_param_types
|
14
14
|
{
|
15
|
-
|
16
|
-
|
15
|
+
source: [String],
|
16
|
+
seconds_to_keep: [Float, Integer]
|
17
17
|
}
|
18
18
|
end
|
19
19
|
|
20
20
|
# @param event [Event]
|
21
|
-
# @return [Buffer,
|
21
|
+
# @return [Buffer, FalseClass]
|
22
22
|
def buffer(event)
|
23
23
|
# TODO: buffering events into buffer plugins
|
24
24
|
# - gesture event buffer
|
@@ -26,16 +26,13 @@ module Fusuma
|
|
26
26
|
# - other event buffer
|
27
27
|
return if event&.tag != source
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
self
|
32
|
-
else
|
33
|
-
clear
|
34
|
-
false
|
35
|
-
end
|
29
|
+
@events.push(event)
|
30
|
+
self
|
36
31
|
end
|
37
32
|
|
38
33
|
def clear_expired(current_time: Time.now)
|
34
|
+
clear if ended?
|
35
|
+
|
39
36
|
@seconds_to_keep ||= (config_params(:seconds_to_keep) || DEFAULT_SECONDS_TO_KEEP)
|
40
37
|
@events.each do |e|
|
41
38
|
break if current_time - e.time < @seconds_to_keep
|
@@ -46,17 +43,28 @@ module Fusuma
|
|
46
43
|
end
|
47
44
|
end
|
48
45
|
|
46
|
+
def ended?
|
47
|
+
return false if empty?
|
48
|
+
|
49
|
+
@events.last.record.status == 'end'
|
50
|
+
end
|
51
|
+
|
49
52
|
# @param attr [Symbol]
|
50
53
|
# @return [Float]
|
51
54
|
def sum_attrs(attr)
|
52
|
-
|
53
|
-
|
55
|
+
updating_events.map do |gesture_event|
|
56
|
+
gesture_event.record.delta[attr].to_f
|
57
|
+
end.inject(:+)
|
58
|
+
end
|
59
|
+
|
60
|
+
def updating_events
|
61
|
+
@events.select { |e| e.record.status == 'update' }
|
54
62
|
end
|
55
63
|
|
56
64
|
# @param attr [Symbol]
|
57
65
|
# @return [Float]
|
58
66
|
def avg_attrs(attr)
|
59
|
-
sum_attrs(attr).to_f /
|
67
|
+
sum_attrs(attr).to_f / updating_events.length
|
60
68
|
end
|
61
69
|
|
62
70
|
# return [Integer]
|
@@ -76,20 +84,21 @@ module Fusuma
|
|
76
84
|
@events.empty?
|
77
85
|
end
|
78
86
|
|
79
|
-
def select_by_events
|
80
|
-
return enum_for(:
|
87
|
+
def select_by_events(&block)
|
88
|
+
return enum_for(:select_by_events) unless block_given?
|
81
89
|
|
82
|
-
events = @events.select
|
90
|
+
events = @events.select(&block)
|
83
91
|
self.class.new events
|
84
92
|
end
|
85
93
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
94
|
+
def select_from_last_begin
|
95
|
+
return self if empty?
|
96
|
+
|
97
|
+
index_from_last = @events.reverse.find_index { |e| e.record.status == 'begin' }
|
98
|
+
return GestureBuffer.new([]) if index_from_last.nil?
|
99
|
+
|
100
|
+
index_last_begin = events.length - index_from_last - 1
|
101
|
+
GestureBuffer.new(@events[index_last_begin..-1])
|
93
102
|
end
|
94
103
|
end
|
95
104
|
end
|