procon_bypass_man 0.1.20.1 → 0.1.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +33 -8
  3. data/.github/workflows/ruby.yml +1 -1
  4. data/.gitignore +1 -0
  5. data/.rspec +1 -0
  6. data/CHANGELOG.md +29 -2
  7. data/Gemfile.lock +3 -3
  8. data/README.md +4 -1
  9. data/docs/getting_started.md +104 -7
  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/jobs/report_completed_upgrade_pbm_job.rb +10 -0
  16. data/lib/procon_bypass_man/background.rb +2 -0
  17. data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +155 -70
  18. data/lib/procon_bypass_man/buttons_setting_configuration/loader.rb +2 -0
  19. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/button.rb +28 -0
  20. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/button_list.rb +31 -0
  21. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/disable_macro_if_pressed.rb +28 -0
  22. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/flip_if_pressed.rb +31 -0
  23. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/force_neutral.rb +28 -0
  24. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/if_pressed.rb +26 -0
  25. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/if_pressed_allows_nil.rb +28 -0
  26. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/open_macro_steps.rb +26 -0
  27. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer.rb +17 -0
  28. data/lib/procon_bypass_man/buttons_setting_configuration.rb +6 -5
  29. data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +4 -0
  30. data/lib/procon_bypass_man/bypass.rb +0 -1
  31. data/lib/procon_bypass_man/commands/connect_device_command.rb +11 -21
  32. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +6 -0
  33. data/lib/procon_bypass_man/configuration.rb +8 -1
  34. data/lib/procon_bypass_man/device_connector.rb +7 -13
  35. data/lib/procon_bypass_man/device_procon_finder.rb +0 -22
  36. data/lib/procon_bypass_man/domains/analog_stick_position.rb +18 -0
  37. data/lib/procon_bypass_man/domains/binary/processing_procon_binary.rb +7 -2
  38. data/lib/procon_bypass_man/{bypass → domains}/bypass_mode.rb +8 -0
  39. data/lib/procon_bypass_man/domains.rb +2 -0
  40. data/lib/procon_bypass_man/plugin/splatoon2/macro/charge_tansan_bomb.rb +21 -0
  41. data/lib/procon_bypass_man/plugin/splatoon2/macro/dasei_cancel.rb +21 -0
  42. data/lib/procon_bypass_man/plugin/splatoon2/macro/fast_return.rb +4 -0
  43. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_left_key.rb +4 -0
  44. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_right_key.rb +4 -0
  45. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_up_key.rb +4 -0
  46. data/lib/procon_bypass_man/plugin/splatoon2/macro/sokuwari_for_splash_bomb.rb +4 -0
  47. data/lib/procon_bypass_man/plugin/splatoon2/mode/guruguru.rb +4 -0
  48. data/lib/procon_bypass_man/plugin/splatoon2/version.rb +1 -1
  49. data/lib/procon_bypass_man/plugins.rb +2 -0
  50. data/lib/procon_bypass_man/procon/analog_stick_cap.rb +4 -23
  51. data/lib/procon_bypass_man/procon/analog_stick_manipulator.rb +36 -0
  52. data/lib/procon_bypass_man/procon/button_collection.rb +0 -8
  53. data/lib/procon_bypass_man/procon/layer_changer.rb +4 -1
  54. data/lib/procon_bypass_man/procon/macro.rb +53 -25
  55. data/lib/procon_bypass_man/procon/macro_builder.rb +43 -35
  56. data/lib/procon_bypass_man/procon/macro_plugin_map.rb +23 -0
  57. data/lib/procon_bypass_man/procon/macro_registry.rb +26 -10
  58. data/lib/procon_bypass_man/procon/user_operation.rb +30 -16
  59. data/lib/procon_bypass_man/procon/value_objects/analog_stick.rb +9 -5
  60. data/lib/procon_bypass_man/procon.rb +51 -17
  61. data/lib/procon_bypass_man/remote_macro/queue_over_process.rb +62 -0
  62. data/lib/procon_bypass_man/remote_macro/remote_macro_object.rb +30 -0
  63. data/lib/procon_bypass_man/remote_macro/remote_macro_receiver.rb +37 -0
  64. data/lib/procon_bypass_man/remote_macro/remote_macro_sender.rb +8 -0
  65. data/lib/procon_bypass_man/remote_macro/task.rb +6 -0
  66. data/lib/procon_bypass_man/remote_macro/task_queue.rb +13 -0
  67. data/lib/procon_bypass_man/remote_macro.rb +14 -0
  68. data/lib/procon_bypass_man/remote_pbm_action/change_pbm_version_action.rb +4 -1
  69. data/lib/procon_bypass_man/remote_pbm_action/value_objects/remote_pbm_action_object.rb +1 -1
  70. data/lib/procon_bypass_man/remote_pbm_action.rb +1 -0
  71. data/lib/procon_bypass_man/runner.rb +5 -1
  72. data/lib/procon_bypass_man/support/analog_stick_hypotenuse_tilting_power_scaler.rb +59 -0
  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/usb_device_controller.rb +51 -0
  76. data/lib/procon_bypass_man/version.rb +1 -1
  77. data/lib/procon_bypass_man/websocket/{pbm_job_client.rb → client.rb} +44 -12
  78. data/lib/procon_bypass_man/websocket/forever.rb +47 -0
  79. data/lib/procon_bypass_man/websocket/watchdog.rb +19 -0
  80. data/lib/procon_bypass_man.rb +19 -9
  81. data/procon_bypass_man.gemspec +2 -2
  82. data/project_template/app.rb +10 -2
  83. data/project_template/systemd_units/pbm.service +1 -1
  84. data/sig/main.rbs +20 -0
  85. metadata +38 -8
@@ -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
@@ -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
@@ -1,3 +1,5 @@
1
+ require "procon_bypass_man/procon/macro_plugin_map"
2
+
1
3
  class ProconBypassMan::Procon
2
4
  require "procon_bypass_man/procon/consts"
3
5
  require "procon_bypass_man/procon/mode_registry"
@@ -19,6 +21,7 @@ class ProconBypassMan::Procon
19
21
  ongoing_macro: MacroRegistry.load(:null),
20
22
  ongoing_mode: ModeRegistry.load(:manual),
21
23
  }
24
+ @@left_stick_tilting_power_scaler = ProconBypassMan::AnalogStickTiltingPowerScaler.new
22
25
  end
23
26
  reset!
24
27
 
@@ -38,6 +41,7 @@ class ProconBypassMan::Procon
38
41
  ProconBypassMan::ButtonsSettingConfiguration.instance.layers[current_layer_key]
39
42
  end
40
43
 
44
+ # 内部ステータスを書き換えるフェーズ
41
45
  def apply!
42
46
  layer_changer = ProconBypassMan::Procon::LayerChanger.new(binary: user_operation.binary)
43
47
  if layer_changer.change_layer?
@@ -46,14 +50,52 @@ class ProconBypassMan::Procon
46
50
  return
47
51
  end
48
52
 
49
- if ongoing_macro.finished?
53
+ analog_stick = ProconBypassMan::Procon::AnalogStick.new(binary: user_operation.binary.raw)
54
+ dumped_tilting_power = @@left_stick_tilting_power_scaler.add_sample(analog_stick.relative_hypotenuse)
55
+
56
+ enable_all_macro = true
57
+ enable_macro_map = Hash.new {|h,k| h[k] = true }
58
+ current_layer.disable_macros.each do |disable_macro|
59
+ if (disable_macro[:if_pressed] == [true] || user_operation.pressing_all_buttons?(disable_macro[:if_pressed]))
60
+ if disable_macro[:name] == :all
61
+ enable_all_macro = false
62
+ else
63
+ enable_macro_map[disable_macro[:name]] = false
64
+ end
65
+ end
66
+ end
67
+
68
+ if ongoing_macro.finished? && enable_all_macro
50
69
  current_layer.macros.each do |macro_name, options|
70
+ next unless enable_macro_map[macro_name]
71
+
72
+ if(if_tilted_left_stick_value = options[:if_tilted_left_stick])
73
+ threshold = (if_tilted_left_stick_value.is_a?(Hash) && if_tilted_left_stick_value[:threshold]) || ProconBypassMan::AnalogStickTiltingPowerScaler::DEFAULT_THRESHOLD
74
+ if dumped_tilting_power&.tilting?(threshold: threshold, current_position_x: analog_stick.relative_x, current_position_y: analog_stick.relative_y) && user_operation.pressing_all_buttons?(options[:if_pressed])
75
+ @@status[:ongoing_macro] = MacroRegistry.load(macro_name)
76
+ break
77
+ end
78
+
79
+ next
80
+ end
81
+
51
82
  if user_operation.pressing_all_buttons?(options[:if_pressed])
52
- @@status[:ongoing_macro] = MacroRegistry.load(macro_name)
83
+ @@status[:ongoing_macro] = MacroRegistry.load(macro_name, force_neutral_buttons: options[:force_neutral])
84
+ break
53
85
  end
54
86
  end
55
87
  end
56
88
 
89
+ # remote macro
90
+ if task = ProconBypassMan::RemoteMacro::TaskQueueInProcess.non_blocking_shift
91
+ ProconBypassMan::Procon::MacroRegistry.cleanup_remote_macros!
92
+ macro_name = task.name || "RemoteMacro-#{task.steps.join}".to_sym
93
+ ProconBypassMan::Procon::MacroRegistry.install_plugin(macro_name, steps: task.steps, macro_type: :remote)
94
+ @@status[:ongoing_macro] = MacroRegistry.load(macro_name, macro_type: :remote) do
95
+ ProconBypassMan::PostCompletedRemoteMacroJob.perform_async(task.uuid)
96
+ end
97
+ end
98
+
57
99
  case current_layer.mode
58
100
  when :manual
59
101
  @@status[:ongoing_mode] = ModeRegistry.load(:manual)
@@ -88,15 +130,17 @@ class ProconBypassMan::Procon
88
130
  status
89
131
  end
90
132
 
91
- # @return [ProconBypassMan::Domains::ProcessingProconBinary]
133
+ # @return [String]
92
134
  def to_binary
93
135
  if ongoing_mode.name != :manual
94
136
  return user_operation.binary.raw
95
137
  end
96
138
 
97
- if ongoing_macro.ongoing?
98
- step = ongoing_macro.next_step or return(user_operation.binary.raw)
99
- user_operation.press_button_only(step)
139
+ if ongoing_macro.ongoing? && (step = ongoing_macro.next_step)
140
+ ongoing_macro.force_neutral_buttons&.each do |force_neutral_button|
141
+ user_operation.unpress_button(force_neutral_button)
142
+ end
143
+ user_operation.press_button_only_or_tilt_sticks(step)
100
144
  return user_operation.binary.raw
101
145
  end
102
146
 
@@ -105,7 +149,7 @@ class ProconBypassMan::Procon
105
149
  end
106
150
 
107
151
  current_layer.left_analog_stick_caps.each do |config|
108
- if config[:if_pressed].nil? || user_operation.pressing_all_buttons?(config[:if_pressed])
152
+ if !config[:if_pressed] || user_operation.pressing_all_buttons?(config[:if_pressed])
109
153
  config[:force_neutral]&.each do |force_neutral_button|
110
154
  user_operation.unpress_button(force_neutral_button)
111
155
  end
@@ -143,14 +187,4 @@ class ProconBypassMan::Procon
143
187
 
144
188
  user_operation.binary.raw
145
189
  end
146
-
147
- private
148
-
149
- def method_missing(name)
150
- if name.to_s =~ /\Apressed_[a-z]+\?\z/
151
- user_operation.public_send(name)
152
- else
153
- super
154
- end
155
- end
156
190
  end
@@ -0,0 +1,62 @@
1
+ class ProconBypassMan::QueueOverProcess
2
+ attr_reader :drb
3
+
4
+ @@drb_server = nil
5
+ @@drb_server_thread = nil
6
+
7
+ def self.start!
8
+ return unless ProconBypassMan.config.enable_remote_macro?
9
+ require 'drb/drb'
10
+
11
+ FileUtils.rm_rf(file_path) if File.exist?(file_path)
12
+ begin
13
+ @@drb_server = DRb.start_service(url, Queue.new, safe_level: 1)
14
+ rescue Errno::EADDRINUSE => e
15
+ ProconBypassMan.logger.error e
16
+ raise
17
+ end
18
+
19
+ @@drb_server_thread =
20
+ Thread.new do
21
+ DRb.thread.join
22
+ end
23
+ end
24
+
25
+ def self.shutdown
26
+ if @@drb_server
27
+ @@drb_server_thread.kill
28
+ @@drb_server.stop_service
29
+ end
30
+ end
31
+
32
+ def self.push(value)
33
+ return unless ProconBypassMan.config.enable_remote_macro?
34
+
35
+ drb.push(value)
36
+ end
37
+
38
+ def self.pop
39
+ return unless ProconBypassMan.config.enable_remote_macro?
40
+
41
+ drb.pop
42
+ end
43
+
44
+ def self.drb
45
+ return unless ProconBypassMan.config.enable_remote_macro?
46
+
47
+ @@drb ||= new.drb
48
+ end
49
+
50
+ PROTOCOL = "drbunix"
51
+ def self.url
52
+ "#{PROTOCOL}:/tmp/procon_bypass_man_queue"
53
+ end
54
+
55
+ def self.file_path
56
+ url.gsub("#{PROTOCOL}:", "")
57
+ end
58
+
59
+ def initialize
60
+ @drb = DRbObject.new_with_uri(self.class.url)
61
+ end
62
+ end
@@ -0,0 +1,30 @@
1
+ module ProconBypassMan
2
+ class RemoteMacroObject
3
+ # valueobjectがvalidatorの責務も持っている. 今度分離する
4
+ class ValidationError < StandardError; end
5
+ class MustBeNotNilError < ValidationError; end
6
+ class NonSupportAction < ValidationError; end
7
+
8
+ attr_accessor :name, :uuid, :steps
9
+
10
+ # @param [String] name
11
+ # @param [String] uuid
12
+ # @param [Array] steps
13
+ def initialize(name: , uuid:, steps: )
14
+ @name = name
15
+ @uuid = uuid
16
+ @steps = steps
17
+ freeze
18
+ end
19
+
20
+ # @raise [MustBeNotNilError]
21
+ # @raise [NonSupportAction]
22
+ # @return [void]
23
+ def validate!
24
+ self.uuid or raise MustBeNotNilError, "uuidは値が必須です"
25
+ unless self.steps.is_a?(Array)
26
+ raise ValidationError, "stepsは配列です"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,37 @@
1
+ class ProconBypassMan::RemoteMacroReceiver
2
+ # forkしたプロセスで動かすクラス。sock経由で命令を受け取ってmacoのキューに積んでいく
3
+ def self.start_with_foreground!
4
+ return unless ProconBypassMan.config.enable_remote_macro?
5
+
6
+ run
7
+ end
8
+
9
+ def self.start!
10
+ return unless ProconBypassMan.config.enable_remote_macro?
11
+
12
+ Thread.start do
13
+ start_with_foreground!
14
+ end
15
+ end
16
+
17
+ def self.run
18
+ while(task = ProconBypassMan::QueueOverProcess.pop)
19
+ receive(task)
20
+ end
21
+ shutdown
22
+ rescue Errno::ENOENT, Errno::ECONNRESET, Errno::ECONNREFUSED => e
23
+ ProconBypassMan.logger.debug(e)
24
+ end
25
+
26
+
27
+ # @param [ProconBypassMan::RemoteMacro::Task] task
28
+ def self.receive(task)
29
+ ProconBypassMan.logger.info "[remote macro][receiver] name: #{task.name}, uuid: #{task.uuid}, steps: #{task.steps}"
30
+ ProconBypassMan::RemoteMacro::TaskQueueInProcess.push(task)
31
+ true
32
+ end
33
+
34
+ def self.shutdown
35
+ ProconBypassMan.logger.info("ProconBypassMan::RemoteMacroReceiverを終了します。")
36
+ end
37
+ end
@@ -0,0 +1,8 @@
1
+ class ProconBypassMan::RemoteMacroSender
2
+ def self.execute(name: , uuid: , steps: )
3
+ ProconBypassMan.logger.info "[remote macro][sender] name: #{name}, uuid: #{uuid}, steps: #{steps}"
4
+ ProconBypassMan::QueueOverProcess.push(
5
+ ProconBypassMan::RemoteMacro::Task.new(name, uuid, steps)
6
+ )
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module ProconBypassMan
2
+ module RemoteMacro
3
+ class Task < Struct.new(:name, :uuid, :steps)
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ module ProconBypassMan
2
+ module RemoteMacro
3
+ class TaskQueue < ::Queue
4
+ def present?
5
+ not empty?
6
+ end
7
+
8
+ def non_blocking_shift
9
+ present? && shift
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module ProconBypassMan
2
+ module RemoteMacro
3
+ require "procon_bypass_man/remote_macro/remote_macro_object"
4
+ require "procon_bypass_man/remote_macro/remote_macro_receiver"
5
+ require "procon_bypass_man/remote_macro/remote_macro_sender"
6
+ require "procon_bypass_man/remote_macro/queue_over_process"
7
+ require "procon_bypass_man/remote_macro/task"
8
+ require "procon_bypass_man/remote_macro/task_queue"
9
+
10
+ ACTION_KEY = "remote_macro"
11
+
12
+ TaskQueueInProcess = ProconBypassMan::RemoteMacro::TaskQueue.new
13
+ end
14
+ end
@@ -6,8 +6,11 @@ module ProconBypassMan
6
6
  require "pbmenv"
7
7
  ProconBypassMan.logger.info "execute ChangePbmVersionAction!"
8
8
  pbm_version = args["pbm_version"] or raise(ProconBypassMan::RemotePbmAction::NeedPbmVersionError, "pbm_versionが必要です, #{args.inspect}")
9
- Pbmenv.install(pbm_version)
9
+ Pbmenv.uninstall(pbm_version) # 途中でシャットダウンしてしまった、とか状態が途中の状態かもしれないので一旦消す
10
+ Pbmenv.install(pbm_version, enable_pbm_cloud: true)
10
11
  Pbmenv.use(pbm_version)
12
+ ProconBypassMan.logger.info "#{pbm_version}へアップグレードしました"
13
+ ProconBypassMan::ReportCompletedUpgradePbmJob.perform
11
14
  `reboot` # symlinkの参照先が変わるのでrebootする必要がある
12
15
  end
13
16
 
@@ -11,7 +11,7 @@ module ProconBypassMan
11
11
  # @param [String] status
12
12
  # @param [String] #uuid
13
13
  # @param [Time] created_at
14
- # @return [Hash] job_args
14
+ # @param [Hash] job_args
15
15
  def initialize(action: , status:, uuid:, created_at:, job_args: )
16
16
  self.action = action
17
17
  self.status = status
@@ -6,6 +6,7 @@ module ProconBypassMan
6
6
  require "procon_bypass_man/remote_pbm_action/stop_pbm_action"
7
7
  require "procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb"
8
8
  require "procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command"
9
+ require "procon_bypass_man/remote_pbm_action/value_objects/remote_pbm_action_object"
9
10
 
10
11
  ACTION_CHANGE_PBM_VERSION = "change_pbm_version"
11
12
  ACTION_REBOOT_OS = "reboot_os"
@@ -27,7 +27,11 @@ class ProconBypassMan::Runner
27
27
  loop do
28
28
  $will_terminate_token = false
29
29
  # NOTE メインプロセスではThreadをいくつか起動しているので念のためパフォーマンスを優先するためにforkしていく
30
- child_pid = Kernel.fork { ProconBypassMan::BypassCommand.new(gadget: @gadget, procon: @procon).execute }
30
+ child_pid = Kernel.fork {
31
+ DRb.start_service if defined?(DRb)
32
+ ProconBypassMan::RemoteMacroReceiver.start!
33
+ ProconBypassMan::BypassCommand.new(gadget: @gadget, procon: @procon).execute
34
+ }
31
35
 
32
36
  begin
33
37
  # TODO 小プロセスが消滅した時に、メインプロセスは生き続けてしまい、何もできなくなる問題がある