fusuma 0.11.1 → 1.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/.github/FUNDING.yml +8 -0
- data/.gitignore +6 -0
- data/.reek.yml +93 -45
- data/.rubocop.yml +2 -0
- data/.rubocop_todo.yml +16 -75
- data/Gemfile +2 -0
- data/README.md +12 -5
- data/Rakefile +2 -1
- data/bin/console +1 -1
- data/exe/fusuma +1 -0
- data/fusuma.gemspec +9 -2
- data/lib/fusuma.rb +88 -31
- data/lib/fusuma/config.rb +65 -66
- data/lib/fusuma/config/index.rb +49 -0
- data/lib/fusuma/device.rb +58 -37
- data/lib/fusuma/multi_logger.rb +3 -0
- data/lib/fusuma/plugin/base.rb +56 -0
- data/lib/fusuma/plugin/buffers/buffer.rb +41 -0
- data/lib/fusuma/plugin/buffers/gesture_buffer.rb +70 -0
- data/lib/fusuma/plugin/detectors/detector.rb +41 -0
- data/lib/fusuma/plugin/detectors/pinch_detector.rb +141 -0
- data/lib/fusuma/plugin/detectors/rotate_detector.rb +135 -0
- data/lib/fusuma/plugin/detectors/swipe_detector.rb +145 -0
- data/lib/fusuma/plugin/events/event.rb +38 -0
- data/lib/fusuma/plugin/events/records/gesture_record.rb +31 -0
- data/lib/fusuma/plugin/events/records/index_record.rb +53 -0
- data/lib/fusuma/plugin/events/records/record.rb +20 -0
- data/lib/fusuma/plugin/events/records/text_record.rb +28 -0
- data/lib/fusuma/plugin/executors/command_executor.rb +39 -0
- data/lib/fusuma/plugin/executors/executor.rb +27 -0
- data/lib/fusuma/plugin/filters/filter.rb +40 -0
- data/lib/fusuma/plugin/filters/libinput_device_filter.rb +42 -0
- data/lib/fusuma/plugin/inputs/input.rb +28 -0
- data/lib/fusuma/plugin/inputs/libinput_command_input.rb +133 -0
- data/lib/fusuma/plugin/manager.rb +118 -0
- data/lib/fusuma/plugin/parsers/libinput_gesture_parser.rb +54 -0
- data/lib/fusuma/plugin/parsers/parser.rb +46 -0
- data/lib/fusuma/version.rb +3 -1
- metadata +74 -14
- data/lib/fusuma/command_executor.rb +0 -43
- data/lib/fusuma/event_stack.rb +0 -87
- data/lib/fusuma/gesture_event.rb +0 -50
- data/lib/fusuma/libinput_commands.rb +0 -98
- data/lib/fusuma/pinch.rb +0 -58
- data/lib/fusuma/swipe.rb +0 -59
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../base.rb'
|
4
|
+
|
5
|
+
module Fusuma
|
6
|
+
module Plugin
|
7
|
+
module Buffers
|
8
|
+
# buffer events and output
|
9
|
+
class Buffer < Base
|
10
|
+
def initialize(*args)
|
11
|
+
@events = Array.new(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :events
|
15
|
+
|
16
|
+
# @return [String]
|
17
|
+
def type
|
18
|
+
self.class.name.underscore.split('/').last.gsub('_buffer', '')
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param event [Event]
|
22
|
+
def buffer(event)
|
23
|
+
return if event&.tag != source
|
24
|
+
|
25
|
+
@events.push(event)
|
26
|
+
end
|
27
|
+
|
28
|
+
# clear buffer
|
29
|
+
def clear
|
30
|
+
@events.clear
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set source for tag from config.yml.
|
34
|
+
# DEFAULT_SOURCE is defined in each plugins.
|
35
|
+
def source
|
36
|
+
@source ||= config_params(:source) || self.class.const_get('DEFAULT_SOURCE')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './buffer.rb'
|
4
|
+
|
5
|
+
module Fusuma
|
6
|
+
module Plugin
|
7
|
+
module Buffers
|
8
|
+
# manage events and generate command
|
9
|
+
class GestureBuffer < Buffer
|
10
|
+
DEFAULT_SOURCE = 'libinput_gesture_parser'
|
11
|
+
|
12
|
+
# @param event [Event]
|
13
|
+
def buffer(event)
|
14
|
+
# TODO: buffering events into buffer plugins
|
15
|
+
# - gesture event buffer
|
16
|
+
# - window event buffer
|
17
|
+
# - other event buffer
|
18
|
+
return if event&.tag != source
|
19
|
+
return if event.record.type != :gesture
|
20
|
+
|
21
|
+
@events.push(event)
|
22
|
+
clear unless updating?
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param attr [Symbol]
|
26
|
+
# @return [Float]
|
27
|
+
def sum_attrs(attr)
|
28
|
+
@events.map { |gesture_event| gesture_event.record.direction[attr].to_f }
|
29
|
+
.inject(:+)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param attr [Symbol]
|
33
|
+
# @return [Float]
|
34
|
+
def avg_attrs(attr)
|
35
|
+
sum_attrs(attr).to_f / @events.length
|
36
|
+
end
|
37
|
+
|
38
|
+
# return [Integer]
|
39
|
+
def finger
|
40
|
+
@events.last.record.finger.to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
# @example
|
44
|
+
# event_buffer.gesture
|
45
|
+
# => 'swipe'
|
46
|
+
# @return [String]
|
47
|
+
def gesture
|
48
|
+
@events.last.record.gesture
|
49
|
+
end
|
50
|
+
|
51
|
+
def empty?
|
52
|
+
@events.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
def select_by_events
|
56
|
+
return enum_for(:select) unless block_given?
|
57
|
+
|
58
|
+
events = @events.select { |event| yield event }
|
59
|
+
self.class.new events
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def updating?
|
65
|
+
return true unless @events.last.record.status =~ /begin|end/
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../base.rb'
|
4
|
+
require_relative '../events/event.rb'
|
5
|
+
|
6
|
+
module Fusuma
|
7
|
+
module Plugin
|
8
|
+
module Detectors
|
9
|
+
# Inherite this base
|
10
|
+
class Detector < Base
|
11
|
+
# @param _buffers [Array<Buffer>]
|
12
|
+
# @return [Event] if event is detected
|
13
|
+
# @return [NilClass] if event is NOT detected
|
14
|
+
def detect(_buffers)
|
15
|
+
raise NotImplementedError, "override #{self.class.name}##{__method__}"
|
16
|
+
|
17
|
+
# create_event(record:)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param record [Events::Records::Record]
|
21
|
+
# @return [Events::Event]
|
22
|
+
def create_event(record:)
|
23
|
+
@last_time = Time.now
|
24
|
+
Events::Event.new(time: Time.now, tag: tag, record: record)
|
25
|
+
end
|
26
|
+
|
27
|
+
def last_time
|
28
|
+
@last_time ||= Time.now
|
29
|
+
end
|
30
|
+
|
31
|
+
def tag
|
32
|
+
self.class.name.split('Detectors::').last.underscore
|
33
|
+
end
|
34
|
+
|
35
|
+
def type
|
36
|
+
self.class.name.underscore.split('/').last.gsub('_detector', '')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './detector.rb'
|
4
|
+
|
5
|
+
module Fusuma
|
6
|
+
module Plugin
|
7
|
+
module Detectors
|
8
|
+
class PinchDetector < Detector
|
9
|
+
BUFFER_TYPE = 'gesture'
|
10
|
+
GESTURE_RECORD_TYPE = 'pinch'
|
11
|
+
|
12
|
+
FINGERS = [2, 3, 4].freeze
|
13
|
+
BASE_THERESHOLD = 0.1
|
14
|
+
BASE_INTERVAL = 0.1
|
15
|
+
|
16
|
+
# @param buffers [Array<Buffer>]
|
17
|
+
# @return [Event] if event is detected
|
18
|
+
# @return [NilClass] if event is NOT detected
|
19
|
+
def detect(buffers)
|
20
|
+
buffer = buffers.find { |b| b.type == BUFFER_TYPE }
|
21
|
+
.select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
|
22
|
+
|
23
|
+
return if buffer.empty?
|
24
|
+
|
25
|
+
finger = buffer.finger
|
26
|
+
|
27
|
+
avg_zoom = buffer.avg_attrs(:zoom)
|
28
|
+
first_zoom = buffer.events.first.record.direction.zoom
|
29
|
+
diameter = avg_zoom / first_zoom
|
30
|
+
|
31
|
+
direction = Direction.new(diameter: diameter).to_s
|
32
|
+
quantity = Quantity.new(diameter: diameter).to_f
|
33
|
+
|
34
|
+
index = create_index(gesture: type,
|
35
|
+
finger: finger,
|
36
|
+
direction: direction)
|
37
|
+
|
38
|
+
return unless enough?(index: index, quantity: quantity)
|
39
|
+
|
40
|
+
create_event(record: Events::Records::IndexRecord.new(index: index))
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param [String] gesture
|
44
|
+
# @param [Integer] finger
|
45
|
+
# @param [String] direction
|
46
|
+
# @return [Config::Index]
|
47
|
+
def create_index(gesture:, finger:, direction:)
|
48
|
+
Config::Index.new(
|
49
|
+
[
|
50
|
+
Config::Index::Key.new(gesture),
|
51
|
+
Config::Index::Key.new(finger.to_i, skippable: true),
|
52
|
+
Config::Index::Key.new(direction)
|
53
|
+
]
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def enough?(index:, quantity:)
|
60
|
+
enough_interval?(index: index) && enough_diameter?(index: index, quantity: quantity)
|
61
|
+
end
|
62
|
+
|
63
|
+
def enough_diameter?(index:, quantity:)
|
64
|
+
MultiLogger.info(type: type, quantity: quantity,
|
65
|
+
quantity_threshold: threshold(index: index))
|
66
|
+
quantity >= threshold(index: index)
|
67
|
+
end
|
68
|
+
|
69
|
+
def enough_interval?(index:)
|
70
|
+
return true if first_time?
|
71
|
+
return true if (Time.now - @last_time) > interval_time(index: index)
|
72
|
+
|
73
|
+
false
|
74
|
+
end
|
75
|
+
|
76
|
+
def first_time?
|
77
|
+
!@last_time
|
78
|
+
end
|
79
|
+
|
80
|
+
def threshold(index:)
|
81
|
+
@threshold ||= {}
|
82
|
+
@threshold[index.cache_key] ||= begin
|
83
|
+
keys_specific = Config::Index.new [*index.keys, 'threshold']
|
84
|
+
keys_global = Config::Index.new ['threshold', type]
|
85
|
+
config_value = Config.search(keys_specific) ||
|
86
|
+
Config.search(keys_global) || 1
|
87
|
+
BASE_THERESHOLD * config_value
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def interval_time(index:)
|
92
|
+
@interval_time ||= {}
|
93
|
+
@interval_time[index.cache_key] ||= begin
|
94
|
+
keys_specific = Config::Index.new [*index.keys, 'interval']
|
95
|
+
keys_global = Config::Index.new ['interval', type]
|
96
|
+
config_value = Config.search(keys_specific) ||
|
97
|
+
Config.search(keys_global) || 1
|
98
|
+
BASE_INTERVAL * config_value
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# direction of gesture
|
103
|
+
class Direction
|
104
|
+
IN = 'in'
|
105
|
+
OUT = 'out'
|
106
|
+
|
107
|
+
def initialize(diameter:)
|
108
|
+
@diameter = diameter
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_s
|
112
|
+
calc
|
113
|
+
end
|
114
|
+
|
115
|
+
def calc
|
116
|
+
if @diameter > 1
|
117
|
+
IN
|
118
|
+
else
|
119
|
+
OUT
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# quantity of gesture
|
125
|
+
class Quantity
|
126
|
+
def initialize(diameter:)
|
127
|
+
@diameter = diameter
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_f
|
131
|
+
calc.to_f
|
132
|
+
end
|
133
|
+
|
134
|
+
def calc
|
135
|
+
(1.0 - @diameter).abs
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './detector.rb'
|
4
|
+
|
5
|
+
module Fusuma
|
6
|
+
module Plugin
|
7
|
+
module Detectors
|
8
|
+
class RotateDetector < Detector
|
9
|
+
BUFFER_TYPE = 'gesture'
|
10
|
+
GESTURE_RECORD_TYPE = 'pinch'
|
11
|
+
|
12
|
+
FINGERS = [2, 3, 4].freeze
|
13
|
+
BASE_THERESHOLD = 0.5
|
14
|
+
BASE_INTERVAL = 0.1
|
15
|
+
|
16
|
+
# @param buffers [Array<Buffer>]
|
17
|
+
# @return [Event] if event is detected
|
18
|
+
# @return [NilClass] if event is NOT detected
|
19
|
+
def detect(buffers)
|
20
|
+
buffer = buffers.find { |b| b.type == BUFFER_TYPE }
|
21
|
+
.select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
|
22
|
+
|
23
|
+
return if buffer.empty?
|
24
|
+
|
25
|
+
angle = buffer.avg_attrs(:rotate)
|
26
|
+
|
27
|
+
finger = buffer.finger
|
28
|
+
direction = Direction.new(angle: angle).to_s
|
29
|
+
quantity = Quantity.new(angle: angle).to_f
|
30
|
+
|
31
|
+
index = create_index(gesture: type,
|
32
|
+
finger: finger,
|
33
|
+
direction: direction)
|
34
|
+
|
35
|
+
return unless enough?(index: index, quantity: quantity)
|
36
|
+
|
37
|
+
create_event(record: Events::Records::IndexRecord.new(index: index))
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param [String] gesture
|
41
|
+
# @param [Integer] finger
|
42
|
+
# @param [String] direction
|
43
|
+
# @return [Config::Index]
|
44
|
+
def create_index(gesture:, finger:, direction:)
|
45
|
+
Config::Index.new(
|
46
|
+
[
|
47
|
+
Config::Index::Key.new(gesture),
|
48
|
+
Config::Index::Key.new(finger.to_i, skippable: true),
|
49
|
+
Config::Index::Key.new(direction)
|
50
|
+
]
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def enough?(index:, quantity:)
|
57
|
+
enough_interval?(index: index) && enough_angle?(index: index, quantity: quantity)
|
58
|
+
end
|
59
|
+
|
60
|
+
def enough_angle?(index:, quantity:)
|
61
|
+
MultiLogger.info(type: type, quantity: quantity,
|
62
|
+
quantity_threshold: threshold(index: index))
|
63
|
+
|
64
|
+
quantity > threshold(index: index)
|
65
|
+
end
|
66
|
+
|
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
|
+
def first_time?
|
75
|
+
!@last_time
|
76
|
+
end
|
77
|
+
|
78
|
+
def threshold(index:)
|
79
|
+
@threshold ||= {}
|
80
|
+
@threshold[index.cache_key] ||= begin
|
81
|
+
keys_specific = Config::Index.new [*index.keys, 'threshold']
|
82
|
+
keys_global = Config::Index.new ['threshold', type]
|
83
|
+
config_value = Config.search(keys_specific) ||
|
84
|
+
Config.search(keys_global) || 1
|
85
|
+
BASE_THERESHOLD * config_value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def interval_time(index:)
|
90
|
+
@interval_time ||= {}
|
91
|
+
@interval_time[index.cache_key] ||= begin
|
92
|
+
keys_specific = Config::Index.new [*index.keys, 'interval']
|
93
|
+
keys_global = Config::Index.new ['interval', type]
|
94
|
+
config_value = Config.search(keys_specific) ||
|
95
|
+
Config.search(keys_global) || 1
|
96
|
+
BASE_INTERVAL * config_value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# direction of gesture
|
101
|
+
class Direction
|
102
|
+
CLOCKWISE = 'clockwise'
|
103
|
+
COUNTERCLOCKWISE = 'counterclockwise'
|
104
|
+
|
105
|
+
def initialize(angle:)
|
106
|
+
@angle = angle
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_s
|
110
|
+
calc
|
111
|
+
end
|
112
|
+
|
113
|
+
def calc
|
114
|
+
if @angle > 0
|
115
|
+
CLOCKWISE
|
116
|
+
else
|
117
|
+
COUNTERCLOCKWISE
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# quantity of gesture
|
123
|
+
class Quantity
|
124
|
+
def initialize(angle:)
|
125
|
+
@angle = angle.abs
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_f
|
129
|
+
@angle.to_f
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './detector.rb'
|
4
|
+
|
5
|
+
module Fusuma
|
6
|
+
module Plugin
|
7
|
+
module Detectors
|
8
|
+
class SwipeDetector < Detector
|
9
|
+
BUFFER_TYPE = 'gesture'
|
10
|
+
GESTURE_RECORD_TYPE = 'swipe'
|
11
|
+
|
12
|
+
FINGERS = [3, 4].freeze
|
13
|
+
BASE_THERESHOLD = 10
|
14
|
+
BASE_INTERVAL = 0.5
|
15
|
+
|
16
|
+
# @param buffers [Array<Buffers::Buffer>]
|
17
|
+
# @return [Event] if event is detected
|
18
|
+
# @return [NilClass] if event is NOT detected
|
19
|
+
def detect(buffers)
|
20
|
+
buffer = buffers.find { |b| b.type == BUFFER_TYPE }
|
21
|
+
.select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
|
22
|
+
|
23
|
+
return if buffer.empty?
|
24
|
+
|
25
|
+
move_x = buffer.avg_attrs(:move_x)
|
26
|
+
move_y = buffer.avg_attrs(:move_y)
|
27
|
+
|
28
|
+
finger = buffer.finger
|
29
|
+
direction = Direction.new(move_x: move_x.to_f, move_y: move_y.to_f).to_s
|
30
|
+
quantity = Quantity.new(move_x: move_x.to_f, move_y: move_y.to_f).to_f
|
31
|
+
|
32
|
+
index = create_index(gesture: type,
|
33
|
+
finger: finger,
|
34
|
+
direction: direction)
|
35
|
+
|
36
|
+
return unless enough?(index: index, quantity: quantity)
|
37
|
+
|
38
|
+
create_event(record: Events::Records::IndexRecord.new(index: index))
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param [String] gesture
|
42
|
+
# @param [Integer] finger
|
43
|
+
# @param [String] direction
|
44
|
+
# @return [Config::Index]
|
45
|
+
def create_index(gesture:, finger:, direction:)
|
46
|
+
Config::Index.new(
|
47
|
+
[
|
48
|
+
Config::Index::Key.new(gesture),
|
49
|
+
Config::Index::Key.new(finger.to_i, skippable: true),
|
50
|
+
Config::Index::Key.new(direction)
|
51
|
+
]
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def enough?(index:, quantity:)
|
58
|
+
enough_interval?(index: index) && enough_distance?(index: index, quantity: quantity)
|
59
|
+
end
|
60
|
+
|
61
|
+
def enough_distance?(index:, quantity:)
|
62
|
+
MultiLogger.info(type: type, quantity: quantity,
|
63
|
+
quantity_threshold: threshold(index: index))
|
64
|
+
quantity > threshold(index: index)
|
65
|
+
end
|
66
|
+
|
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
|
+
def first_time?
|
75
|
+
!@last_time
|
76
|
+
end
|
77
|
+
|
78
|
+
def threshold(index:)
|
79
|
+
@threshold ||= {}
|
80
|
+
@threshold[index.cache_key] ||= begin
|
81
|
+
keys_specific = Config::Index.new [*index.keys, 'threshold']
|
82
|
+
keys_global = Config::Index.new ['threshold', type]
|
83
|
+
config_value = Config.search(keys_specific) ||
|
84
|
+
Config.search(keys_global) || 1
|
85
|
+
BASE_THERESHOLD * config_value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def interval_time(index:)
|
90
|
+
@interval_time ||= {}
|
91
|
+
@interval_time[index.cache_key] ||= begin
|
92
|
+
keys_specific = Config::Index.new [*index.keys, 'interval']
|
93
|
+
keys_global = Config::Index.new ['interval', type]
|
94
|
+
config_value = Config.search(keys_specific) ||
|
95
|
+
Config.search(keys_global) || 1
|
96
|
+
BASE_INTERVAL * config_value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# direction of gesture
|
101
|
+
class Direction
|
102
|
+
RIGHT = 'right'
|
103
|
+
LEFT = 'left'
|
104
|
+
DOWN = 'down'
|
105
|
+
UP = 'up'
|
106
|
+
|
107
|
+
def initialize(move_x:, move_y:)
|
108
|
+
@move_x = move_x
|
109
|
+
@move_y = move_y
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s
|
113
|
+
calc
|
114
|
+
end
|
115
|
+
|
116
|
+
def calc
|
117
|
+
if @move_x.abs > @move_y.abs
|
118
|
+
@move_x > 0 ? RIGHT : LEFT
|
119
|
+
elsif @move_y > 0
|
120
|
+
DOWN
|
121
|
+
else
|
122
|
+
UP
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# quantity of gesture
|
128
|
+
class Quantity
|
129
|
+
def initialize(move_x:, move_y:)
|
130
|
+
@x = move_x.abs
|
131
|
+
@y = move_y.abs
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_f
|
135
|
+
calc.to_f
|
136
|
+
end
|
137
|
+
|
138
|
+
def calc
|
139
|
+
@x > @y ? @x.abs : @y.abs
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|