config.lua
1 --[[ 2 ToasterGen Spin 3 4 Copyright (C) 2025 Clifton Toaster Reid <cliftontreid@duck.com> 5 6 This library is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 ]] 11 12 local completion = require("cc.completion") 13 local expect = require "cc.expect".expect 14 15 local config = {} 16 17 local function choice_impl(text, choices, add_space) 18 expect(1, text, "string") 19 expect(2, choices, "table") 20 expect(3, add_space, "boolean", "nil") 21 local results = {} 22 for n = 1, #choices do 23 local option = choices[n] 24 if #option + (add_space and 1 or 0) > #text and option:sub(1, #text) == text then 25 local result = option:sub(#text + 1) 26 if add_space then 27 table.insert(results, result .. " ") 28 else 29 table.insert(results, result) 30 end 31 end 32 end 33 return results 34 end 35 36 local function peripheral_extended(text, add_space) 37 expect(1, text, "string") 38 expect(2, add_space, "boolean", "nil") 39 40 local perifs = peripheral.getNames(); 41 -- Add directions to the list of peripherals 42 local sides = { "top", "bottom", "left", "right", "front", "back" } 43 for _, side in ipairs(sides) do 44 table.insert(perifs, side) 45 end 46 return choice_impl(text, perifs, add_space) 47 end 48 49 --- Asks the user for a yes or no response 50 ---@param message string The message to display 51 ---@return boolean 52 function config.askYesNo(message) 53 expect(1, message, "string") 54 local options = { "yes", "no" } 55 while true do 56 write(message .. " [Y/N]: ") 57 local response = string.lower(read(nil, nil, function(text) 58 return completion.choice(text, options) 59 end)) 60 if response == "yes" or response == "y" then 61 return true 62 elseif response == "no" or response == "n" then 63 return false 64 end 65 end 66 end 67 68 --- Asks the user for a peripheral 69 --- @param message string The message to display 70 --- @return string 71 function config.askPeripheral(message, expectedType) 72 expect(1, message, "string") 73 expect(2, expectedType, "string", "nil") 74 while true do 75 print(message .. ": ") 76 local response = read(nil, nil, peripheral_extended) 77 if response and peripheral.getType(response) then 78 if expectedType and peripheral.getType(response) ~= expectedType then 79 print("The peripheral is not of the expected type: " .. expectedType) 80 -- retry without recursion 81 else 82 return response 83 end 84 end 85 end 86 end 87 88 --- Ask monitor 89 --- @param message string The message to display 90 --- @return string 91 function config.askMonitor(message) 92 expect(1, message, "string") 93 while true do 94 print(message .. ": ") 95 local response = read(nil, nil, peripheral_extended) 96 if response and peripheral.getType(response) then 97 if peripheral.getType(response) == "monitor" then 98 local monitor = peripheral.wrap(response) 99 if monitor.isColour() then 100 monitor.setBackgroundColor(colors.red) 101 monitor.clear() 102 config.askYesNo("Is the correct monitor red?") 103 monitor.setBackgroundColor(colors.black) 104 monitor.clear() 105 return response 106 else 107 print("The monitor does not support color") 108 -- retry without recursion 109 end 110 else 111 print("The peripheral is not a monitor") 112 -- retry without recursion 113 end 114 end 115 end 116 end 117 118 -- Helper function to ask for user input 119 function config.askInput(message, default) 120 expect(1, message, "string") 121 expect(2, default, "nil", "string", "number") 122 term.clear() 123 term.setCursorPos(1, 1) 124 print(message) 125 if default ~= nil then 126 write("Default: " .. tostring(default) .. " > ") 127 else 128 write("> ") 129 end 130 local input = read() 131 if input == "" and default ~= nil then 132 return default 133 end 134 return input 135 end 136 137 -- Helper function to ask for a numeric input 138 function config.askNumber(message, default) 139 expect(1, message, "string") 140 expect(2, default, "nil", "number") 141 while true do 142 local input = config.askInput(message, default) 143 local num = tonumber(input) 144 if num ~= nil then 145 return num 146 end 147 print("Please enter a valid number.") 148 sleep(1) 149 end 150 end 151 152 -- Helper function to ask for an option from a list 153 function config.askOption(message, options) 154 expect(1, message, "string") 155 expect(2, options, "table") 156 while true do 157 term.clear() 158 term.setCursorPos(1, 1) 159 print(message) 160 for i, option in ipairs(options) do 161 print(i .. ") " .. option) 162 end 163 write("> ") 164 local input = read() 165 local num = tonumber(input) 166 if num and num >= 1 and num <= #options then 167 return options[num] 168 elseif input ~= "" then 169 -- Check if input matches option directly 170 for _, option in ipairs(options) do 171 if option:lower() == input:lower() then 172 return option 173 end 174 end 175 end 176 print("Please enter a valid option.") 177 sleep(1) 178 end 179 end 180 181 -- Helper function to ask for a URL 182 ---@param message string The message to display 183 ---@param default string|nil The default URL 184 ---@return string | nil The validated URL 185 function config.askURL(message, default) 186 expect(1, message, "string") 187 expect(2, default, "nil", "string") 188 while true do 189 local input = config.askInput(message, default) 190 if input == "" and default ~= nil then 191 input = default -- Ensure default is used if input is empty 192 end 193 194 if input and input ~= "" then 195 local ok, reason = http.checkURL(input) 196 if ok then 197 return input 198 else 199 print("Invalid URL: " .. (reason or "Unknown error")) 200 sleep(1) 201 end 202 else 203 return nil 204 end 205 end 206 end 207 208 -- Configure peripheral devices 209 function config.configPeripherals() 210 local peripherals = peripheral.getNames() 211 print("Available peripherals: " .. table.concat(peripherals, ", ")) 212 213 local carpet = config.askMonitor("Enter the carpet monitor name:") 214 local ring = config.askMonitor("Enter the ring monitor name:") 215 local redstone = config.askPeripheral("Enter the redstone input side:", nil) 216 217 local ivManagers = {} 218 local ivCount = config.askNumber("How many inventory managers?", 1) 219 for i = 1, ivCount do 220 ivManagers[i] = config.askPeripheral("Enter inventory manager " .. i .. " name:", "inventoryManager") 221 end 222 223 local ivmanBigger = config.askNumber("Base redstone signal strength:", 1) 224 local modem = config.askPeripheral("Enter modem name:", "modem") 225 226 return { 227 carpet = carpet, 228 ring = ring, 229 redstone = redstone, 230 ivmanagers = ivManagers, 231 ivmanBigger = ivmanBigger, 232 modem = modem, 233 } 234 end 235 236 -- Configure reward multipliers 237 function config.configRewards() 238 local numeric = config.askNumber("Reward multiplier for direct number bets:", 36) 239 local dozen = config.askNumber("Reward multiplier for dozen bets:", 3) 240 local binary = config.askNumber("Reward multiplier for binary bets:", 2) 241 local colour = config.askNumber("Reward multiplier for color bets:", 2) 242 243 return { 244 numeric = numeric, 245 dozen = dozen, 246 binary = binary, 247 colour = colour, 248 } 249 end 250 251 -- Configure debug options 252 function config.configDebug() 253 local debug = config.askYesNo("Enable debug mode?") 254 local LokiURL = nil 255 local TempoURL = nil 256 257 if debug then 258 LokiURL = config.askURL("Enter Loki URL:", "http://localhost:3100") 259 TempoURL = config.askURL("Enter Tempo URL:", "http://localhost:3100") 260 end 261 262 return { 263 loki = LokiURL, 264 tempo = TempoURL, 265 } 266 end 267 268 -- Function to configure the table 269 function config.configTable() 270 local toml = require("src.toml") 271 272 term.clear() 273 term.setCursorPos(1, 1) 274 print("ToasterGen Spin Configuration Utility") 275 print("====================================") 276 277 -- Configure rewards and peripherals 278 local rewards = config.configRewards() 279 local devices = config.configPeripherals() 280 local debug = config.configDebug() 281 282 -- Create the configuration 283 ---@type ClientConfig 284 local fullConfig = { 285 version = "0.1.0", 286 rewards = rewards, 287 devices = devices, 288 debug = debug, 289 } 290 291 -- Save the configuration 292 local file = fs.open("/config.toml", "w") 293 file.write(toml.encode(fullConfig)) 294 file.close() 295 296 print("Configuration saved successfully!") 297 print("Press any key to exit.") 298 os.pullEvent("key") 299 end 300 301 return config