rgss_db 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/COPYING.md +674 -0
  4. data/README.md +347 -0
  5. data/bin/rgss-db +4 -0
  6. data/bin/rgssdb +4 -0
  7. data/lib/rgss_db/app.rb +928 -0
  8. data/lib/rgss_db/controller/data_manager.rb +557 -0
  9. data/lib/rgss_db/model/data_file.rb +516 -0
  10. data/lib/rgss_db/model/data_file_factory.rb +94 -0
  11. data/lib/rgss_db/model/debug.rb +199 -0
  12. data/lib/rgss_db/model/errors.rb +17 -0
  13. data/lib/rgss_db/model/mixins/jsonable.rb +35 -0
  14. data/lib/rgss_db/model/mixins/jsonable_constructor.rb +40 -0
  15. data/lib/rgss_db/model/rpg_maker_data/vx/rgss/color.rb +72 -0
  16. data/lib/rgss_db/model/rpg_maker_data/vx/rgss/rect.rb +70 -0
  17. data/lib/rgss_db/model/rpg_maker_data/vx/rgss/table.rb +99 -0
  18. data/lib/rgss_db/model/rpg_maker_data/vx/rgss/tone.rb +72 -0
  19. data/lib/rgss_db/model/rpg_maker_data/vx/rgss.rb +11 -0
  20. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/actor.rb +44 -0
  21. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/animation.rb +31 -0
  22. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/animation_frame.rb +20 -0
  23. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/animation_timing.rb +23 -0
  24. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/area.rb +26 -0
  25. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/armor.rb +31 -0
  26. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/audio_file.rb +23 -0
  27. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/base_item.rb +25 -0
  28. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/bgm.rb +36 -0
  29. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/bgs.rb +36 -0
  30. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/class.rb +31 -0
  31. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/class_learning.rb +20 -0
  32. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/common_event.rb +25 -0
  33. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/enemy.rb +44 -0
  34. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/enemy_action.rb +29 -0
  35. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/enemy_drop_item.rb +23 -0
  36. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event.rb +36 -0
  37. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event_command.rb +19 -0
  38. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event_page.rb +32 -0
  39. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event_page_condition.rb +34 -0
  40. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event_page_graphic.rb +25 -0
  41. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/item.rb +27 -0
  42. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/map.rb +47 -0
  43. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/map_info.rb +26 -0
  44. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/me.rb +27 -0
  45. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/move_command.rb +18 -0
  46. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/move_route.rb +20 -0
  47. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/se.rb +21 -0
  48. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/skill.rb +22 -0
  49. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/state.rb +47 -0
  50. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/system.rb +43 -0
  51. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/system_terms.rb +53 -0
  52. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/system_test_battler.rb +25 -0
  53. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/system_vehicle.rb +24 -0
  54. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/troop.rb +24 -0
  55. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/troop_member.rb +23 -0
  56. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/troop_page.rb +21 -0
  57. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/troop_page_condition.rb +33 -0
  58. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/usable_item.rb +87 -0
  59. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/weapon.rb +31 -0
  60. data/lib/rgss_db/model/rpg_maker_data/vx/rpg.rb +59 -0
  61. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss/color.rb +72 -0
  62. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss/rect.rb +70 -0
  63. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss/table.rb +99 -0
  64. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss/tone.rb +72 -0
  65. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss.rb +11 -0
  66. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/actor.rb +27 -0
  67. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/animation.rb +31 -0
  68. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/animation_frame.rb +23 -0
  69. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/animation_timing.rb +26 -0
  70. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/armor.rb +20 -0
  71. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/audio_file.rb +23 -0
  72. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/base_item.rb +31 -0
  73. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/base_item_feature.rb +29 -0
  74. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/bgm.rb +43 -0
  75. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/bgs.rb +43 -0
  76. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/class.rb +37 -0
  77. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/class_learning.rb +24 -0
  78. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/common_event.rb +33 -0
  79. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/enemy.rb +27 -0
  80. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/enemy_action.rb +26 -0
  81. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/enemy_drop_item.rb +24 -0
  82. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/equip_item.rb +19 -0
  83. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event.rb +36 -0
  84. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event_command.rb +19 -0
  85. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event_page.rb +35 -0
  86. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event_page_condition.rb +40 -0
  87. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event_page_graphic.rb +31 -0
  88. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/item.rb +25 -0
  89. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/map.rb +58 -0
  90. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/map_encounter.rb +23 -0
  91. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/map_info.rb +26 -0
  92. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/me.rb +27 -0
  93. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/move_command.rb +17 -0
  94. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/move_route.rb +19 -0
  95. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/se.rb +21 -0
  96. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/skill.rb +25 -0
  97. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/state.rb +34 -0
  98. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/system.rb +62 -0
  99. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/system_terms.rb +25 -0
  100. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/system_test_battler.rb +24 -0
  101. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/system_vehicle.rb +27 -0
  102. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/tileset.rb +26 -0
  103. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/troop.rb +24 -0
  104. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/troop_member.rb +25 -0
  105. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/troop_page.rb +24 -0
  106. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/troop_page_condition.rb +39 -0
  107. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/usable_item.rb +84 -0
  108. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/usable_item_damage.rb +56 -0
  109. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/usable_item_effect.rb +25 -0
  110. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/weapon.rb +25 -0
  111. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg.rb +66 -0
  112. data/lib/rgss_db/model/rpg_maker_data/xp/rgss/color.rb +72 -0
  113. data/lib/rgss_db/model/rpg_maker_data/xp/rgss/rect.rb +70 -0
  114. data/lib/rgss_db/model/rpg_maker_data/xp/rgss/table.rb +99 -0
  115. data/lib/rgss_db/model/rpg_maker_data/xp/rgss/tone.rb +72 -0
  116. data/lib/rgss_db/model/rpg_maker_data/xp/rgss.rb +11 -0
  117. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/actor.rb +44 -0
  118. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/animation.rb +28 -0
  119. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/animation_frame.rb +20 -0
  120. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/animation_timing.rb +24 -0
  121. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/armor.rb +37 -0
  122. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/audio_file.rb +23 -0
  123. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/class.rb +28 -0
  124. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/class_learning.rb +20 -0
  125. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/common_event.rb +25 -0
  126. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/enemy.rb +47 -0
  127. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/enemy_action.rb +28 -0
  128. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event.rb +36 -0
  129. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event_command.rb +19 -0
  130. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event_page.rb +32 -0
  131. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event_page_condition.rb +30 -0
  132. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event_page_graphic.rb +27 -0
  133. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/item.rb +48 -0
  134. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/map.rb +39 -0
  135. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/map_info.rb +26 -0
  136. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/move_command.rb +18 -0
  137. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/move_route.rb +19 -0
  138. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/skill.rb +47 -0
  139. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/state.rb +51 -0
  140. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/system.rb +56 -0
  141. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/system_test_battler.rb +25 -0
  142. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/system_words.rb +39 -0
  143. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/tileset.rb +39 -0
  144. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/troop.rb +24 -0
  145. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/troop_member.rb +23 -0
  146. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/troop_page.rb +21 -0
  147. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/troop_page_condition.rb +32 -0
  148. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/weapon.rb +38 -0
  149. data/lib/rgss_db/model/rpg_maker_data/xp/rpg.rb +52 -0
  150. data/lib/rgss_db/model/strings.rb +607 -0
  151. data/lib/rgss_db/model/utilities.rb +90 -0
  152. data/lib/rgss_db/version.rb +7 -0
  153. data/lib/rgss_db/view/app_cli.rb +449 -0
  154. data/lib/rgss_db.rb +41 -0
  155. data/sig/rgss_db.rbs +5221 -0
  156. metadata +496 -0
@@ -0,0 +1,928 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./version"
4
+ require_relative "./model/errors"
5
+ require_relative "./model/debug"
6
+ require_relative "./model/strings"
7
+ require_relative "./model/utilities"
8
+ require_relative "./view/app_cli"
9
+ require_relative "./controller/data_manager"
10
+
11
+ module RgssDb
12
+ # App option debug mode
13
+ # @return [Symbol]
14
+ APP_OPTION_DEBUG_MODE = :debug
15
+
16
+ # App option back up flag
17
+ # @return [Symbol]
18
+ APP_OPTION_BACK_UP = :backup
19
+
20
+ # App option action type
21
+ # @return [Symbol]
22
+ APP_OPTION_ACTION = :action
23
+
24
+ # App option file entries
25
+ # @return [Symbol]
26
+ APP_OPTION_FILE_ENTRIES = :files
27
+
28
+ # App option object ids
29
+ # @return [Symbol]
30
+ APP_OPTION_IDS = :ids
31
+
32
+ # App option format
33
+ # @return [Symbol]
34
+ APP_OPTION_FORMAT_TYPE = :type
35
+
36
+ # App option working directory
37
+ # @return [Symbol]
38
+ APP_OPTION_WORKING_DIR = :directory
39
+
40
+ # Export data action command name
41
+ #
42
+ # This action exports all binary files into external files
43
+ # @return [String]
44
+ APP_ACTION_EXPORT = "export"
45
+
46
+ # Export custom data action command name
47
+ #
48
+ # This action exports the supported binary files custom objects into external files
49
+ # @return [String]
50
+ APP_ACTION_EXPORT_CUSTOM = "export_custom"
51
+
52
+ # Import data action command name
53
+ #
54
+ # This action imports external files into binary files
55
+ # @return [String]
56
+ APP_ACTION_IMPORT = "import"
57
+
58
+ # Import custom data action command name
59
+ #
60
+ # This action imports external custom data files into their appropiate binary files
61
+ # @return [String]
62
+ APP_ACTION_IMPORT_CUSTOM = "import_custom"
63
+
64
+ # Default back up mode of the application
65
+ # @return [Boolean]
66
+ APP_DEFAULT_BACK_UP = true
67
+
68
+ # Default debug mode of the application
69
+ # @return [Integer]
70
+ APP_DEFAULT_DEBUG_MODE = 0
71
+
72
+ # Default file format type for the application
73
+ # @return [String]
74
+ APP_DEFAULT_FORMAT_TYPE = "YAML"
75
+
76
+ # Default working directory for the application
77
+ # @return [String]
78
+ APP_DEFAULT_WORKING_DIR = "./rgss-db"
79
+
80
+ #
81
+ # Application class
82
+ #
83
+ class App
84
+ include Strings
85
+
86
+ #
87
+ # Creates a new app instance
88
+ #
89
+ # @param data_path [String] RPG Maker database folder
90
+ # @param options [Hash<Symbol, Object>] App options hash
91
+ #
92
+ def initialize(data_path, options)
93
+ @options = process_options(options)
94
+ @data_manager = DataManager.new(data_path)
95
+ @cli = AppCli.new(
96
+ data_folder: @data_manager.path,
97
+ rgss_version: @data_manager.rgss_version,
98
+ app_version: RgssDb::VERSION
99
+ )
100
+ end
101
+
102
+ #
103
+ # Starts the app
104
+ #
105
+ def start
106
+ # Checks for debug usage to start the module or not
107
+ unless Debug.disabled?
108
+ debug_path = File.expand_path(opt_working_dir, @data_manager.path)
109
+ Debug.start(debug_path)
110
+ Debug.update_extra_info(@data_manager.path, @data_manager.rgss_version)
111
+ Debug.write_debug_header
112
+ end
113
+
114
+ # Start application logic
115
+ begin
116
+ if opt_action
117
+ # An action was given, avoid main menu loop
118
+ Debug.log_info("bypassing app menu")
119
+
120
+ # Logs current options
121
+ Debug.log_info("options: #{@options}")
122
+
123
+ # Creates the data files instances
124
+ data_files = []
125
+ case opt_action
126
+ when APP_ACTION_EXPORT
127
+ data_files = @data_manager.load_database_files
128
+
129
+ # Checks if user selected specific file entries
130
+ unless opt_file_entries.empty?
131
+ data_files = data_files.keep_if do |data_file|
132
+ opt_file_entries.any? { |entry| data_file.file?(entry) }
133
+ end
134
+ end
135
+ when APP_ACTION_EXPORT_CUSTOM
136
+ data_files = @data_manager.load_database_files.keep_if(&:customizable?)
137
+
138
+ # Checks if user selected specific file entries
139
+ unless opt_file_entries.empty?
140
+ data_files = data_files.keep_if do |data_file|
141
+ opt_file_entries.any? { |entry| data_file.file?(entry) }
142
+ end
143
+ end
144
+
145
+ # Applies any possible object IDs list for each file entry
146
+ data_files.each do |data_file|
147
+ data_file.object_ids_update(*opt_file_object_ids(data_file.file))
148
+ end
149
+ when APP_ACTION_IMPORT
150
+ data_files = @data_manager.load_extracted_files(opt_working_dir)
151
+
152
+ # Checks if user selected specific file entries
153
+ unless opt_file_entries.empty?
154
+ data_files = data_files.keep_if do |data_file|
155
+ opt_file_entries.any? { |entry| data_file.file?(entry) }
156
+ end
157
+ end
158
+ when APP_ACTION_IMPORT_CUSTOM
159
+ data_files = @data_manager.load_extracted_files_custom(opt_working_dir).keep_if(&:mergeable?)
160
+
161
+ # Checks if user selected specific file entries
162
+ unless opt_file_entries.empty?
163
+ data_files = data_files.keep_if do |data_file|
164
+ opt_file_entries.any? { |entry| data_file.file?(entry) }
165
+ end
166
+ end
167
+ end
168
+
169
+ # Perform the action for each data file created
170
+ data_files.each { |data_file| do_action(opt_action, data_file) }
171
+ else
172
+ # No action given, run the app main menu loop
173
+ Debug.log_info("running app menu")
174
+ menu_main
175
+ end
176
+ rescue Error => e
177
+ # Application error
178
+ Debug.log_exception(e, @options)
179
+ @cli.draw_empty_line
180
+ @cli.draw_error(e.message)
181
+ @cli.draw_empty_line
182
+ @cli.prompt_pause
183
+ retry
184
+ rescue StandardError => e
185
+ # Unknown error
186
+ Debug.log_exception(e, @options)
187
+ raise e
188
+ end
189
+ end
190
+
191
+ private
192
+
193
+ #
194
+ # Process the user options
195
+ #
196
+ # @param options_hash [Hash<Symbol, Object>] Options hash
197
+ #
198
+ # @return [Hash<Symbol, Object>]
199
+ #
200
+ def process_options(options_hash)
201
+ options = {}
202
+ options_hash.each_pair do |option_id, option_value|
203
+ case option_id
204
+ when APP_OPTION_DEBUG_MODE
205
+ # Process the debug mode
206
+ debug_mode_id = option_value.to_s.to_i # to 0 if invalid int
207
+ options.store(option_id, debug_mode_id)
208
+ Debug.update_debug_mode(debug_mode_id)
209
+ when APP_OPTION_ACTION
210
+ # Process the action option (case insensitive)
211
+ action = option_value.to_s
212
+ if action.casecmp?(APP_ACTION_IMPORT)
213
+ options.store(option_id, APP_ACTION_IMPORT)
214
+ elsif action.casecmp?(APP_ACTION_IMPORT_CUSTOM)
215
+ options.store(option_id, APP_ACTION_IMPORT_CUSTOM)
216
+ elsif action.casecmp?(APP_ACTION_EXPORT)
217
+ options.store(option_id, APP_ACTION_EXPORT)
218
+ elsif action.casecmp?(APP_ACTION_EXPORT_CUSTOM)
219
+ options.store(option_id, APP_ACTION_EXPORT_CUSTOM)
220
+ else
221
+ # Unknown action value
222
+ options.store(option_id, nil)
223
+ end
224
+ when APP_OPTION_FORMAT_TYPE
225
+ # Process the output file format option (case insensitive)
226
+ type = option_value.to_s.downcase.to_sym
227
+ case type
228
+ when RGSS_FORMAT_TYPE_BINARY
229
+ options.store(option_id, RGSS_FORMAT_TYPE_BINARY)
230
+ when RGSS_FORMAT_TYPE_JSON
231
+ options.store(option_id, RGSS_FORMAT_TYPE_JSON)
232
+ when RGSS_FORMAT_TYPE_YAML
233
+ options.store(option_id, RGSS_FORMAT_TYPE_YAML)
234
+ else
235
+ options.store(option_id, APP_DEFAULT_FORMAT_TYPE)
236
+ end
237
+ when APP_OPTION_WORKING_DIR
238
+ # Process the working directory option
239
+ path = Utilities.valid_path?(option_value) ? option_value : APP_DEFAULT_WORKING_DIR
240
+ options.store(option_id, path)
241
+ when APP_OPTION_FILE_ENTRIES
242
+ # Process the list of pre-selected file entries option
243
+ options.store(option_id, option_value || [])
244
+ when APP_OPTION_IDS
245
+ # Process the list of pre-selected object IDs per file entry option
246
+ options.store(option_id, {})
247
+ # Populate the hash based on the given file entries list
248
+ (options_hash[APP_OPTION_FILE_ENTRIES] || []).each_with_index do |file, index|
249
+ id_list = option_value.at(index)
250
+ options[option_id].store(file, id_list) unless id_list.nil?
251
+ end
252
+ else
253
+ # Option does not need treatment
254
+ options.store(option_id, option_value)
255
+ end
256
+ end
257
+ options
258
+ end
259
+
260
+ #
261
+ # Gets the user's backup flag
262
+ #
263
+ # @return [Boolean]
264
+ #
265
+ def opt_backup_allowed
266
+ @options[APP_OPTION_BACK_UP]
267
+ end
268
+
269
+ #
270
+ # Gets the user's action option
271
+ #
272
+ # @return [Symbol]
273
+ #
274
+ def opt_action
275
+ @options[APP_OPTION_ACTION]
276
+ end
277
+
278
+ #
279
+ # Gets the user's file format type option
280
+ #
281
+ # @return [String]
282
+ #
283
+ def opt_format_type
284
+ @options[APP_OPTION_FORMAT_TYPE]
285
+ end
286
+
287
+ #
288
+ # Gets the user's working directory option
289
+ #
290
+ # @return [String]
291
+ #
292
+ def opt_working_dir
293
+ @options[APP_OPTION_WORKING_DIR]
294
+ end
295
+
296
+ #
297
+ # Gets the user's file entries option
298
+ #
299
+ # @return [Array<String>]
300
+ #
301
+ def opt_file_entries
302
+ @options[APP_OPTION_FILE_ENTRIES]
303
+ end
304
+
305
+ #
306
+ # Gets the user's hash of object IDs and file entries
307
+ #
308
+ # @return [Hash<String, Array<Integer>>]
309
+ #
310
+ def opt_object_ids
311
+ @options[APP_OPTION_IDS]
312
+ end
313
+
314
+ #
315
+ # Gets the user's object IDs option
316
+ #
317
+ # @param file_name [String] File entry
318
+ #
319
+ # @return [Array<Integer>]
320
+ #
321
+ def opt_file_object_ids(file_name)
322
+ opt_object_ids.each_pair do |file, object_ids|
323
+ return object_ids if file.casecmp?(file_name)
324
+ end
325
+ []
326
+ end
327
+
328
+ #
329
+ # Performs the action by ``action_name`` with the given data file
330
+ #
331
+ # @param action_name [String] Action
332
+ # @param data_file [DataFile] Data file
333
+ #
334
+ # @raise [StandardError]
335
+ #
336
+ def do_action(action_name, data_file)
337
+ case action_name
338
+ when APP_ACTION_EXPORT
339
+ Debug.log_info("exporting: #{data_file} (#{data_file.serialize_file_name})")
340
+ @data_manager.save_data_file(data_file, opt_working_dir, opt_format_type)
341
+ Debug.log_info("exporting action finished!")
342
+ when APP_ACTION_EXPORT_CUSTOM
343
+ Debug.log_info("exporting (custom): #{data_file} (#{data_file.serialize_file_name})")
344
+ @data_manager.save_data_file(data_file, opt_working_dir, opt_format_type)
345
+ Debug.log_info("exporting (custom) action finished!")
346
+ when APP_ACTION_IMPORT
347
+ Debug.log_info("importing: #{data_file} (#{data_file.serialize_file_name})")
348
+
349
+ # Checks if the data file is a "full file" to avoid data loss, this error
350
+ # should never trigger since data_file should have all objects selected
351
+ # at this point for import (hardcoded), but it exists as a security measure
352
+ raise "trying to import an incompleted data file: #{data_file.inspect}" unless data_file.all_objects?
353
+
354
+ # Performs a back up creation (if allowed)
355
+ if opt_backup_allowed
356
+ Debug.log_info("creating back up file...")
357
+ @data_manager.save_database_back_up(data_file.file, opt_working_dir)
358
+ Debug.log_info("back up created")
359
+ else
360
+ Debug.log_info("back up creation is disabled!")
361
+ end
362
+
363
+ # Performs the import process
364
+ @data_manager.save_data_file(data_file, @data_manager.path, RGSS_FORMAT_TYPE_BINARY)
365
+ Debug.log_info("importing action finished!")
366
+ when APP_ACTION_IMPORT_CUSTOM
367
+ Debug.log("importing (custom): #{data_file} (#{data_file.serialize_file_name})")
368
+ database_file = @data_manager.load_database_file(data_file.type)
369
+
370
+ # Performs a back up creation (if allowed)
371
+ if opt_backup_allowed
372
+ Debug.log_info("creating back up file...")
373
+ @data_manager.save_database_back_up(database_file.file, opt_working_dir)
374
+ Debug.log_info("back up created")
375
+ else
376
+ Debug.log_info("back up creation is disabled!")
377
+ end
378
+
379
+ # Merges data file contents
380
+ database_file.merge(data_file)
381
+
382
+ # Saves the result of the merge operation
383
+ @data_manager.save_data_file(database_file, @data_manager.path, RGSS_FORMAT_TYPE_BINARY)
384
+ Debug.log_info("importing (custom) action finished!")
385
+ else
386
+ raise "action called with an unknown action name: '#{action_name}'"
387
+ end
388
+ end
389
+
390
+ #
391
+ # Main menu process
392
+ #
393
+ def menu_main
394
+ loop do
395
+ @cli.draw_app_menu(
396
+ StrMenuContents::APP_MENU_MAIN_MENU_TEXT_INFO,
397
+ breadcrumbs: [StrMenu::APP_MENU_MAIN_MENU]
398
+ )
399
+ option = @cli.prompt_select(
400
+ StrMenu::APP_MENU_ACTIONS,
401
+ StrMenu::APP_MENU_OPTIONS,
402
+ StrMenu::APP_MENU_EXIT
403
+ )
404
+ case option
405
+ when StrMenu::APP_MENU_ACTIONS
406
+ menu_actions
407
+ when StrMenu::APP_MENU_OPTIONS
408
+ menu_options
409
+ when StrMenu::APP_MENU_EXIT
410
+ submenu_exit
411
+ break
412
+ end
413
+ end
414
+ end
415
+
416
+ #
417
+ # Perform actions menu process
418
+ #
419
+ def menu_actions
420
+ loop do
421
+ @cli.draw_app_menu(
422
+ StrMenuContents::APP_MENU_ACTIONS_TEXT_INFO,
423
+ breadcrumbs: [StrMenu::APP_MENU_MAIN_MENU, StrMenu::APP_MENU_ACTIONS]
424
+ )
425
+ option = @cli.prompt_select(
426
+ StrMenu::APP_MENU_ACTIONS_EXPORT,
427
+ StrMenu::APP_MENU_ACTIONS_EXPORT_CUSTOM,
428
+ StrMenu::APP_MENU_ACTIONS_IMPORT,
429
+ StrMenu::APP_MENU_ACTIONS_IMPORT_CUSTOM,
430
+ StrMenu::APP_MENU_EXIT
431
+ )
432
+ case option
433
+ when StrMenu::APP_MENU_ACTIONS_EXPORT
434
+ submenu_export
435
+ when StrMenu::APP_MENU_ACTIONS_EXPORT_CUSTOM
436
+ submenu_export_custom
437
+ when StrMenu::APP_MENU_ACTIONS_IMPORT
438
+ submenu_import
439
+ when StrMenu::APP_MENU_ACTIONS_IMPORT_CUSTOM
440
+ submenu_import_custom
441
+ when StrMenu::APP_MENU_EXIT
442
+ submenu_exit
443
+ break
444
+ end
445
+ end
446
+ end
447
+
448
+ #
449
+ # Options menu process
450
+ #
451
+ def menu_options
452
+ loop do
453
+ @cli.draw_app_menu(
454
+ StrMenuContents::APP_MENU_OPTIONS_TEXT_INFO,
455
+ breadcrumbs: [StrMenu::APP_MENU_MAIN_MENU, StrMenu::APP_MENU_OPTIONS]
456
+ )
457
+ option = @cli.prompt_select(
458
+ StrMenu::APP_MENU_OPTIONS_SET_FORMAT_TYPE,
459
+ StrMenu::APP_MENU_OPTIONS_SET_WORKING_DIR,
460
+ StrMenu::APP_MENU_OPTIONS_SET_ENTRIES,
461
+ StrMenu::APP_MENU_OPTIONS_SET_IDS,
462
+ StrMenu::APP_MENU_OPTIONS_SHOW_OPTIONS_PRETTY,
463
+ StrMenu::APP_MENU_OPTIONS_SHOW_OPTIONS_RAW,
464
+ StrMenu::APP_MENU_EXIT
465
+ )
466
+ case option
467
+ when StrMenu::APP_MENU_OPTIONS_SET_FORMAT_TYPE
468
+ submenu_set_format_type
469
+ when StrMenu::APP_MENU_OPTIONS_SET_WORKING_DIR
470
+ submenu_set_working_dir
471
+ when StrMenu::APP_MENU_OPTIONS_SET_ENTRIES
472
+ submenu_set_entries
473
+ when StrMenu::APP_MENU_OPTIONS_SET_IDS
474
+ submenu_set_ids
475
+ when StrMenu::APP_MENU_OPTIONS_SHOW_OPTIONS_PRETTY
476
+ submenu_show_options_pretty
477
+ when StrMenu::APP_MENU_OPTIONS_SHOW_OPTIONS_RAW
478
+ submenu_show_options_raw
479
+ when StrMenu::APP_MENU_EXIT
480
+ submenu_exit
481
+ break
482
+ end
483
+ end
484
+ end
485
+
486
+ #
487
+ # Exit submenu process
488
+ #
489
+ def submenu_exit
490
+ @cli.draw_cancel_operation(StrSubMenu::EXIT_TEXT)
491
+ end
492
+
493
+ #
494
+ # Export submenu process
495
+ #
496
+ # @raise [Error]
497
+ #
498
+ def submenu_export
499
+ @cli.draw_app_submenu(
500
+ StrSubMenu::EXPORT_TEXT, StrPrompts::MULTI_SELECT_TIP_TEXT,
501
+ breadcrumbs: [StrMenu::APP_MENU_MAIN_MENU, StrMenu::APP_MENU_ACTIONS, StrMenu::APP_MENU_ACTIONS_EXPORT]
502
+ )
503
+
504
+ data_files = []
505
+ @cli.prompt_spinner(StrSubMenu::EXPORT_LOAD_FILES_TEXT) do
506
+ data_files = @data_manager.load_database_files
507
+ end
508
+ raise Error, StrSubMenu::EXPORT_LOAD_ERROR_TEXT if data_files.empty?
509
+
510
+ # Determines the list of pre-selected database files (for TTY select menu)
511
+ data_files_default = Utilities.menu_default_indexes(
512
+ data_files,
513
+ opt_file_entries
514
+ ) do |menu_option, menu_index, file_entry|
515
+ menu_option.file?(file_entry)
516
+ end
517
+
518
+ # Ask the user to select the data files
519
+ # @type [Array<DataFile>]
520
+ data_files_selected = @cli.prompt_select_multi(
521
+ *data_files, default: data_files_default
522
+ )
523
+ raise Error, StrSubMenu::EXPORT_NO_FILES_ERROR_TEXT if data_files_selected.empty?
524
+
525
+ # Confirm operation
526
+ unless @cli.prompt_confirm?
527
+ @cli.draw_cancel_operation
528
+ @cli.prompt_pause
529
+ return
530
+ end
531
+
532
+ # Perform operation
533
+ data_files_selected.each do |data_file|
534
+ @cli.prompt_spinner(format(StrSubMenu::EXPORT_ACTION_TEXT, data_file)) do
535
+ do_action(APP_ACTION_EXPORT, data_file)
536
+ end
537
+ end
538
+
539
+ @cli.draw_success_operation
540
+ @cli.prompt_pause
541
+ end
542
+
543
+ #
544
+ # Export custom submenu process
545
+ #
546
+ # @raise [Error]
547
+ #
548
+ def submenu_export_custom
549
+ @cli.draw_app_submenu(
550
+ StrSubMenu::EXPORT_CUSTOM_TEXT, StrPrompts::MULTI_SELECT_TIP_TEXT,
551
+ breadcrumbs: [StrMenu::APP_MENU_MAIN_MENU, StrMenu::APP_MENU_ACTIONS, StrMenu::APP_MENU_ACTIONS_EXPORT_CUSTOM]
552
+ )
553
+
554
+ data_files = []
555
+ @cli.prompt_spinner(StrSubMenu::EXPORT_LOAD_FILES_TEXT) do
556
+ data_files = @data_manager.load_database_files.keep_if(&:customizable?)
557
+ end
558
+ raise Error, StrSubMenu::EXPORT_LOAD_ERROR_TEXT if data_files.empty?
559
+
560
+ # Determines the list of pre-selected database files (for TTY select menu)
561
+ data_files_default = Utilities.menu_default_indexes(
562
+ data_files,
563
+ opt_file_entries
564
+ ) do |menu_option, menu_index, file_entry|
565
+ menu_option.file?(file_entry)
566
+ end
567
+
568
+ # Ask the user to select the data files
569
+ # @type [Array<DataFile>]
570
+ data_files_selected = @cli.prompt_select_multi(
571
+ *data_files, default: data_files_default
572
+ )
573
+ raise Error, StrSubMenu::EXPORT_NO_FILES_ERROR_TEXT if data_files_selected.empty?
574
+
575
+ # Determine the list of object IDs for each data file that supports it
576
+ data_files_selected.each do |data_file|
577
+ data_file_list = data_file.to_list
578
+ next if data_file_list.nil?
579
+ next unless @cli.prompt_confirm?(format(StrSubMenu::EXPORT_CUSTOM_SELECT_OBJ_ID_TEXT, data_file))
580
+
581
+ data_file_list_default = Utilities.menu_default_indexes(
582
+ data_file_list,
583
+ opt_file_object_ids(data_file.file)
584
+ )
585
+ data_file_list_selected = @cli.prompt_select_multi(
586
+ *data_file_list,
587
+ default: data_file_list_default
588
+ )
589
+ data_file.object_ids_update(data_file.convert_list_to_ids(data_file_list_selected))
590
+ end
591
+
592
+ # Confirm operation
593
+ unless @cli.prompt_confirm?
594
+ @cli.draw_cancel_operation
595
+ @cli.prompt_pause
596
+ return
597
+ end
598
+
599
+ # Perform operation
600
+ data_files_selected.each do |data_file|
601
+ @cli.prompt_spinner(format(StrSubMenu::EXPORT_CUSTOM_ACTION_TEXT, data_file)) do
602
+ do_action(APP_ACTION_EXPORT_CUSTOM, data_file)
603
+ end
604
+ end
605
+
606
+ @cli.draw_success_operation
607
+ @cli.prompt_pause
608
+ end
609
+
610
+ #
611
+ # Import submenu process
612
+ #
613
+ # @raise [Error]
614
+ #
615
+ def submenu_import
616
+ @cli.draw_app_submenu(
617
+ StrSubMenu::IMPORT_TEXT, StrPrompts::MULTI_SELECT_TIP_TEXT,
618
+ breadcrumbs: [StrMenu::APP_MENU_MAIN_MENU, StrMenu::APP_MENU_ACTIONS, StrMenu::APP_MENU_ACTIONS_IMPORT]
619
+ )
620
+
621
+ data_files = []
622
+ @cli.prompt_spinner(StrSubMenu::IMPORT_LOAD_FILES_TEXT) do
623
+ data_files = @data_manager.load_extracted_files(opt_working_dir)
624
+ end
625
+ raise Error, StrSubMenu::IMPORT_LOAD_ERROR_TEXT if data_files.empty?
626
+
627
+ # Determines the list of pre-selected files (for TTY select menu)
628
+ data_files_default = Utilities.menu_default_indexes(
629
+ data_files,
630
+ opt_file_entries
631
+ ) do |menu_option, menu_index, file_entry|
632
+ menu_option.file?(file_entry)
633
+ end
634
+
635
+ # Ask the user to select the data files
636
+ # @type [Array<DataFile>]
637
+ data_files_selected = @cli.prompt_select_multi(
638
+ *data_files, default: data_files_default
639
+ )
640
+ raise Error, StrSubMenu::IMPORT_NO_FILES_ERROR_TEXT if data_files_selected.empty?
641
+
642
+ # Confirm operation
643
+ unless @cli.prompt_confirm?
644
+ @cli.draw_cancel_operation
645
+ @cli.prompt_pause
646
+ return
647
+ end
648
+
649
+ # Perform operation
650
+ data_files_selected.each do |data_file|
651
+ @cli.prompt_spinner(format(StrSubMenu::IMPORT_ACTION_TEXT, data_file)) do
652
+ do_action(APP_ACTION_IMPORT, data_file)
653
+ end
654
+ end
655
+
656
+ @cli.draw_success_operation
657
+ @cli.prompt_pause
658
+ end
659
+
660
+ #
661
+ # Import custom submenu process
662
+ #
663
+ # @raise [Error]
664
+ #
665
+ def submenu_import_custom
666
+ @cli.draw_app_submenu(
667
+ StrSubMenu::IMPORT_CUSTOM_TEXT, StrPrompts::MULTI_SELECT_TIP_TEXT,
668
+ breadcrumbs: [StrMenu::APP_MENU_MAIN_MENU, StrMenu::APP_MENU_ACTIONS, StrMenu::APP_MENU_ACTIONS_IMPORT_CUSTOM]
669
+ )
670
+
671
+ data_files = []
672
+ @cli.prompt_spinner(StrSubMenu::IMPORT_CUSTOM_LOAD_FILES_TEXT) do
673
+ data_files = @data_manager.load_extracted_files_custom(opt_working_dir).keep_if(&:mergeable?)
674
+ end
675
+ raise Error, StrSubMenu::IMPORT_LOAD_ERROR_TEXT if data_files.empty?
676
+
677
+ # Determines the list of pre-selected files (for TTY select menu)
678
+ data_files_default = Utilities.menu_default_indexes(
679
+ data_files,
680
+ opt_file_entries
681
+ ) do |menu_option, menu_index, file_entry|
682
+ menu_option.file?(file_entry)
683
+ end
684
+
685
+ # Ask the user to select the data files
686
+ # @type [Array<DataFile>]
687
+ data_files_selected = @cli.prompt_select_multi(
688
+ *data_files, default: data_files_default
689
+ )
690
+ raise Error, StrSubMenu::IMPORT_NO_FILES_ERROR_TEXT if data_files_selected.empty?
691
+
692
+ # Confirm operation
693
+ unless @cli.prompt_confirm?
694
+ @cli.draw_cancel_operation
695
+ @cli.prompt_pause
696
+ return
697
+ end
698
+
699
+ # Perform operation
700
+ data_files_selected.each do |data_file|
701
+ @cli.prompt_spinner(format(StrSubMenu::IMPORT_CUSTOM_ACTION_TEXT, data_file)) do
702
+ do_action(APP_ACTION_IMPORT_CUSTOM, data_file)
703
+ end
704
+ end
705
+
706
+ @cli.draw_success_operation
707
+ @cli.prompt_pause
708
+ end
709
+
710
+ #
711
+ # Set file format type submenu process
712
+ #
713
+ def submenu_set_format_type
714
+ @cli.draw_app_submenu(
715
+ StrSubMenu::SET_FORMAT_TYPE_TEXT, StrPrompts::SELECT_TIP_TEXT,
716
+ breadcrumbs: [
717
+ StrMenu::APP_MENU_MAIN_MENU,
718
+ StrMenu::APP_MENU_OPTIONS,
719
+ StrMenu::APP_MENU_OPTIONS_SET_FORMAT_TYPE
720
+ ]
721
+ )
722
+
723
+ # Ask user to select a file format
724
+ file_format = @cli.prompt_select(
725
+ RGSS_FORMAT_TYPE_YAML,
726
+ RGSS_FORMAT_TYPE_JSON,
727
+ RGSS_FORMAT_TYPE_BINARY
728
+ )
729
+
730
+ # Confirm operation
731
+ if @cli.prompt_confirm?
732
+ @options.store(APP_OPTION_FORMAT_TYPE, file_format)
733
+ @cli.draw_success_operation(format(StrSubMenu::SET_FORMAT_TYPE_UPDATE_TEXT, file_format))
734
+ else
735
+ @cli.draw_cancel_operation
736
+ end
737
+ @cli.prompt_pause
738
+ end
739
+
740
+ #
741
+ # Set working directory submenu process
742
+ #
743
+ def submenu_set_working_dir
744
+ @cli.draw_app_submenu(
745
+ StrSubMenu::SET_WORKING_DIR_TEXT, StrPrompts::ASK_TIP_TEXT,
746
+ breadcrumbs: [
747
+ StrMenu::APP_MENU_MAIN_MENU,
748
+ StrMenu::APP_MENU_OPTIONS,
749
+ StrMenu::APP_MENU_OPTIONS_SET_WORKING_DIR
750
+ ]
751
+ )
752
+
753
+ # Ask user to type the new app working dir
754
+ working_dir = @cli.prompt_ask(
755
+ StrSubMenu::SET_WORKING_DIR_ASK_TEXT,
756
+ default: APP_DEFAULT_WORKING_DIR,
757
+ value: opt_working_dir,
758
+ validate_text: StrSubMenu::SET_WORKING_DIR_ASK_FAIL_TEXT
759
+ ) do |input|
760
+ Utilities.valid_path?(input)
761
+ end
762
+
763
+ # Confirm operation
764
+ if @cli.prompt_confirm?
765
+ @options.store(APP_OPTION_WORKING_DIR, working_dir)
766
+ @cli.draw_success_operation(format(StrSubMenu::SET_WORKING_DIR_UPDATE_TEXT, working_dir))
767
+ else
768
+ @cli.draw_cancel_operation
769
+ end
770
+ @cli.prompt_pause
771
+ end
772
+
773
+ #
774
+ # Set pre-selected file entries submenu process
775
+ #
776
+ def submenu_set_entries
777
+ @cli.draw_app_submenu(
778
+ StrSubMenu::SET_ENTRIES_TEXT, StrPrompts::ASK_TIP_TEXT,
779
+ breadcrumbs: [
780
+ StrMenu::APP_MENU_MAIN_MENU,
781
+ StrMenu::APP_MENU_OPTIONS,
782
+ StrMenu::APP_MENU_OPTIONS_SET_ENTRIES
783
+ ]
784
+ )
785
+
786
+ # Ask user to type the list of entries
787
+ # @type [Array<String>]
788
+ entries = @cli.prompt_ask(
789
+ StrSubMenu::SET_ENTRIES_ASK_TEXT,
790
+ default: [],
791
+ value: opt_file_entries.join(","),
792
+ convert: :list
793
+ )
794
+
795
+ # Confirm operation
796
+ if @cli.prompt_confirm?
797
+ entries.uniq! # Make the entries unique before saving it
798
+ @options.store(APP_OPTION_FILE_ENTRIES, entries)
799
+ @cli.draw_success_operation(format(StrSubMenu::SET_ENTRIES_UPDATE_TEXT, entries))
800
+
801
+ # Since the file entries list was updated, we should drop the key-value pairs
802
+ # from the hash of object IDs that doesn't exist in the current file entry list
803
+ @options[APP_OPTION_IDS].delete_if do |file_entry, ids_array|
804
+ !entries.include?(file_entry)
805
+ end
806
+ else
807
+ @cli.draw_cancel_operation
808
+ end
809
+ @cli.prompt_pause
810
+ end
811
+
812
+ #
813
+ # Set pre-selected object IDs submenu process
814
+ #
815
+ # @raise [Error]
816
+ #
817
+ def submenu_set_ids
818
+ @cli.draw_app_submenu(
819
+ StrSubMenu::SET_IDS_TEXT, StrPrompts::MULTI_SELECT_TIP_TEXT, StrPrompts::ASK_TIP_TEXT,
820
+ breadcrumbs: [
821
+ StrMenu::APP_MENU_MAIN_MENU,
822
+ StrMenu::APP_MENU_OPTIONS,
823
+ StrMenu::APP_MENU_OPTIONS_SET_IDS
824
+ ]
825
+ )
826
+
827
+ # Checks if the user's file entries list is empty
828
+ raise Error, StrSubMenu::SET_IDS_NO_FILES_ERROR_TEXT if opt_file_entries.empty?
829
+
830
+ # Ask user to type the list of entries
831
+ # @type [Array<String>]
832
+ entries = @cli.prompt_select_multi(
833
+ *opt_file_entries
834
+ )
835
+ raise Error, StrSubMenu::SET_IDS_NO_FILES_SELECTED_ERROR_TEXT if entries.empty?
836
+
837
+ # @type [Hash<String, Array<Integer>>]
838
+ ids = opt_object_ids
839
+
840
+ # Ask the user for the list of object IDs for each file entry selected
841
+ entries.each do |file_entry|
842
+ current_ids = opt_file_object_ids(file_entry)
843
+ # @type [Array<Integer>]
844
+ user_ids = @cli.prompt_ask(
845
+ format(StrSubMenu::SET_IDS_ASK_IDS_TEXT, file_entry),
846
+ default: [],
847
+ value: current_ids.join(","),
848
+ convert: :int_list
849
+ )
850
+ # Process the user input
851
+ if user_ids.empty?
852
+ # Deletes the file entry if the list of IDs is empty
853
+ ids.delete(file_entry)
854
+ else
855
+ # Cleans any item that is not an integer
856
+ user_ids.delete_if { |id| !id.is_a?(Integer) }
857
+ # Removes any dupes
858
+ user_ids.uniq!
859
+ # Saves the list of IDs
860
+ ids.store(file_entry, user_ids)
861
+ end
862
+ end
863
+
864
+ # Confirm operation
865
+ if @cli.prompt_confirm?
866
+ @options.store(APP_OPTION_IDS, ids)
867
+ @cli.draw_success_operation(format(StrSubMenu::SET_IDS_UPDATE_TEXT, ids))
868
+ else
869
+ @cli.draw_cancel_operation
870
+ end
871
+ @cli.prompt_pause
872
+ end
873
+
874
+ #
875
+ # Show app options (pretty) submenu process
876
+ #
877
+ def submenu_show_options_pretty
878
+ @cli.draw_app_submenu(
879
+ StrSubMenu::SHOW_OPTIONS_PRETTY_TEXT,
880
+ breadcrumbs: [
881
+ StrMenu::APP_MENU_MAIN_MENU,
882
+ StrMenu::APP_MENU_OPTIONS,
883
+ StrMenu::APP_MENU_OPTIONS_SHOW_OPTIONS_PRETTY
884
+ ]
885
+ )
886
+
887
+ # Prepares the table rows
888
+ rows = []
889
+ @options.each_pair do |option_id, option_value|
890
+ # For some reason, TTY::Table does not like hashes
891
+ # Hence this workaround to convert it into an array
892
+ rows << if option_value.is_a?(Hash)
893
+ [option_id, option_value.to_a]
894
+ else
895
+ [option_id, option_value]
896
+ end
897
+ end
898
+
899
+ # Shows the option in a table
900
+ @cli.draw_table(
901
+ [StrSubMenu::SHOW_OPTIONS_COLUMN_1, StrSubMenu::SHOW_OPTIONS_COLUMN_2],
902
+ *rows
903
+ )
904
+ @cli.draw_success_operation
905
+ @cli.prompt_pause
906
+ end
907
+
908
+ #
909
+ # Show app options (raw) submenu process
910
+ #
911
+ def submenu_show_options_raw
912
+ @cli.draw_app_submenu(
913
+ StrSubMenu::SHOW_OPTIONS_RAW_TEXT,
914
+ breadcrumbs: [
915
+ StrMenu::APP_MENU_MAIN_MENU,
916
+ StrMenu::APP_MENU_OPTIONS,
917
+ StrMenu::APP_MENU_OPTIONS_SHOW_OPTIONS_RAW
918
+ ]
919
+ )
920
+
921
+ @options.each_pair do |option_id, option_value|
922
+ @cli.draw("#{option_id} => #{option_value}")
923
+ end
924
+ @cli.draw_success_operation
925
+ @cli.prompt_pause
926
+ end
927
+ end
928
+ end