procon_bypass_man 0.1.16.1 → 0.1.19.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +86 -11
  3. data/.github/workflows/release.yml +2 -2
  4. data/.rubocop.yml +2 -0
  5. data/CHANGELOG.md +18 -0
  6. data/Gemfile +1 -0
  7. data/Gemfile.lock +7 -3
  8. data/README.md +25 -17
  9. data/Steepfile +31 -17
  10. data/docs/getting_started.md +60 -0
  11. data/docs/setting/left-analogstick-cap.md +60 -0
  12. data/docs/setting/splatoon2_macro_sokuwari_bubble.md +52 -0
  13. data/docs/setting/splatoon2_recommended_setting.md +40 -0
  14. data/docs/upgrade_pbm.md +56 -0
  15. data/lib/ext/module.rb +16 -0
  16. data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +33 -7
  17. data/lib/procon_bypass_man/buttons_setting_configuration/loader.rb +4 -1
  18. data/lib/procon_bypass_man/buttons_setting_configuration/validator.rb +36 -0
  19. data/lib/procon_bypass_man/buttons_setting_configuration.rb +34 -21
  20. data/lib/procon_bypass_man/commands/bypass_command.rb +2 -2
  21. data/lib/procon_bypass_man/domains/binary/base.rb +14 -0
  22. data/lib/procon_bypass_man/domains/binary/inbound_procon_binary.rb +0 -14
  23. data/lib/procon_bypass_man/domains/binary/processing_procon_binary.rb +2 -16
  24. data/lib/procon_bypass_man/plugin/splatoon2/macro/fast_return.rb +1 -1
  25. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_left_key.rb +1 -1
  26. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_right_key.rb +1 -1
  27. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_up_key.rb +1 -1
  28. data/lib/procon_bypass_man/plugin/splatoon2/macro/sokuwari_for_splash_bomb.rb +22 -0
  29. data/lib/procon_bypass_man/plugin/splatoon2/version.rb +1 -1
  30. data/lib/procon_bypass_man/plugins.rb +1 -0
  31. data/lib/procon_bypass_man/procon/button.rb +1 -1
  32. data/lib/procon_bypass_man/procon/button_collection.rb +8 -0
  33. data/lib/procon_bypass_man/procon/macro.rb +89 -0
  34. data/lib/procon_bypass_man/procon/macro_builder.rb +123 -0
  35. data/lib/procon_bypass_man/procon/macro_registry.rb +9 -27
  36. data/lib/procon_bypass_man/procon/mode_registry.rb +4 -4
  37. data/lib/procon_bypass_man/procon/press_button_aware.rb +6 -5
  38. data/lib/procon_bypass_man/procon/user_operation.rb +16 -2
  39. data/lib/procon_bypass_man/procon/value_objects/analog_stick.rb +1 -1
  40. data/lib/procon_bypass_man/procon.rb +6 -4
  41. data/lib/procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb +3 -3
  42. data/lib/procon_bypass_man/support/compress_array.rb +5 -0
  43. data/lib/procon_bypass_man/support/http_client.rb +4 -0
  44. data/lib/procon_bypass_man/support/on_memory_cache.rb +3 -1
  45. data/lib/procon_bypass_man/support/server_pool.rb +4 -0
  46. data/lib/procon_bypass_man/support/yaml_writer.rb +16 -0
  47. data/lib/procon_bypass_man/version.rb +1 -1
  48. data/lib/procon_bypass_man/websocket/pbm_job_client.rb +13 -2
  49. data/lib/procon_bypass_man.rb +2 -0
  50. data/procon_bypass_man.gemspec +1 -1
  51. data/project_template/app.rb +3 -2
  52. data/project_template/setting.yml +4 -11
  53. data/sig/main.rbs +213 -42
  54. data/sig/on_memory_cache.rbs +16 -0
  55. metadata +16 -5
@@ -0,0 +1,56 @@
1
+ # procon_bypass_man のアップグレード方法
2
+ * pbm-cloudを使う方法、pbmenvを使う方法、pbmenvを使わない方法があります
3
+
4
+ ## pbm-cloudを使う方法
5
+ * https://pbm-cloud.herokuapp.com からデバイス詳細画面を開いてください
6
+ * `デバイスの設定` => `PBMのバージョンアップ`を選択して、表示されるモーダルからインストールしたいバージョンを選択し、 `このバージョンでバージョンアップする` をクリックしてください
7
+ * クリックするとRaspberry Piが再起動するのでしばらく待ってください
8
+ * 設定ファイルが初期状態に戻っているので適宜復元してください
9
+ * デバイス詳細画面からバージョンが上がっていることを確認してください
10
+
11
+ ## pbmenvを使う方法
12
+ * sshをして、以下の3行を実行してください
13
+
14
+ ```
15
+ sudo gem i pbmenv
16
+ sudo pbmenv install latest
17
+ sudo pbmenv use latest
18
+ ```
19
+
20
+ * `sudo pbmenv use latest` を実行すると、 `/usr/share/pbm/current/` に新しいバージョンのprocon_bypass_manを配備します
21
+ * `/usr/share/pbm/current/setting.yml` が初期状態になっているので適宜変更してください
22
+ * 前バージョンのsetting.ymlは消していないので残っています
23
+ * 変更後は、プログラムを起動し直してください
24
+
25
+ ## pbmenvを使わない方法
26
+ * rbファイル内にある `gem 'procon_bypass_man', ` の後ろの番号を変更することで、procon_bypass_manのバージョンを変更できます
27
+ * 最新バージョンは https://rubygems.org/gems/procon_bypass_man を参照してください
28
+ * 変更後は、プログラムを起動し直してください
29
+ * バージョンを変更後、エラーになる場合はサポートするので、discordやissueに報告をお願いします
30
+
31
+ ```ruby
32
+ #!/usr/bin/env ruby
33
+
34
+ require 'bundler/inline'
35
+
36
+ gemfile do
37
+ source 'https://rubygems.org'
38
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
39
+ gem 'procon_bypass_man', '0.1.16.1'
40
+ end
41
+
42
+ ProconBypassMan.configure do |config|
43
+ config.root = File.expand_path(__dir__)
44
+ config.logger = Logger.new("#{ProconBypassMan.root}/app.log", 5, 1024 * 1024 * 10)
45
+ config.logger.level = :debug
46
+ # config.api_servers = ['https://...']
47
+ config.enable_critical_error_logging = true
48
+ end
49
+
50
+ ProconBypassMan.run(setting_path: "/usr/share/pbm/current/setting.yml")
51
+ ```
52
+
53
+ ```diff
54
+ - gem 'procon_bypass_man', '0.1.16.1'
55
+ + gem 'procon_bypass_man', '0.1.17'
56
+ ```
data/lib/ext/module.rb ADDED
@@ -0,0 +1,16 @@
1
+ # pluginの定数未定義を握りつぶす
2
+ class Module
3
+ module ExtModule
4
+ def const_missing(id)
5
+ if self.name =~ /^ProconBypassMan::Plugin/
6
+ parent_const = Object.const_get("#{self.name}")
7
+ parent_const.const_set(id, Module.new)
8
+ Object.const_get("#{self.name}::#{id}")
9
+ else
10
+ super
11
+ end
12
+ end
13
+ end
14
+
15
+ prepend ExtModule
16
+ end
@@ -8,7 +8,7 @@ module ProconBypassMan
8
8
  self.flips = {}
9
9
  self.macros = {}
10
10
  self.remaps = {}
11
- self.left_analog_stick_caps = {}
11
+ self.left_analog_stick_caps = []
12
12
  self.disables = []
13
13
  end
14
14
 
@@ -53,12 +53,18 @@ module ProconBypassMan
53
53
  self.flips[button] = hash
54
54
  end
55
55
 
56
+ # @param [String, Class] プラグインのclass
56
57
  def macro(name, if_pressed: )
57
- if name.respond_to?(:name)
58
- macro_name = name.name.to_sym
59
- else
60
- macro_name = name
61
- end
58
+ macro_name = name.to_s.to_sym
59
+ self.macros[macro_name] = { if_pressed: if_pressed }
60
+ end
61
+
62
+ # 設定ファイルに直接マクロを打ち込める
63
+ # @param [String, Class] macroの識別子
64
+ # @paramh[Array<Symbol>] macroの本体. ボタンの配列
65
+ def open_macro(name, steps: , if_pressed: )
66
+ macro_name = name || "OpenMacro-#{steps.join}".to_sym
67
+ ProconBypassMan::Procon::MacroRegistry.install_plugin(macro_name, steps: steps)
62
68
  self.macros[macro_name] = { if_pressed: if_pressed }
63
69
  end
64
70
 
@@ -88,6 +94,10 @@ module ProconBypassMan
88
94
  raise "not support value"
89
95
  end
90
96
 
97
+ if if_pressed
98
+ hash[:if_pressed] = if_pressed
99
+ end
100
+
91
101
  case force_neutral
92
102
  when TrueClass
93
103
  raise "ボタンを渡してください"
@@ -101,7 +111,7 @@ module ProconBypassMan
101
111
  raise "not support value"
102
112
  end
103
113
 
104
- left_analog_stick_caps[if_pressed] = hash
114
+ left_analog_stick_caps << hash
105
115
  end
106
116
 
107
117
  def disable(button)
@@ -123,6 +133,22 @@ module ProconBypassMan
123
133
  def flip_buttons
124
134
  flips
125
135
  end
136
+
137
+ # @return [String]
138
+ def to_json(*)
139
+ to_hash.to_json
140
+ end
141
+
142
+ # @return [Hash]
143
+ def to_hash
144
+ { mode: mode,
145
+ flips: flips,
146
+ macros: macros,
147
+ remaps: remaps,
148
+ disables: disables,
149
+ left_analog_stick_caps: left_analog_stick_caps,
150
+ }
151
+ end
126
152
  end
127
153
  end
128
154
  end
@@ -3,6 +3,7 @@ module ProconBypassMan
3
3
  module Loader
4
4
  require 'digest/md5'
5
5
 
6
+ # @return [ProconBypassMan::ButtonsSettingConfiguration]
6
7
  def self.load(setting_path: )
7
8
  ProconBypassMan::ButtonsSettingConfiguration.switch_new_context(:validation) do |new_instance|
8
9
  yaml = YAML.load_file(setting_path) or raise "読み込みに失敗しました"
@@ -14,7 +15,9 @@ module ProconBypassMan
14
15
  raise ProconBypassMan::CouldNotLoadConfigError, validator.errors
15
16
  end
16
17
  rescue SyntaxError
17
- raise ProconBypassMan::CouldNotLoadConfigError, "Rubyのシンタックスエラーです"
18
+ raise ProconBypassMan::CouldNotLoadConfigError, "Rubyスクリプトのシンタックスエラーです"
19
+ rescue NoMethodError
20
+ raise ProconBypassMan::CouldNotLoadConfigError, "Rubyスクリプトに未定義の定数・変数があります"
18
21
  rescue Psych::SyntaxError
19
22
  raise ProconBypassMan::CouldNotLoadConfigError, "yamlのシンタックスエラーです"
20
23
  end
@@ -2,6 +2,8 @@ module ProconBypassMan
2
2
  class ButtonsSettingConfiguration
3
3
  class Validator
4
4
  def initialize(config)
5
+ @macro_plugins = config.macro_plugins
6
+ @mode_plugins = config.mode_plugins
5
7
  @layers = config.layers
6
8
  @prefix_keys = config.prefix_keys
7
9
  end
@@ -14,6 +16,8 @@ module ProconBypassMan
14
16
  validate_config_of_button_lonely
15
17
  validate_verify_button_existence
16
18
  validate_flip_and_remap_are_hate_each_other
19
+ validate_verify_mode_plugins
20
+ validate_verify_macro_plugins
17
21
 
18
22
  @errors.empty?
19
23
  end
@@ -86,6 +90,38 @@ module ProconBypassMan
86
90
  end
87
91
  end
88
92
  end
93
+
94
+ def validate_verify_mode_plugins
95
+ @mode_plugins.each do |key, mode|
96
+ begin
97
+ Module.const_get(key.to_s)
98
+ rescue NameError
99
+ next
100
+ end
101
+
102
+ if(const = Module.const_get(key.to_s))
103
+ if not (const.respond_to?(:binaries) && mode.call)
104
+ @errors[:mode] << "モード #{key}を読み込めませんでした。"
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ def validate_verify_macro_plugins
111
+ @macro_plugins.each do |key, macro|
112
+ begin
113
+ Module.const_get(key.to_s)
114
+ rescue NameError
115
+ next
116
+ end
117
+
118
+ if(const = Module.const_get(key.to_s))
119
+ if not (const.respond_to?(:steps) && macro.call)
120
+ @errors[:macro] << "マクロ #{key}を読み込めませんでした。"
121
+ end
122
+ end
123
+ end
124
+ end
89
125
  end
90
126
  end
91
127
  end
@@ -10,27 +10,33 @@ module ProconBypassMan
10
10
  :setting_path,
11
11
  :mode_plugins,
12
12
  :macro_plugins,
13
- :context,
14
- :current_context_key,
15
13
  :neutral_position
16
14
 
17
15
  def self.instance
18
- @@current_context_key ||= :main
19
16
  @@context ||= {}
20
- @@context[@@current_context_key] ||= new
17
+ @@context[current_context_key] ||= new
21
18
  end
22
19
 
23
- def self.switch_new_context(key)
24
- @@context[key] = new
25
- previous_key = @@current_context_key
20
+ def self.current_context_key
21
+ @@current_context_key ||= :main
22
+ end
23
+
24
+ def self.instance=(val)
25
+ @@context[current_context_key] = val
26
+ end
27
+
28
+ def self.switch_new_context(new_context_key)
29
+ @@context[new_context_key] = new
30
+ previous_key = current_context_key
26
31
  if block_given?
27
- @@current_context_key = key
28
- value = yield(@@context[key])
29
- @@current_context_key = previous_key
32
+ @@current_context_key = new_context_key
33
+ value = yield(@@context[new_context_key])
30
34
  return value
31
35
  else
32
- @@current_context_key = key
36
+ @@current_context_key = new_context_key
33
37
  end
38
+ ensure
39
+ @@current_context_key = previous_key
34
40
  end
35
41
 
36
42
  def initialize
@@ -39,19 +45,26 @@ module ProconBypassMan
39
45
 
40
46
  module ManualMode
41
47
  def self.name
42
- 'manual'
48
+ :manual
43
49
  end
44
50
  end
45
51
  def layer(direction, mode: ManualMode, &block)
46
- mode_name = case mode
47
- when String
48
- mode.to_sym
49
- when Symbol
50
- mode
51
- else
52
- mode.name.to_sym
53
- end
54
- unless ([ManualMode.name.to_sym] + ProconBypassMan::Procon::ModeRegistry.plugins.keys).include?(mode_name)
52
+ if ProconBypassMan::ButtonsSettingConfiguration::ManualMode == mode
53
+ mode_name = mode.name
54
+ else
55
+ mode_name = case mode
56
+ when ProconBypassMan::ButtonsSettingConfiguration::ManualMode
57
+ mode.name
58
+ when String
59
+ mode.to_sym
60
+ when Symbol
61
+ mode
62
+ else
63
+ mode.to_s.to_sym
64
+ end
65
+ end
66
+
67
+ unless ([ManualMode.name] + ProconBypassMan::Procon::ModeRegistry.plugins.keys).include?(mode_name)
55
68
  raise("#{mode_name} mode is unknown")
56
69
  end
57
70
 
@@ -40,7 +40,7 @@ class ProconBypassMan::BypassCommand
40
40
  monitor1.shutdown
41
41
  puts "10秒経過したのでThread1を終了します"
42
42
  break
43
- rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
43
+ rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN => e
44
44
  ProconBypassMan::SendErrorCommand.execute(error: "Switchとの切断されました.終了処理を開始します. #{e.full_message}")
45
45
  Process.kill "TERM", Process.ppid
46
46
  rescue Errno::ETIMEDOUT => e
@@ -62,7 +62,7 @@ class ProconBypassMan::BypassCommand
62
62
  rescue EOFError => e
63
63
  ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
64
64
  Process.kill "TERM", Process.ppid
65
- rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
65
+ rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN => e
66
66
  ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します2. #{e.full_message}")
67
67
  Process.kill "TERM", Process.ppid
68
68
  end
@@ -8,4 +8,18 @@ class ProconBypassMan::Domains::Binary::Base
8
8
  def binary
9
9
  raise NotImplementedError
10
10
  end
11
+
12
+ # @return [String]
13
+ def raw
14
+ binary
15
+ end
16
+
17
+ def unpack
18
+ binary.unpack("H*")
19
+ end
20
+
21
+ # @return [ProconBypassMan::ProconReader]
22
+ def to_procon_reader
23
+ ProconBypassMan::ProconReader.new(binary: binary)
24
+ end
11
25
  end
@@ -2,20 +2,6 @@
2
2
  class ProconBypassMan::Domains::InboundProconBinary < ProconBypassMan::Domains::Binary::Base
3
3
  include ProconBypassMan::Domains::HasImmutableBinary
4
4
 
5
- # @return [String]
6
- def raw
7
- binary.dup
8
- end
9
-
10
- def unpack
11
- binary.unpack("H*")
12
- end
13
-
14
- # @return [ProconBypassMan::ProconReader]
15
- def to_procon_reader
16
- ProconBypassMan::ProconReader.new(binary: binary)
17
- end
18
-
19
5
  # @return [Boolean]
20
6
  def user_operation_data?
21
7
  binary[0] == "\x30".b
@@ -4,15 +4,6 @@ class ProconBypassMan::Domains::ProcessingProconBinary < ProconBypassMan::Domain
4
4
 
5
5
  ALL_ZERO_BIT = ["0"].pack("H*").freeze
6
6
 
7
- # @return [String]
8
- def raw
9
- binary
10
- end
11
-
12
- def unpack
13
- binary.unpack("H*")
14
- end
15
-
16
7
  def set_no_action!
17
8
  binary[3] = ALL_ZERO_BIT
18
9
  binary[4] = ALL_ZERO_BIT
@@ -48,7 +39,7 @@ class ProconBypassMan::Domains::ProcessingProconBinary < ProconBypassMan::Domain
48
39
  raise "already pressing button(#{button})" if ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
49
40
 
50
41
  button_obj = ProconBypassMan::Procon::Button.new(button)
51
- value = binary[button_obj.byte_position].unpack("H*").first.to_i(16) + (2**button_obj.bit_position)
42
+ value = binary[button_obj.byte_position].unpack("C").first + (2**button_obj.bit_position)
52
43
  binary[button_obj.byte_position] = ["%02X" % value.to_s].pack("H*")
53
44
  end
54
45
 
@@ -57,7 +48,7 @@ class ProconBypassMan::Domains::ProcessingProconBinary < ProconBypassMan::Domain
57
48
  raise "not press button(#{button}) yet" if not ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
58
49
 
59
50
  button_obj = ProconBypassMan::Procon::Button.new(button)
60
- value = binary[button_obj.byte_position].unpack("H*").first.to_i(16) - (2**button_obj.bit_position)
51
+ value = binary[button_obj.byte_position].unpack("C").first - (2**button_obj.bit_position)
61
52
  binary[button_obj.byte_position] = ["%02X" % value.to_s].pack("H*")
62
53
  end
63
54
 
@@ -72,9 +63,4 @@ class ProconBypassMan::Domains::ProcessingProconBinary < ProconBypassMan::Domain
72
63
  analog_stick_cap = ProconBypassMan::Procon::AnalogStickCap.new(binary)
73
64
  binary[6..8] = analog_stick_cap.capped_position(cap_hypotenuse: cap).to_binary
74
65
  end
75
-
76
- # @return [ProconBypassMan::ProconReader]
77
- def to_procon_reader
78
- ProconBypassMan::ProconReader.new(binary: binary)
79
- end
80
66
  end
@@ -3,7 +3,7 @@ module ProconBypassMan
3
3
  module Splatoon2
4
4
  module Macro
5
5
  module FastReturn
6
- def self.name
6
+ def self.display_name
7
7
  :fast_return
8
8
  end
9
9
 
@@ -3,7 +3,7 @@ module ProconBypassMan
3
3
  module Splatoon2
4
4
  module Macro
5
5
  module JumpToLeftKey
6
- def self.name
6
+ def self.display_name
7
7
  :jump_to_left_key
8
8
  end
9
9
 
@@ -3,7 +3,7 @@ module ProconBypassMan
3
3
  module Splatoon2
4
4
  module Macro
5
5
  module JumpToRightKey
6
- def self.name
6
+ def self.display_name
7
7
  :jump_to_right_key
8
8
  end
9
9
 
@@ -3,7 +3,7 @@ module ProconBypassMan
3
3
  module Splatoon2
4
4
  module Macro
5
5
  module JumpToUpKey
6
- def self.name
6
+ def self.display_name
7
7
  :jump_to_up_key
8
8
  end
9
9
 
@@ -0,0 +1,22 @@
1
+ module ProconBypassMan
2
+ module Plugin
3
+ module Splatoon2
4
+ module Macro
5
+ module SokuwariForSplashBomb
6
+ def self.display_name
7
+ :sokuwari_for_splash_bomb
8
+ end
9
+
10
+ # procon_bypass_man: 0.1.18以上が必要
11
+ def self.steps
12
+ [ :toggle_r_for_0_2sec,
13
+ :toggle_thumbr_for_0_14sec,
14
+ :toggle_thumbr_and_toggle_zr_for_0_34sec,
15
+ :toggle_r_for_1sec,
16
+ ].freeze
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -3,7 +3,7 @@
3
3
  module ProconBypassMan
4
4
  module Plugin
5
5
  module Splatoon2
6
- VERSION = "0.1.2"
6
+ VERSION = "0.1.3"
7
7
  end
8
8
  end
9
9
  end
@@ -3,6 +3,7 @@ require_relative "plugin/splatoon2/macro/fast_return"
3
3
  require_relative "plugin/splatoon2/macro/jump_to_right_key"
4
4
  require_relative "plugin/splatoon2/macro/jump_to_up_key"
5
5
  require_relative "plugin/splatoon2/macro/jump_to_left_key"
6
+ require_relative "plugin/splatoon2/macro/sokuwari_for_splash_bomb"
6
7
  require_relative "plugin/splatoon2/mode/guruguru"
7
8
 
8
9
  module ProconBypassMan
@@ -4,7 +4,7 @@ class ProconBypassMan::Procon::Button
4
4
  attr_accessor :byte_position, :bit_position
5
5
 
6
6
  def initialize(key)
7
- b = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[key] or raise(UnknownButtonFoundError, '定義にないボタンです')
7
+ b = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[key] or raise(UnknownButtonFoundError, "#{key}は定義にないボタンです")
8
8
  self.byte_position = b[:byte_position]
9
9
  self.bit_position = b[:bit_position]
10
10
  end
@@ -37,4 +37,12 @@ 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
40
48
  end
@@ -0,0 +1,89 @@
1
+ class ProconBypassMan::Procon::Macro
2
+ class NestedStep
3
+ def initialize(value)
4
+ @hash = value
5
+ unless @hash[:end_at]
6
+ @hash[:end_at] = (Time.now + @hash[:continue_for]).round(4)
7
+ end
8
+ end
9
+
10
+ def over_end_at?
11
+ (@hash[:end_at] < Time.now).tap do |result|
12
+ if result
13
+ ProconBypassMan.logger.debug { "[Macro] nested step is finished(#{@hash})" }
14
+ end
15
+ end
16
+ end
17
+
18
+ def next_step
19
+ incr_step_index!
20
+
21
+ debug_incr_called_count!
22
+ if step = current_step
23
+ return step
24
+ else
25
+ reset_step_index!
26
+ return current_step
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def current_step
33
+ @hash[:steps][step_index]
34
+ end
35
+
36
+ def step_index
37
+ @hash[:step_index]
38
+ end
39
+
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
+ def reset_step_index!
49
+ @hash[:step_index] = 0
50
+ end
51
+
52
+ def debug_incr_called_count!
53
+ @hash[:debug_called_count] ||= 0
54
+ @hash[:debug_called_count] += 1
55
+ end
56
+ end
57
+
58
+ attr_accessor :name, :steps
59
+
60
+ def initialize(name: , steps: )
61
+ self.name = name
62
+ self.steps = steps
63
+ end
64
+
65
+ def next_step
66
+ step = steps.first
67
+ if step.is_a?(Symbol)
68
+ return steps.shift
69
+ end
70
+
71
+ if step.is_a?(Hash)
72
+ nested_step = NestedStep.new(step)
73
+ if nested_step.over_end_at?
74
+ steps.shift # NestedStepを破棄する
75
+ return next_step
76
+ else
77
+ return nested_step.next_step
78
+ end
79
+ end
80
+ end
81
+
82
+ def finished?
83
+ steps.empty?
84
+ end
85
+
86
+ def ongoing?
87
+ !finished?
88
+ end
89
+ end