fusuma 2.0.0.pre → 2.0.0.pre2
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/.rubocop.yml +8 -5
- data/.rubocop_todo.yml +34 -19
- data/.solargraph.yml +16 -0
- data/.travis.yml +1 -3
- data/CHANGELOG.md +1 -1
- data/Gemfile +6 -1
- data/README.md +43 -5
- data/fusuma.gemspec +3 -2
- 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 +78 -4
- data/lib/fusuma/custom_process.rb +13 -0
- data/lib/fusuma/device.rb +19 -6
- data/lib/fusuma/environment.rb +3 -3
- data/lib/fusuma/hash_support.rb +40 -0
- data/lib/fusuma/libinput_command.rb +8 -8
- 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 +20 -3
- 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 +19 -7
- data/lib/fusuma/plugin/inputs/libinput_command_input.rb +10 -5
- data/lib/fusuma/plugin/inputs/timer_input.rb +7 -7
- data/lib/fusuma/plugin/manager.rb +10 -28
- 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
- metadata +13 -8
@@ -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
|
@@ -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
|
@@ -12,8 +12,8 @@ module Fusuma
|
|
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
|
|
@@ -1,13 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../base
|
4
|
-
require_relative '../events/event
|
3
|
+
require_relative '../base'
|
4
|
+
require_relative '../events/event'
|
5
5
|
|
6
6
|
module Fusuma
|
7
7
|
module Plugin
|
8
8
|
module Detectors
|
9
9
|
# Inherite this base
|
10
10
|
class Detector < Base
|
11
|
+
# @return [Array<String>]
|
12
|
+
def sources
|
13
|
+
@source ||= self.class.const_get('SOURCES')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Always watch buffers and detect them or not
|
17
|
+
# @return [TrueClass,FalseClass]
|
18
|
+
def watch?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
11
22
|
# @param _buffers [Array<Buffer>]
|
12
23
|
# @return [Event] if event is detected
|
13
24
|
# @return [NilClass] if event is NOT detected
|
@@ -21,7 +32,7 @@ module Fusuma
|
|
21
32
|
# @return [Events::Event]
|
22
33
|
def create_event(record:)
|
23
34
|
@last_time = Time.now
|
24
|
-
Events::Event.new(time:
|
35
|
+
Events::Event.new(time: @last_time, tag: tag, record: record)
|
25
36
|
end
|
26
37
|
|
27
38
|
def last_time
|
@@ -33,11 +44,21 @@ module Fusuma
|
|
33
44
|
end
|
34
45
|
|
35
46
|
def tag
|
36
|
-
self.class.
|
47
|
+
self.class.tag
|
37
48
|
end
|
38
49
|
|
39
50
|
def type
|
40
|
-
self.class.
|
51
|
+
self.class.type
|
52
|
+
end
|
53
|
+
|
54
|
+
class << self
|
55
|
+
def tag
|
56
|
+
name.split('Detectors::').last.underscore
|
57
|
+
end
|
58
|
+
|
59
|
+
def type(tag_name = tag)
|
60
|
+
tag_name.gsub('_detector', '')
|
61
|
+
end
|
41
62
|
end
|
42
63
|
end
|
43
64
|
end
|
@@ -1,50 +1,111 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './detector
|
3
|
+
require_relative './detector'
|
4
4
|
|
5
5
|
module Fusuma
|
6
6
|
module Plugin
|
7
7
|
module Detectors
|
8
8
|
class PinchDetector < Detector
|
9
|
+
SOURCES = ['gesture'].freeze
|
9
10
|
BUFFER_TYPE = 'gesture'
|
10
11
|
GESTURE_RECORD_TYPE = 'pinch'
|
11
12
|
|
12
13
|
FINGERS = [2, 3, 4].freeze
|
13
|
-
BASE_THERESHOLD =
|
14
|
-
BASE_INTERVAL = 0.1
|
14
|
+
BASE_THERESHOLD = 1.3
|
15
15
|
|
16
16
|
# @param buffers [Array<Buffer>]
|
17
|
-
# @return [Event] if event is detected
|
17
|
+
# @return [Events::Event] if event is detected
|
18
18
|
# @return [NilClass] if event is NOT detected
|
19
19
|
def detect(buffers)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
20
|
+
gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
|
21
|
+
.select_from_last_begin
|
22
|
+
.select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
|
23
|
+
|
24
|
+
updating_events = gesture_buffer.updating_events
|
25
|
+
return if updating_events.empty?
|
26
|
+
|
27
|
+
finger = gesture_buffer.finger
|
28
|
+
|
29
|
+
status = case gesture_buffer.events.last.record.status
|
30
|
+
when 'end'
|
31
|
+
'end'
|
32
|
+
when 'update'
|
33
|
+
if updating_events.length == 1
|
34
|
+
'begin'
|
35
|
+
else
|
36
|
+
'update'
|
37
|
+
end
|
38
|
+
else
|
39
|
+
gesture_buffer.events.last.record.status
|
40
|
+
end
|
41
|
+
|
42
|
+
prev_event, event = if status == 'end'
|
43
|
+
[
|
44
|
+
gesture_buffer.events[-3],
|
45
|
+
gesture_buffer.events[-2]
|
46
|
+
]
|
47
|
+
else
|
48
|
+
[
|
49
|
+
gesture_buffer.events[-2],
|
50
|
+
gesture_buffer.events[-1]
|
51
|
+
]
|
52
|
+
end
|
53
|
+
delta = event.record.delta
|
54
|
+
prev_delta = prev_event.record.delta
|
55
|
+
|
56
|
+
repeat_direction = Direction.new(target: delta.zoom, base: (prev_delta&.zoom || 1.0)).to_s
|
57
|
+
# repeat_quantity = Quantity.new(target: delta.zoom, base: (prev_delta&.zoom || 1.0)).to_f
|
58
|
+
|
59
|
+
repeat_index = create_repeat_index(gesture: type, finger: finger,
|
60
|
+
direction: repeat_direction,
|
61
|
+
status: status)
|
62
|
+
if status == 'update'
|
63
|
+
return unless moved?(prev_event, event)
|
64
|
+
|
65
|
+
avg_zoom = gesture_buffer.avg_attrs(:zoom)
|
66
|
+
first_zoom = updating_events.first.record.delta.zoom
|
67
|
+
|
68
|
+
oneshot_quantity = Quantity.new(target: avg_zoom, base: first_zoom).to_f
|
69
|
+
oneshot_direction = Direction.new(target: avg_zoom, base: first_zoom).to_s
|
70
|
+
oneshot_index = create_oneshot_index(gesture: type, finger: finger,
|
71
|
+
direction: oneshot_direction)
|
72
|
+
if enough_oneshot_threshold?(index: oneshot_index, quantity: oneshot_quantity)
|
73
|
+
return [
|
74
|
+
create_event(record: Events::Records::IndexRecord.new(
|
75
|
+
index: oneshot_index, trigger: :oneshot, args: delta.to_h
|
76
|
+
)),
|
77
|
+
create_event(record: Events::Records::IndexRecord.new(
|
78
|
+
index: repeat_index, trigger: :repeat, args: delta.to_h
|
79
|
+
))
|
80
|
+
]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
create_event(record: Events::Records::IndexRecord.new(
|
84
|
+
index: repeat_index, trigger: :repeat, args: delta.to_h
|
85
|
+
))
|
86
|
+
end
|
39
87
|
|
40
|
-
|
88
|
+
# @param [String] gesture
|
89
|
+
# @param [Integer] finger
|
90
|
+
# @param [String] direction
|
91
|
+
# @param [String] status
|
92
|
+
# @return [Config::Index]
|
93
|
+
def create_repeat_index(gesture:, finger:, direction:, status:)
|
94
|
+
Config::Index.new(
|
95
|
+
[
|
96
|
+
Config::Index::Key.new(gesture),
|
97
|
+
Config::Index::Key.new(finger.to_i),
|
98
|
+
Config::Index::Key.new(direction, skippable: true),
|
99
|
+
Config::Index::Key.new(status)
|
100
|
+
]
|
101
|
+
)
|
41
102
|
end
|
42
103
|
|
43
104
|
# @param [String] gesture
|
44
105
|
# @param [Integer] finger
|
45
106
|
# @param [String] direction
|
46
107
|
# @return [Config::Index]
|
47
|
-
def
|
108
|
+
def create_oneshot_index(gesture:, finger:, direction:)
|
48
109
|
Config::Index.new(
|
49
110
|
[
|
50
111
|
Config::Index::Key.new(gesture),
|
@@ -56,41 +117,25 @@ module Fusuma
|
|
56
117
|
|
57
118
|
private
|
58
119
|
|
59
|
-
def
|
60
|
-
|
120
|
+
def moved?(prev_event, event)
|
121
|
+
zoom_delta = (event.record.delta.zoom - prev_event.record.delta.zoom).abs
|
122
|
+
updating_time = (event.time - prev_event.time) * 100
|
123
|
+
zoom_delta / updating_time > 0.01
|
61
124
|
end
|
62
125
|
|
63
|
-
def
|
126
|
+
def enough_oneshot_threshold?(index:, quantity:)
|
64
127
|
quantity >= threshold(index: index)
|
65
128
|
end
|
66
129
|
|
67
|
-
def enough_interval?(index:)
|
68
|
-
return true if first_time?
|
69
|
-
return true if (Time.now - last_time) > interval_time(index: index)
|
70
|
-
|
71
|
-
false
|
72
|
-
end
|
73
|
-
|
74
130
|
def threshold(index:)
|
75
131
|
@threshold ||= {}
|
76
132
|
@threshold[index.cache_key] ||= begin
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
def interval_time(index:)
|
86
|
-
@interval_time ||= {}
|
87
|
-
@interval_time[index.cache_key] ||= begin
|
88
|
-
keys_specific = Config::Index.new [*index.keys, 'interval']
|
89
|
-
keys_global = Config::Index.new ['interval', type]
|
90
|
-
config_value = Config.search(keys_specific) ||
|
91
|
-
Config.search(keys_global) || 1
|
92
|
-
BASE_INTERVAL * config_value
|
93
|
-
end
|
133
|
+
keys_specific = Config::Index.new [*index.keys, 'threshold']
|
134
|
+
keys_global = Config::Index.new ['threshold', type]
|
135
|
+
config_value = Config.search(keys_specific) ||
|
136
|
+
Config.search(keys_global) || 1
|
137
|
+
BASE_THERESHOLD * config_value
|
138
|
+
end
|
94
139
|
end
|
95
140
|
|
96
141
|
# direction of gesture
|
@@ -98,8 +143,9 @@ module Fusuma
|
|
98
143
|
IN = 'in'
|
99
144
|
OUT = 'out'
|
100
145
|
|
101
|
-
def initialize(
|
102
|
-
@
|
146
|
+
def initialize(target:, base:)
|
147
|
+
@target = target.to_f
|
148
|
+
@base = base.to_f
|
103
149
|
end
|
104
150
|
|
105
151
|
def to_s
|
@@ -107,7 +153,7 @@ module Fusuma
|
|
107
153
|
end
|
108
154
|
|
109
155
|
def calc
|
110
|
-
if @
|
156
|
+
if @target > @base
|
111
157
|
IN
|
112
158
|
else
|
113
159
|
OUT
|
@@ -117,8 +163,9 @@ module Fusuma
|
|
117
163
|
|
118
164
|
# quantity of gesture
|
119
165
|
class Quantity
|
120
|
-
def initialize(
|
121
|
-
@
|
166
|
+
def initialize(target:, base:)
|
167
|
+
@target = target.to_f
|
168
|
+
@base = base.to_f
|
122
169
|
end
|
123
170
|
|
124
171
|
def to_f
|
@@ -126,7 +173,11 @@ module Fusuma
|
|
126
173
|
end
|
127
174
|
|
128
175
|
def calc
|
129
|
-
|
176
|
+
if @target > @base
|
177
|
+
@target / @base
|
178
|
+
else
|
179
|
+
@base / @target
|
180
|
+
end
|
130
181
|
end
|
131
182
|
end
|
132
183
|
end
|
@@ -1,47 +1,106 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './detector
|
3
|
+
require_relative './detector'
|
4
4
|
|
5
5
|
module Fusuma
|
6
6
|
module Plugin
|
7
7
|
module Detectors
|
8
8
|
class RotateDetector < Detector
|
9
|
+
SOURCES = ['gesture'].freeze
|
9
10
|
BUFFER_TYPE = 'gesture'
|
10
11
|
GESTURE_RECORD_TYPE = 'pinch'
|
11
12
|
|
12
13
|
FINGERS = [2, 3, 4].freeze
|
13
14
|
BASE_THERESHOLD = 0.5
|
14
|
-
BASE_INTERVAL = 0.1
|
15
15
|
|
16
16
|
# @param buffers [Array<Buffer>]
|
17
|
-
# @return [Event] if event is detected
|
17
|
+
# @return [Events::Event] if event is detected
|
18
18
|
# @return [NilClass] if event is NOT detected
|
19
19
|
def detect(buffers)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
20
|
+
gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
|
21
|
+
.select_from_last_begin
|
22
|
+
.select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
|
23
|
+
|
24
|
+
updating_events = gesture_buffer.updating_events
|
25
|
+
return if updating_events.empty?
|
26
|
+
|
27
|
+
updating_time = 100 * (updating_events.last.time - updating_events.first.time)
|
28
|
+
oneshot_angle = gesture_buffer.sum_attrs(:rotate) / updating_time
|
29
|
+
|
30
|
+
return if updating_events.empty?
|
31
|
+
|
32
|
+
finger = gesture_buffer.finger
|
33
|
+
|
34
|
+
status = case gesture_buffer.events.last.record.status
|
35
|
+
when 'end'
|
36
|
+
'end'
|
37
|
+
when 'update'
|
38
|
+
if updating_events.length == 1
|
39
|
+
'begin'
|
40
|
+
else
|
41
|
+
'update'
|
42
|
+
end
|
43
|
+
else
|
44
|
+
gesture_buffer.events.last.record.status
|
45
|
+
end
|
46
|
+
|
47
|
+
delta = if status == 'end'
|
48
|
+
gesture_buffer.events[-2].record.delta
|
49
|
+
else
|
50
|
+
gesture_buffer.events.last.record.delta
|
51
|
+
end
|
52
|
+
|
53
|
+
repeat_direction = Direction.new(angle: delta.rotate).to_s
|
54
|
+
repeat_quantity = Quantity.new(angle: delta.rotate).to_f
|
55
|
+
|
56
|
+
repeat_index = create_repeat_index(gesture: type, finger: finger,
|
57
|
+
direction: repeat_direction,
|
58
|
+
status: status)
|
59
|
+
|
60
|
+
if status == 'update'
|
61
|
+
return unless moved?(repeat_quantity)
|
62
|
+
|
63
|
+
oneshot_direction = Direction.new(angle: oneshot_angle).to_s
|
64
|
+
oneshot_quantity = Quantity.new(angle: oneshot_angle).to_f
|
65
|
+
oneshot_index = create_oneshot_index(gesture: type, finger: finger,
|
66
|
+
direction: oneshot_direction)
|
67
|
+
if enough_oneshot_threshold?(index: oneshot_index, quantity: oneshot_quantity)
|
68
|
+
return [
|
69
|
+
create_event(record: Events::Records::IndexRecord.new(
|
70
|
+
index: oneshot_index, trigger: :oneshot, args: delta.to_h
|
71
|
+
)),
|
72
|
+
create_event(record: Events::Records::IndexRecord.new(
|
73
|
+
index: repeat_index, trigger: :repeat, args: delta.to_h
|
74
|
+
))
|
75
|
+
]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
create_event(record: Events::Records::IndexRecord.new(
|
79
|
+
index: repeat_index, trigger: :repeat, args: delta.to_h
|
80
|
+
))
|
81
|
+
end
|
36
82
|
|
37
|
-
|
83
|
+
# @param [String] gesture
|
84
|
+
# @param [Integer] finger
|
85
|
+
# @param [String] direction
|
86
|
+
# @param [String] status
|
87
|
+
# @return [Config::Index]
|
88
|
+
def create_repeat_index(gesture:, finger:, direction:, status:)
|
89
|
+
Config::Index.new(
|
90
|
+
[
|
91
|
+
Config::Index::Key.new(gesture),
|
92
|
+
Config::Index::Key.new(finger.to_i),
|
93
|
+
Config::Index::Key.new(direction),
|
94
|
+
Config::Index::Key.new(status)
|
95
|
+
]
|
96
|
+
)
|
38
97
|
end
|
39
98
|
|
40
99
|
# @param [String] gesture
|
41
100
|
# @param [Integer] finger
|
42
101
|
# @param [String] direction
|
43
102
|
# @return [Config::Index]
|
44
|
-
def
|
103
|
+
def create_oneshot_index(gesture:, finger:, direction:)
|
45
104
|
Config::Index.new(
|
46
105
|
[
|
47
106
|
Config::Index::Key.new(gesture),
|
@@ -53,41 +112,23 @@ module Fusuma
|
|
53
112
|
|
54
113
|
private
|
55
114
|
|
56
|
-
def
|
57
|
-
|
115
|
+
def moved?(repeat_quantity)
|
116
|
+
repeat_quantity > 0.2
|
58
117
|
end
|
59
118
|
|
60
|
-
def
|
119
|
+
def enough_oneshot_threshold?(index:, quantity:)
|
61
120
|
quantity > threshold(index: index)
|
62
121
|
end
|
63
122
|
|
64
|
-
def enough_interval?(index:)
|
65
|
-
return true if first_time?
|
66
|
-
return true if (Time.now - last_time) > interval_time(index: index)
|
67
|
-
|
68
|
-
false
|
69
|
-
end
|
70
|
-
|
71
123
|
def threshold(index:)
|
72
124
|
@threshold ||= {}
|
73
125
|
@threshold[index.cache_key] ||= begin
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
def interval_time(index:)
|
83
|
-
@interval_time ||= {}
|
84
|
-
@interval_time[index.cache_key] ||= begin
|
85
|
-
keys_specific = Config::Index.new [*index.keys, 'interval']
|
86
|
-
keys_global = Config::Index.new ['interval', type]
|
87
|
-
config_value = Config.search(keys_specific) ||
|
88
|
-
Config.search(keys_global) || 1
|
89
|
-
BASE_INTERVAL * config_value
|
90
|
-
end
|
126
|
+
keys_specific = Config::Index.new [*index.keys, 'threshold']
|
127
|
+
keys_global = Config::Index.new ['threshold', type]
|
128
|
+
config_value = Config.search(keys_specific) ||
|
129
|
+
Config.search(keys_global) || 1
|
130
|
+
BASE_THERESHOLD * config_value
|
131
|
+
end
|
91
132
|
end
|
92
133
|
|
93
134
|
# direction of gesture
|
@@ -96,7 +137,7 @@ module Fusuma
|
|
96
137
|
COUNTERCLOCKWISE = 'counterclockwise'
|
97
138
|
|
98
139
|
def initialize(angle:)
|
99
|
-
@angle = angle
|
140
|
+
@angle = angle.to_f
|
100
141
|
end
|
101
142
|
|
102
143
|
def to_s
|
@@ -104,7 +145,7 @@ module Fusuma
|
|
104
145
|
end
|
105
146
|
|
106
147
|
def calc
|
107
|
-
if @angle
|
148
|
+
if @angle.positive?
|
108
149
|
CLOCKWISE
|
109
150
|
else
|
110
151
|
COUNTERCLOCKWISE
|