procon_bypass_man 0.1.20.2 → 0.1.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +9 -5
  3. data/.github/workflows/ruby.yml +1 -1
  4. data/.gitignore +1 -0
  5. data/.rspec +1 -0
  6. data/CHANGELOG.md +30 -1
  7. data/Gemfile.lock +4 -4
  8. data/README.md +4 -1
  9. data/docs/getting_started.md +81 -11
  10. data/docs/setting/left-analogstick-cap.md +1 -1
  11. data/docs/setting/splatoon2_macro_dasei_cancel.md +77 -0
  12. data/docs/setting/splatoon2_macro_sokuwari_bubble.md +4 -0
  13. data/docs/setting/splatoon2_shake_tansan.md +47 -0
  14. data/lib/procon_bypass_man/background/jobs/post_completed_remote_macro_job.rb +17 -0
  15. data/lib/procon_bypass_man/background.rb +1 -0
  16. data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +155 -70
  17. data/lib/procon_bypass_man/buttons_setting_configuration/loader.rb +2 -0
  18. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/button.rb +28 -0
  19. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/button_list.rb +31 -0
  20. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/disable_macro_if_pressed.rb +28 -0
  21. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/flip_if_pressed.rb +31 -0
  22. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/force_neutral.rb +28 -0
  23. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/if_pressed.rb +26 -0
  24. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/if_pressed_allows_nil.rb +28 -0
  25. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/open_macro_steps.rb +26 -0
  26. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer.rb +17 -0
  27. data/lib/procon_bypass_man/buttons_setting_configuration.rb +6 -5
  28. data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +4 -0
  29. data/lib/procon_bypass_man/bypass.rb +45 -23
  30. data/lib/procon_bypass_man/commands/bypass_command.rb +30 -10
  31. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +1 -1
  32. data/lib/procon_bypass_man/configuration.rb +8 -1
  33. data/lib/procon_bypass_man/device_connector.rb +55 -174
  34. data/lib/procon_bypass_man/plugin/splatoon2/macro/charge_tansan_bomb.rb +21 -0
  35. data/lib/procon_bypass_man/plugin/splatoon2/macro/dasei_cancel.rb +21 -0
  36. data/lib/procon_bypass_man/plugin/splatoon2/version.rb +1 -1
  37. data/lib/procon_bypass_man/plugins.rb +2 -0
  38. data/lib/procon_bypass_man/procon/analog_stick_cap.rb +4 -23
  39. data/lib/procon_bypass_man/procon/analog_stick_manipulator.rb +36 -0
  40. data/lib/procon_bypass_man/procon/button_collection.rb +0 -8
  41. data/lib/procon_bypass_man/procon/layer_changer.rb +4 -1
  42. data/lib/procon_bypass_man/procon/macro.rb +53 -25
  43. data/lib/procon_bypass_man/procon/macro_builder.rb +43 -35
  44. data/lib/procon_bypass_man/procon/macro_plugin_map.rb +23 -0
  45. data/lib/procon_bypass_man/procon/macro_registry.rb +26 -10
  46. data/lib/procon_bypass_man/procon/suppress_rumble.rb +13 -0
  47. data/lib/procon_bypass_man/procon/user_operation.rb +30 -16
  48. data/lib/procon_bypass_man/procon/value_objects/analog_stick.rb +9 -5
  49. data/lib/procon_bypass_man/procon/value_objects/analog_stick_position.rb +18 -0
  50. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/base.rb +0 -0
  51. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/has_immutable_binary.rb +0 -0
  52. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/has_mutable_binary.rb +0 -0
  53. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/inbound_procon_binary.rb +5 -0
  54. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/processing_procon_binary.rb +7 -2
  55. data/lib/procon_bypass_man/procon/value_objects/binary.rb +11 -0
  56. data/lib/procon_bypass_man/{bypass → procon/value_objects}/bypass_mode.rb +0 -0
  57. data/lib/procon_bypass_man/procon/value_objects/rumble_binary.rb +18 -0
  58. data/lib/procon_bypass_man/procon.rb +59 -17
  59. data/lib/procon_bypass_man/remote_macro/queue_over_process.rb +62 -0
  60. data/lib/procon_bypass_man/remote_macro/remote_macro_object.rb +30 -0
  61. data/lib/procon_bypass_man/remote_macro/remote_macro_receiver.rb +37 -0
  62. data/lib/procon_bypass_man/remote_macro/remote_macro_sender.rb +8 -0
  63. data/lib/procon_bypass_man/remote_macro/task.rb +6 -0
  64. data/lib/procon_bypass_man/remote_macro/task_queue.rb +13 -0
  65. data/lib/procon_bypass_man/remote_macro.rb +14 -0
  66. data/lib/procon_bypass_man/remote_pbm_action/value_objects/remote_pbm_action_object.rb +1 -1
  67. data/lib/procon_bypass_man/remote_pbm_action.rb +1 -0
  68. data/lib/procon_bypass_man/runner.rb +11 -7
  69. data/lib/procon_bypass_man/support/analog_stick_hypotenuse_tilting_power_scaler.rb +59 -0
  70. data/lib/procon_bypass_man/support/cycle_sleep.rb +22 -0
  71. data/lib/procon_bypass_man/support/device_mouse_finder.rb +60 -0
  72. data/lib/procon_bypass_man/{device_procon_finder.rb → support/device_procon_finder.rb} +0 -2
  73. data/lib/procon_bypass_man/{never_exit_accidentally.rb → support/never_exit_accidentally.rb} +0 -0
  74. data/lib/procon_bypass_man/support/remote_macro_http_client.rb +9 -0
  75. data/lib/procon_bypass_man/support/safe_timeout.rb +7 -1
  76. data/lib/procon_bypass_man/{usb_device_controller.rb → support/usb_device_controller.rb} +7 -4
  77. data/lib/procon_bypass_man/version.rb +1 -1
  78. data/lib/procon_bypass_man/websocket/{pbm_job_client.rb → client.rb} +34 -12
  79. data/lib/procon_bypass_man/websocket/forever.rb +47 -0
  80. data/lib/procon_bypass_man/websocket/watchdog.rb +19 -0
  81. data/lib/procon_bypass_man.rb +25 -23
  82. data/procon_bypass_man.gemspec +1 -1
  83. data/project_template/app.rb +13 -4
  84. data/sig/main.rbs +21 -13
  85. metadata +46 -14
  86. data/lib/procon_bypass_man/domains.rb +0 -11
@@ -0,0 +1,36 @@
1
+ class ProconBypassMan::Procon::AnalogStickManipulator
2
+ attr_accessor :manipulated_abs_x, :manipulated_abs_y
3
+
4
+ def initialize(binary, method: )
5
+ analog_stick = ProconBypassMan::Procon::AnalogStick.new(binary: binary)
6
+
7
+ if method =~ /tilt_left_stick_(completely)_to_(left|right)/
8
+ power_level = $1
9
+ direction = $2
10
+
11
+ case direction
12
+ when 'left'
13
+ self.manipulated_abs_x = 400
14
+ # yを引き継ぐとタンサンボムの溜まりが悪くなったので固定値を入れる
15
+ self.manipulated_abs_y = analog_stick.abs_y
16
+ # self.manipulated_abs_y = 1808
17
+ when 'right'
18
+ self.manipulated_abs_x = 3400
19
+ self.manipulated_abs_y = 1808
20
+ end
21
+ else
22
+ warn "error stick manipulator"
23
+ self.manipulated_abs_x = analog_stick.abs_x
24
+ self.manipulated_abs_y = analog_stick.abs_y
25
+ end
26
+ end
27
+
28
+
29
+ # @return [String]
30
+ def to_binary
31
+ ProconBypassMan::AnalogStickPosition.new(
32
+ x: self.manipulated_abs_x,
33
+ y: self.manipulated_abs_y,
34
+ ).to_binary
35
+ end
36
+ end
@@ -37,12 +37,4 @@ class ProconBypassMan::Procon::ButtonCollection
37
37
  BUTTONS = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP.keys.freeze
38
38
 
39
39
  LEFT_ANALOG_STICK = { byte_position: 6..8 }
40
-
41
- # @param [Array<Symbol>] buttons
42
- # @return [Array<Symbol>]
43
- def self.normalize(buttons)
44
- buttons.select { |x|
45
- !!ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[x]
46
- }
47
- end
48
40
  end
@@ -24,7 +24,10 @@ class ProconBypassMan::Procon::LayerChanger
24
24
  # @return [Boolean]
25
25
  def change_layer?
26
26
  if ProconBypassMan::ButtonsSettingConfiguration.instance.prefix_keys.empty?
27
- raise "prefix_keysが未設定です"
27
+ ProconBypassMan.cache.fetch key: 'unknown prefix_keys', expires_in: 60 do
28
+ warn "prefix_keysが未設定です"
29
+ end
30
+ return false
28
31
  end
29
32
  ProconBypassMan::ButtonsSettingConfiguration.instance.prefix_keys.map { |b| pressed?(button: b) }.all?
30
33
  end
@@ -1,13 +1,51 @@
1
1
  class ProconBypassMan::Procon::Macro
2
- class NestedStep
2
+ class BaseNestedStep
3
3
  def initialize(value)
4
4
  @hash = value
5
+ end
6
+
7
+ private
8
+
9
+ def incr_step_index!
10
+ if step_index
11
+ @hash[:step_index] += 1
12
+ else
13
+ @hash[:step_index] = 0
14
+ end
15
+ end
16
+
17
+ def current_step
18
+ @hash[:steps][step_index]
19
+ end
20
+ end
21
+
22
+ class OnetimeNestedStep < BaseNestedStep
23
+ def over?
24
+ current_step.nil?
25
+ end
26
+
27
+ def next_step
28
+ step = current_step
29
+ incr_step_index!
30
+ step
31
+ end
32
+
33
+ private
34
+
35
+ def step_index
36
+ @hash[:step_index] ||= 0
37
+ end
38
+ end
39
+
40
+ class NestedStep < BaseNestedStep
41
+ def initialize(value)
42
+ super
5
43
  unless @hash[:end_at]
6
44
  @hash[:end_at] = (Time.now + @hash[:continue_for]).round(4)
7
45
  end
8
46
  end
9
47
 
10
- def over_end_at?
48
+ def over?
11
49
  (@hash[:end_at] < Time.now).tap do |result|
12
50
  if result
13
51
  ProconBypassMan.logger.debug { "[Macro] nested step is finished(#{@hash})" }
@@ -17,8 +55,6 @@ class ProconBypassMan::Procon::Macro
17
55
 
18
56
  def next_step
19
57
  incr_step_index!
20
-
21
- debug_incr_called_count!
22
58
  if step = current_step
23
59
  return step
24
60
  else
@@ -29,37 +65,22 @@ class ProconBypassMan::Procon::Macro
29
65
 
30
66
  private
31
67
 
32
- def current_step
33
- @hash[:steps][step_index]
34
- end
35
-
36
68
  def step_index
37
69
  @hash[:step_index]
38
70
  end
39
71
 
40
- def incr_step_index!
41
- if step_index
42
- @hash[:step_index] += 1
43
- else
44
- @hash[:step_index] = 0
45
- end
46
- end
47
-
48
72
  def reset_step_index!
49
73
  @hash[:step_index] = 0
50
74
  end
51
-
52
- def debug_incr_called_count!
53
- @hash[:debug_called_count] ||= 0
54
- @hash[:debug_called_count] += 1
55
- end
56
75
  end
57
76
 
58
- attr_accessor :name, :steps
77
+ attr_accessor :name, :steps, :after_callback_block, :force_neutral_buttons
59
78
 
60
- def initialize(name: , steps: )
79
+ def initialize(name: , steps: , force_neutral_buttons: [], &after_callback_block)
61
80
  self.name = name
62
81
  self.steps = steps
82
+ self.after_callback_block = after_callback_block
83
+ self.force_neutral_buttons = force_neutral_buttons # 外部から呼ばれるだけ
63
84
  end
64
85
 
65
86
  def next_step
@@ -69,9 +90,16 @@ class ProconBypassMan::Procon::Macro
69
90
  end
70
91
 
71
92
  if step.is_a?(Hash)
72
- nested_step = NestedStep.new(step)
73
- if nested_step.over_end_at?
93
+ nested_step =
94
+ if step[:continue_for]
95
+ NestedStep.new(step)
96
+ else
97
+ OnetimeNestedStep.new(step)
98
+ end
99
+
100
+ if nested_step.over?
74
101
  steps.shift # NestedStepを破棄する
102
+ self.after_callback_block.call if self.after_callback_block
75
103
  return next_step
76
104
  else
77
105
  return nested_step.next_step
@@ -13,34 +13,32 @@ class ProconBypassMan::Procon::MacroBuilder
13
13
 
14
14
  class Subject
15
15
  def initialize(value)
16
- @button =
17
- if match = value.match(/_(\w+)\z/)
18
- match[1]
19
- else
20
- :unknown
21
- end
16
+ if not /^shake_/ =~ value
17
+ @button =
18
+ if match = value.match(/_(\w+)\z/)
19
+ match[1]
20
+ else
21
+ :unknown
22
+ end
23
+ end
22
24
  @type =
23
25
  if value.start_with?("toggle_")
24
26
  :toggle
27
+ elsif value.start_with?("shake_left_stick")
28
+ :shake_left_stick
25
29
  else
26
30
  :pressing
27
31
  end
28
32
  end
29
33
 
30
- def toggle?
31
- @type == :toggle
32
- end
33
-
34
- def pressing?
35
- not toggle?
36
- end
37
-
38
34
  def to_steps
39
35
  case @type
40
36
  when :toggle
41
37
  [@button.to_sym, :none]
42
38
  when :pressing
43
39
  [@button.to_sym, @button.to_sym]
40
+ when :shake_left_stick
41
+ [:tilt_left_stick_completely_to_left, :tilt_left_stick_completely_to_right]
44
42
  end
45
43
  end
46
44
  end
@@ -56,7 +54,7 @@ class ProconBypassMan::Procon::MacroBuilder
56
54
 
57
55
  # @return [Arary<Symbol>]
58
56
  def build
59
- steps = @steps.map { |step|
57
+ steps = @steps.flat_map { |step|
60
58
  if is_reserved?(step: step) || v1_format?(step: step)
61
59
  step.to_sym
62
60
  elsif value = build_if_v2_format?(step: step)
@@ -65,7 +63,8 @@ class ProconBypassMan::Procon::MacroBuilder
65
63
  nil
66
64
  end
67
65
  }
68
- steps.compact.flatten
66
+
67
+ steps.compact
69
68
  end
70
69
 
71
70
  private
@@ -81,31 +80,40 @@ class ProconBypassMan::Procon::MacroBuilder
81
80
  end
82
81
 
83
82
  def build_if_v2_format?(step: )
84
- # 時間指定なし
85
- if(match = step.match(%r!\Atoggle_(\w+)\z!)) && (button_candidate = match[1]) && is_button(button_candidate)
86
- button = button_candidate
87
- return [button.to_sym, :none]
88
- end
89
-
90
- # 時間指定あり
91
- if %r!^(pressing_|toggle_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|toggle_[^_]+!)) && (match = step.match(%r!_for_([\d_]+)(sec)?\z!))
92
- sec = match[1]
93
- return [
94
- { continue_for: to_num(sec),
95
- steps: SubjectMerger.merge(subjects.map { |x| Subject.new(x) }),
96
- }
97
- ]
98
- end
99
-
100
83
  # no-op command
101
84
  if(match = step.match(%r!wait_for_([\d_]+)(sec)?\z!))
102
85
  sec = match[1]
103
86
  return [
104
- { continue_for: to_num(sec),
87
+ { continue_for: to_f(sec),
105
88
  steps: [:none],
106
89
  }
107
90
  ]
108
91
  end
92
+
93
+ if %r!^(pressing_|toggle_|shake_left_stick_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|shake_left_stick|toggle_[^_]+!)) && (match = step.match(%r!_for_([\d_]+)(sec)?\z!))
94
+ if sec = match[1]
95
+ return {
96
+ continue_for: to_f(sec),
97
+ steps: SubjectMerger.merge(subjects.map { |x| Subject.new(x) }).select { |x|
98
+ if x.is_a?(Array)
99
+ x.select { |y| is_button(y) || RESERVED_WORD_NONE == y }
100
+ else
101
+ is_button(x) || RESERVED_WORD_NONE == x || :tilt_left_stick_completely_to_left == x || :tilt_left_stick_completely_to_right == x
102
+ end
103
+ },
104
+ }
105
+ end
106
+ end
107
+
108
+ if %r!^(pressing_|toggle_|shake_left_stick_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|shake_left_stick|toggle_[^_]+!))
109
+ return SubjectMerger.merge(subjects.map { |x| Subject.new(x) }).select { |x|
110
+ if x.is_a?(Array)
111
+ x.select { |y| is_button(y) || RESERVED_WORD_NONE == y }
112
+ else
113
+ is_button(x) || RESERVED_WORD_NONE == x
114
+ end
115
+ }
116
+ end
109
117
  end
110
118
 
111
119
  # @return [Boolean]
@@ -113,11 +121,11 @@ class ProconBypassMan::Procon::MacroBuilder
113
121
  !!ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[step.to_sym]
114
122
  end
115
123
 
116
- def to_num(value)
124
+ def to_f(value)
117
125
  if value.include?("_")
118
126
  value.sub("_", ".").to_f
119
127
  else
120
- value.to_i
128
+ value.to_f
121
129
  end
122
130
  end
123
131
  end
@@ -0,0 +1,23 @@
1
+ module ProconBypassMan
2
+ class Procon
3
+ # macroキーにメタデータを埋め込んでいる. 通常の処理ではメタデータを露出したくないので露出しないためのクラス
4
+ class MacroPluginMap < ::Hash
5
+ def [](value)
6
+ self.fetch([value, :normal], nil)
7
+ end
8
+
9
+ def each
10
+ transform_keys(&:first).each { |x| yield(x[0], x[1]) }
11
+ end
12
+
13
+ alias_method :original_keys, :keys
14
+ def keys
15
+ super.map(&:first)
16
+ end
17
+
18
+ def raw_keys
19
+ self.original_keys
20
+ end
21
+ end
22
+ end
23
+ end
@@ -3,28 +3,44 @@ class ProconBypassMan::Procon::MacroRegistry
3
3
  null: [],
4
4
  }
5
5
 
6
- def self.install_plugin(klass, steps: nil)
7
- if plugins[klass.to_s.to_sym]
8
- raise "#{klass} macro is already registered"
6
+ def self.install_plugin(klass, steps: nil, macro_type: :normal)
7
+ if plugins.fetch([klass.to_s.to_sym, macro_type], nil)
8
+ Kernel.warn "#{klass} macro is already registered"
9
+ return
9
10
  end
10
11
 
11
- plugins[klass.to_s.to_sym] = ->{
12
- ProconBypassMan::Procon::MacroBuilder.new(steps || klass.steps).build
13
- }
12
+ plugins.store(
13
+ [klass.to_s.to_sym, macro_type], ->{
14
+ ProconBypassMan::Procon::MacroBuilder.new(steps || klass.steps).build
15
+ }
16
+ )
14
17
  end
15
18
 
16
- def self.load(name)
17
- steps = PRESETS[name] || plugins[name].call || raise("unknown macro")
18
- ProconBypassMan::Procon::Macro.new(name: name, steps: steps.dup)
19
+ # @return [ProconBypassMan::Procon::Macro]
20
+ def self.load(name, macro_type: :normal, force_neutral_buttons: [], &after_callback_block)
21
+ if(steps = PRESETS[name] || plugins.fetch([name.to_s.to_sym, macro_type], nil)&.call)
22
+ return ProconBypassMan::Procon::Macro.new(name: name, steps: steps.dup, force_neutral_buttons: force_neutral_buttons, &after_callback_block)
23
+ else
24
+ warn "installされていないマクロ(#{name})を使うことはできません"
25
+ return self.load(:null)
26
+ end
19
27
  end
20
28
 
21
29
  def self.reset!
22
- ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins = {}
30
+ ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins = ProconBypassMan::Procon::MacroPluginMap.new
23
31
  end
24
32
 
25
33
  def self.plugins
26
34
  ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins
27
35
  end
28
36
 
37
+ def self.cleanup_remote_macros!
38
+ remote_keys = ProconBypassMan::Procon::MacroRegistry.plugins.original_keys.select { |_, y| y == :remote }
39
+ remote_keys.each do |remote_key|
40
+ ProconBypassMan::Procon::MacroRegistry.plugins.delete(remote_key)
41
+ end
42
+ ProconBypassMan::Procon::MacroRegistry.plugins
43
+ end
44
+
29
45
  reset!
30
46
  end
@@ -0,0 +1,13 @@
1
+ class ProconBypassMan::SuppressRumble
2
+ # @param [String] binary
3
+ def initialize(binary: )
4
+ @binary = binary
5
+ end
6
+
7
+ # @return [String]
8
+ def execute
9
+ new_raw = ["100c0001404000014040"].pack("H*")
10
+ new_raw[1] = @binary[1]
11
+ new_raw
12
+ end
13
+ end
@@ -33,22 +33,22 @@ class ProconBypassMan::Procon::UserOperation
33
33
  binary.write_as_press_button(button)
34
34
  end
35
35
 
36
- # @param [Symbol, Array<Symbol>] button
37
- def press_button_only(button)
38
- if button.is_a?(Array)
39
- binary.set_no_action!
40
- button.uniq.each do |b|
41
- unless ProconBypassMan::Procon::MacroBuilder::RESERVED_WORD_NONE == b
42
- binary.write_as_press_button(b)
43
- end
44
- end
45
- return
46
- end
36
+ # @param [Symbol, Array<Symbol>] macro_step
37
+ def press_button_only_or_tilt_sticks(macro_step)
38
+ macro_step = [macro_step] if not macro_step.is_a?(Array)
39
+ # スティック操作の時はボタン入力を通す
40
+ binary.set_no_action! if is_button?(macro_step)
41
+
42
+ macro_step.uniq.each do |ms|
43
+ next if ProconBypassMan::Procon::MacroBuilder::RESERVED_WORD_NONE == ms
47
44
 
48
- if ProconBypassMan::Procon::MacroBuilder::RESERVED_WORD_NONE == button
49
- binary.set_no_action!
50
- else
51
- binary.write_as_press_button_only(button)
45
+ if is_button?(ms)
46
+ binary.write_as_press_button(ms)
47
+ elsif is_stick?(ms)
48
+ binary.write_as_tilt_left_stick(ms)
49
+ else
50
+ warn "知らないmacro stepです"
51
+ end
52
52
  end
53
53
  end
54
54
 
@@ -62,7 +62,7 @@ class ProconBypassMan::Procon::UserOperation
62
62
  # @param [Symbol] button
63
63
  # @return [Boolean]
64
64
  def pressing_button?(button)
65
- ProconBypassMan::PressButtonAware.new(@binary.raw).pressing_button?(button)
65
+ pressing_all_buttons?([button])
66
66
  end
67
67
 
68
68
  # @param [Array<Symbol>] buttons
@@ -71,4 +71,18 @@ class ProconBypassMan::Procon::UserOperation
71
71
  aware = ProconBypassMan::PressButtonAware.new(@binary.raw)
72
72
  buttons.all? { |b| aware.pressing_button?(b) }
73
73
  end
74
+
75
+ # @return [Boolean]
76
+ def is_button?(button)
77
+ button = [button] if not button.is_a?(Array)
78
+
79
+ button.all? do |b|
80
+ !!ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[b.to_sym] || b.to_sym == ProconBypassMan::Procon::MacroBuilder::RESERVED_WORD_NONE
81
+ end
82
+ end
83
+
84
+ # @return [Boolean]
85
+ def is_stick?(step)
86
+ !!(step =~ /\Atilt_/)
87
+ end
74
88
  end
@@ -1,6 +1,6 @@
1
1
  class ProconBypassMan::Procon::AnalogStick
2
2
  attr_accessor :neutral_position
3
- attr_accessor :bin_x, :bin_y
3
+ attr_writer :bin_x, :bin_y
4
4
 
5
5
  def initialize(binary: )
6
6
  @neutral_position = ProconBypassMan::ButtonsSettingConfiguration.instance.neutral_position
@@ -13,18 +13,22 @@ class ProconBypassMan::Procon::AnalogStick
13
13
  end
14
14
 
15
15
  def abs_x
16
- bin_x.to_i(2)
16
+ @bin_x.to_i(2)
17
17
  end
18
18
 
19
19
  def abs_y
20
- bin_y.to_i(2)
20
+ @bin_y.to_i(2)
21
21
  end
22
22
 
23
23
  def relative_x
24
- bin_x.to_i(2) - neutral_position.x
24
+ @bin_x.to_i(2) - neutral_position.x
25
25
  end
26
26
 
27
27
  def relative_y
28
- bin_y.to_i(2) - neutral_position.y
28
+ @bin_y.to_i(2) - neutral_position.y
29
+ end
30
+
31
+ def relative_hypotenuse
32
+ Math.sqrt((relative_x**2) + (relative_y**2)).floor(6)
29
33
  end
30
34
  end
@@ -0,0 +1,18 @@
1
+ class ProconBypassMan::AnalogStickPosition
2
+ attr_accessor :x, :y
3
+
4
+ def initialize(x:, y:)
5
+ @x = x.to_i
6
+ @y = y.to_i
7
+ end
8
+
9
+ def to_binary
10
+ analog_stick_data = [
11
+ (@x & "0xff".to_i(16)),
12
+ ((@y << 4) & "0xf0".to_i(16)) | ((@x >> 8) & "0x0f".to_i(16)),
13
+ (@y >> 4) & "0xff".to_i(16),
14
+ ]
15
+ hex = analog_stick_data.map{ |x| x.to_s(16).rjust(2, "0") }.join
16
+ [hex].pack("H*")
17
+ end
18
+ end
@@ -6,4 +6,9 @@ class ProconBypassMan::Domains::InboundProconBinary < ProconBypassMan::Domains::
6
6
  def user_operation_data?
7
7
  binary[0] == "\x30".b
8
8
  end
9
+
10
+ # @return [Boolean]
11
+ def rumble_data?
12
+ binary[0] == "\x10".b
13
+ end
9
14
  end
@@ -36,16 +36,21 @@ class ProconBypassMan::Domains::ProcessingProconBinary < ProconBypassMan::Domain
36
36
 
37
37
  # @param [Symbol] button
38
38
  def write_as_press_button(button)
39
- raise "already pressing button(#{button})" if ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
39
+ return if ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
40
40
 
41
41
  button_obj = ProconBypassMan::Procon::Button.new(button)
42
42
  value = binary[button_obj.byte_position].unpack("C").first + (2**button_obj.bit_position)
43
43
  binary[button_obj.byte_position] = ["%02X" % value.to_s].pack("H*")
44
44
  end
45
45
 
46
+ # @param [Symbol] stick method
47
+ def write_as_tilt_left_stick(step)
48
+ binary[6..8] = ProconBypassMan::Procon::AnalogStickManipulator.new(binary, method: step).to_binary
49
+ end
50
+
46
51
  # @param [Symbol] button
47
52
  def write_as_unpress_button(button)
48
- raise "not press button(#{button}) yet" if not ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
53
+ raise "do not press button(#{button}) yet" if not ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
49
54
 
50
55
  button_obj = ProconBypassMan::Procon::Button.new(button)
51
56
  value = binary[button_obj.byte_position].unpack("C").first - (2**button_obj.bit_position)
@@ -0,0 +1,11 @@
1
+ module ProconBypassMan
2
+ module Domains
3
+ module Binary; end
4
+ end
5
+ end
6
+
7
+ require "procon_bypass_man/procon/value_objects/binary/base"
8
+ require "procon_bypass_man/procon/value_objects/binary/has_immutable_binary"
9
+ require "procon_bypass_man/procon/value_objects/binary/has_mutable_binary"
10
+ require "procon_bypass_man/procon/value_objects/binary/inbound_procon_binary"
11
+ require "procon_bypass_man/procon/value_objects/binary/processing_procon_binary"
@@ -0,0 +1,18 @@
1
+ class ProconBypassMan::RumbleBinary
2
+ # @param [String] binary
3
+ def initialize(binary: )
4
+ @binary = binary
5
+ end
6
+
7
+ def unpack
8
+ @binary.unpack("H*")
9
+ end
10
+
11
+ def noop!
12
+ @binary = ProconBypassMan::SuppressRumble.new(binary: @binary).execute
13
+ end
14
+
15
+ def raw
16
+ @binary
17
+ end
18
+ end