rgss_db 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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