diff --git a/lib/backend.rb b/lib/backend.rb index fe063ca..6909cf2 100644 --- a/lib/backend.rb +++ b/lib/backend.rb @@ -2,8 +2,8 @@ module TAC class Backend attr_reader :config, :settings, :tacnet def initialize - @config = load_config - @settings = load_settings + load_settings + load_config(@settings.config) if @settings.config @tacnet = TACNET.new @config_changed = false @@ -19,43 +19,35 @@ module TAC @config_changed end - def load_config - if File.exist?(TAC::CONFIG_PATH) - return TAC::Config.new - else - write_default_config - load_config + def load_config(name) + if File.exist?("#{TAC::CONFIGS_PATH}/#{name}.json") + @config = TAC::Config.new(name) end end - def update_config - @config = load_config - $window.current_state.populate_groups_list - end - - def save_config + def save_config(name) json = @config.to_json - File.open(TAC::CONFIG_PATH, "w") { |f| f.write json } + File.open("#{TAC::CONFIGS_PATH}/#{name}.json", "w") { |f| f.write json } @config_changed = false end def upload_config - if @tacnet.connected? + if @config && @tacnet.connected? json = @config.to_json @tacnet.puts(TAC::TACNET::PacketHandler.packet_upload_config(json)) end end def download_config - if @tacnet.connected? + if @config && @tacnet.connected? @tacnet.puts(TAC::TACNET::PacketHandler.packet_download_config) end end - def write_default_config - File.open(TAC::CONFIG_PATH, "w") do |f| + def write_new_config(name) + File.open("#{TAC::CONFIGS_PATH}/#{name}.json", "w") do |f| f.write JSON.dump( { config: { @@ -64,23 +56,19 @@ module TAC spec_version: TAC::CONFIG_SPEC_VERSION, hostname: TACNET::DEFAULT_HOSTNAME, port: TACNET::DEFAULT_PORT, - presets: [], }, data: { groups: [], + presets: { + groups: [], + actions: [], + }, }, } ) end end - def refresh_config - load_config - - $window.states.clear - $window.push_state(Editor) - end - def refresh_tacnet_status $window.current_state.refresh_tacnet_status end @@ -96,7 +84,7 @@ module TAC def load_settings if File.exist?(TAC::SETTINGS_PATH) - return TAC::Settings.new + @settings = TAC::Settings.new else write_default_settings load_settings @@ -118,6 +106,7 @@ module TAC data: { hostname: TACNET::DEFAULT_HOSTNAME, port: TACNET::DEFAULT_PORT, + config: nil, } } ) diff --git a/lib/config.rb b/lib/config.rb index e53c571..c0d2921 100644 --- a/lib/config.rb +++ b/lib/config.rb @@ -1,11 +1,12 @@ module TAC class Config - attr_reader :configuration, :groups - def initialize + attr_reader :configuration, :groups, :presets + def initialize(name) @configuration = nil @groups = nil + @presets = nil - parse(File.read(TAC::CONFIG_PATH)) + parse(File.read("#{TAC::CONFIGS_PATH}/#{name}.json")) end def parse(json) @@ -26,24 +27,24 @@ module TAC def parse_spec_current(data) @configuration = Configuration.from_json(data[:config]) @groups = data.dig(:data, :groups).map { |g| Group.from_json(g) } + @presets = Presets.from_json(data.dig(:data, :presets)) end def to_json(*args) { config: @configuration, data: { - groups: @groups + groups: @groups, + presets: @presets, } }.to_json(*args) end class Configuration attr_accessor :created_at, :updated_at, :spec_version - attr_reader :presets - def initialize(created_at:, updated_at:, spec_version:, presets:) + def initialize(created_at:, updated_at:, spec_version:) @created_at, @updated_at = created_at, updated_at @spec_version = spec_version - @presets = presets end def to_json(*args) @@ -51,26 +52,36 @@ module TAC created_at: @created_at, updated_at: @updated_at, spec_version: @spec_version, - presets: @presets }.to_json(*args) end def self.from_json(hash) Configuration.new( - created_at: hash[:created_at], updated_at: hash[:updated_at], - spec_version: hash[:spec_version], presets: hash[:presets].map { |ps| Preset.from_json(ps) } + created_at: hash[:created_at], + updated_at: hash[:updated_at], + spec_version: hash[:spec_version] ) end end - class Preset - def initialize() + class Presets + attr_reader :groups, :actions + def initialize(groups:, actions:) + @groups, @actions = groups, actions end def to_json(*args) + { + groups: @groups, + actions: @actions, + }.to_json(*args) end def self.from_json(hash) + Presets.new( + groups: hash[:groups].map { |group| Group.from_json(group) }, + actions: hash[:actions].map { |action| Action.from_json(action) }, + ) end end diff --git a/lib/settings.rb b/lib/settings.rb index fa20a6b..1ef9962 100644 --- a/lib/settings.rb +++ b/lib/settings.rb @@ -1,6 +1,6 @@ module TAC class Settings - attr_accessor :hostname, :port + attr_accessor :hostname, :port, :config def initialize parse(File.read(TAC::SETTINGS_PATH)) end @@ -10,6 +10,7 @@ module TAC @hostname = data[:data][:hostname] @port = data[:data][:port] + @config = data[:data][:config] end def to_json(*args) @@ -17,6 +18,7 @@ module TAC data: { hostname: @hostname, port: @port, + config: @config, } }.to_json(*args) end diff --git a/lib/states/editor.rb b/lib/states/editor.rb index 62a101f..3b2c2da 100644 --- a/lib/states/editor.rb +++ b/lib/states/editor.rb @@ -32,15 +32,18 @@ module TAC button get_image("#{TAC::ROOT_PATH}/media/icons/menuList.png"), image_width: THEME_ICON_SIZE, margin_left: 10, tip: "Manage presets" do push_state(ManagePresets) end + button get_image("#{TAC::ROOT_PATH}/media/icons/wrench.png"), image_width: THEME_ICON_SIZE, margin_left: 10, tip: "Manage configurations" do + push_state(ManageConfigurations) + end button get_image("#{TAC::ROOT_PATH}/media/icons/save.png"), image_width: THEME_ICON_SIZE, margin_left: 10, tip: "Save config and settings to disk" do - window.backend.save_config + window.backend.save_config(window.backend.settings.config) window.backend.save_settings end button get_image("#{TAC::ROOT_PATH}/media/icons/export.png"), image_width: THEME_ICON_SIZE, margin_left: 10, tip: "Upload local config to remote, if connected." do - window.backend.upload_config + window.backend.upload_config(window.backend.settings.config) end button get_image("#{TAC::ROOT_PATH}/media/icons/import.png"), image_width: THEME_ICON_SIZE, margin_left: 10, tip: "Download remote config, if connected." do - window.backend.download_config + window.backend.download_config(window.backend.settings.config) end end end @@ -86,7 +89,7 @@ module TAC end end - flow width: 1.0, height: 0.9 do + @content = flow width: 1.0, height: 0.9 do background THEME_CONTENT_BACKGROUND stack width: 0.333, height: 1.0, border_thickness: 1, border_color: [0, Gosu::Color::BLACK, 0, 0] do flow do @@ -167,7 +170,11 @@ module TAC end end - populate_groups_list + unless window.backend.settings.config + push_state(ManageConfigurations) + else + populate_groups_list + end @tacnet_status_monitor = CyberarmEngine::Timer.new(250) do case window.backend.tacnet.status @@ -283,7 +290,7 @@ module TAC @groups_list.clear do groups.each_with_index do |group, i| - flow width: 1.0, padding_left: THEME_ITEM_PADDING, padding_right: THEME_ITEM_PADDING, padding_top: THEME_ITEM_PADDING, padding_bottom: THEME_ITEM_PADDING do + flow width: 1.0, **THEME_ITEM_CONTAINER_PADDING do background i.even? ? THEME_EVEN_COLOR : THEME_ODD_COLOR button group.name, width: 0.855 do @@ -296,7 +303,7 @@ module TAC @variables_list.clear end - button get_image("#{TAC::ROOT_PATH}/media/icons/wrench.png"), image_width: THEME_ICON_SIZE, tip: "Edit group" do + button get_image("#{TAC::ROOT_PATH}/media/icons/gear.png"), image_width: THEME_ICON_SIZE, tip: "Edit group" do push_state(Dialog::NamePromptDialog, title: "Rename Group", renaming: group, list: window.backend.config.groups, callback_method: method(:update_group)) end button get_image("#{TAC::ROOT_PATH}/media/icons/trashcan.png"), image_width: THEME_ICON_SIZE, tip: "Delete group", **THEME_DANGER_BUTTON do @@ -312,7 +319,7 @@ module TAC @actions_list.clear do actions.each_with_index do |action, i| - flow width: 1.0, padding_left: THEME_ITEM_PADDING, padding_right: THEME_ITEM_PADDING, padding_top: THEME_ITEM_PADDING, padding_bottom: THEME_ITEM_PADDING do + flow width: 1.0, **THEME_ITEM_CONTAINER_PADDING do background i.even? ? THEME_EVEN_COLOR : THEME_ODD_COLOR button action.name, width: 0.8 do @@ -324,7 +331,7 @@ module TAC toggle_button tip: "Enable action" - button get_image("#{TAC::ROOT_PATH}/media/icons/wrench.png"), image_width: THEME_ICON_SIZE, tip: "Edit action" do + button get_image("#{TAC::ROOT_PATH}/media/icons/gear.png"), image_width: THEME_ICON_SIZE, tip: "Edit action" do push_state(Dialog::NamePromptDialog, title: "Rename Action", renaming: action, list: @active_group.actions, callback_method: method(:update_action)) end button get_image("#{TAC::ROOT_PATH}/media/icons/trashcan.png"), image_width: THEME_ICON_SIZE, tip: "Delete action", **THEME_DANGER_BUTTON do @@ -340,7 +347,7 @@ module TAC @variables_list.clear do variables.each_with_index do |variable, i| - flow width: 1.0, padding_left: THEME_ITEM_PADDING, padding_right: THEME_ITEM_PADDING, padding_top: THEME_ITEM_PADDING, padding_bottom: THEME_ITEM_PADDING do + flow width: 1.0, **THEME_ITEM_CONTAINER_PADDING do background i.even? ? THEME_EVEN_COLOR : THEME_ODD_COLOR button "#{variable.name} [Type: #{variable.type}, Value: #{variable.value}]", width: 0.925, tip: "Edit variable" do @@ -353,6 +360,19 @@ module TAC end end end + + def refresh_config + @active_group = nil + @active_group_label.value = "" + @active_action = nil + @active_action_label.value = "" + + @groups_list.clear + @actions_list.clear + @variables_list.clear + + populate_groups_list + end end end end \ No newline at end of file diff --git a/lib/states/manage_configurations.rb b/lib/states/manage_configurations.rb new file mode 100644 index 0000000..10319b5 --- /dev/null +++ b/lib/states/manage_configurations.rb @@ -0,0 +1,84 @@ +module TAC + class States + class ManageConfigurations < CyberarmEngine::GuiState + def setup + theme(THEME) + stack width: 1.0, height: 0.1 do + background THEME_HEADER_BACKGROUND + label "#{TAC::NAME} ― Manage Configurations", bold: true, text_size: THEME_HEADING_TEXT_SIZE + flow do + button "Close" do + if window.backend.settings.config + window.backend.load_config(window.backend.settings.config) + + pop_state + + window.current_state.refresh_config + else + push_state(Dialog::AlertDialog, title: "No Config Loaded", message: "A config must be loaded.") + end + end + + label "Current Configuration: " + @config_label = label window.backend.settings.config + end + end + + stack width: 1.0, height: 0.9 do + background THEME_CONTENT_BACKGROUND + flow do + label "Configurations", text_size: THEME_SUBHEADING_TEXT_SIZE + button get_image("#{TAC::ROOT_PATH}/media/icons/plus.png"), image_width: 18, tip: "Add configuration" do + push_state(Dialog::NamePromptDialog, title: "Config Name", callback_method: proc { |name| + window.backend.write_new_config(name) + + change_config(name) + populate_configs + }) + end + end + + @configs_list = stack width: 1.0 do + end + end + + populate_configs + end + + def populate_configs + @configs_list.clear do + Dir.glob("#{TAC::CONFIGS_PATH}/*.json").each_with_index do |config_file, i| + flow width: 1.0, **THEME_ITEM_CONTAINER_PADDING do + background i.even? ? THEME_EVEN_COLOR : THEME_ODD_COLOR + + name = File.basename(config_file, ".json") + + button "#{name}", width: 0.965 do + change_config(name) + end + + button get_image("#{TAC::ROOT_PATH}/media/icons/trashcan.png"), image_width: THEME_ICON_SIZE, **THEME_DANGER_BUTTON, tip: "Delete configuration" do + push_state(Dialog::ConfirmDialog, title: "Delete Config?", callback_method: proc { + File.delete("#{TAC::CONFIGS_PATH}/#{name}.json") + + if window.backend.settings.config == name + change_config(nil) + end + + populate_configs + }) + end + end + end + end + end + + def change_config(name) + window.backend.settings.config = name + window.backend.save_settings + + @config_label.value = name.to_s + end + end + end +end \ No newline at end of file diff --git a/lib/tac.rb b/lib/tac.rb index 77675c7..e36fef4 100644 --- a/lib/tac.rb +++ b/lib/tac.rb @@ -1,6 +1,6 @@ module TAC ROOT_PATH = File.expand_path("../..", __FILE__) - CONFIG_PATH = "#{ROOT_PATH}/data/config.json" + CONFIGS_PATH = "#{ROOT_PATH}/data/configs" SETTINGS_PATH = "#{ROOT_PATH}/data/settings.json" CONFIG_SPEC_VERSION = 2 diff --git a/lib/tacnet/packet_handler.rb b/lib/tacnet/packet_handler.rb index 3fcd1d2..eec54fc 100644 --- a/lib/tacnet/packet_handler.rb +++ b/lib/tacnet/packet_handler.rb @@ -81,7 +81,7 @@ module TAC $window.backend.tacnet.puts(PacketHandler.packet_upload_config(json)) else if $server.active_client && $server.active_client.connected? - json = File.read(TAC::CONFIG_PATH) + json = File.read(TAC::CONFIGS_PATH) $server.active_client.puts(PacketHandler.packet_upload_config(json)) end end diff --git a/lib/tacnet/server.rb b/lib/tacnet/server.rb index a174f62..6dd0430 100644 --- a/lib/tacnet/server.rb +++ b/lib/tacnet/server.rb @@ -71,7 +71,7 @@ module TAC @active_client = client # TODO: Backup local config # SEND CONFIG - config = File.read(TAC::CONFIG_PATH) + config = File.read(TAC::CONFIGS_PATH) @active_client.puts(PacketHandler.packet_handshake(@active_client.uuid)) @active_client.puts(PacketHandler.packet_upload_config(config)) diff --git a/lib/theme.rb b/lib/theme.rb index b6b99ba..530a55b 100644 --- a/lib/theme.rb +++ b/lib/theme.rb @@ -40,6 +40,12 @@ module TAC THEME_HEADING_TEXT_SIZE = 32 THEME_SUBHEADING_TEXT_SIZE = 28 THEME_ITEM_PADDING = 8 + THEME_ITEM_CONTAINER_PADDING = { + padding_left: THEME_ITEM_PADDING, + padding_right: THEME_ITEM_PADDING, + padding_top: THEME_ITEM_PADDING, + padding_bottom: THEME_ITEM_PADDING + } THEME_EVEN_COLOR = Gosu::Color.new(0xff_606060) THEME_ODD_COLOR = Gosu::Color.new(0xff_202020) THEME_CONTENT_BACKGROUND = Gosu::Color.new(0x88_007f3f) diff --git a/timecrafters_configuration_tool.rb b/timecrafters_configuration_tool.rb index c13cdde..b763b3d 100644 --- a/timecrafters_configuration_tool.rb +++ b/timecrafters_configuration_tool.rb @@ -14,6 +14,7 @@ require_relative "lib/states/boot" require_relative "lib/states/editor" require_relative "lib/states/simulator" require_relative "lib/states/manage_presets" +require_relative "lib/states/manage_configurations" require_relative "lib/simulator/robot" require_relative "lib/simulator/field" require_relative "lib/simulator/simulation"