BigBlow_

Untitled

Nov 8th, 2024
12
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.75 KB | None | 0 0
  1. local state, data, reactor, turbine, info_window, rules_window
  2.  
  3. local STATES = {
  4. READY = 1, -- Reactor is off and can be started with the lever
  5. RUNNING = 2, -- Reactor is running and all rules are met
  6. ESTOP = 3, -- Reactor is stopped due to rule(s) being violated
  7. UNKNOWN = 4, -- Reactor or turbine peripherals are missing
  8. }
  9.  
  10. ------------------------------------------------
  11.  
  12. local rules = {}
  13.  
  14. local function add_rule(name, fn)
  15. table.insert(rules, function()
  16. local ok, rule_met, value = pcall(fn)
  17. if ok then
  18. return rule_met, string.format("%s (%s)", name, value)
  19. else
  20. return false, name
  21. end
  22. end)
  23. end
  24.  
  25. add_rule("REACTOR TEMPERATURE <= 745K", function()
  26. local value = string.format("%3dK", math.ceil(data.reactor_temp))
  27. return data.reactor_temp <= 745, value
  28. end)
  29.  
  30. add_rule("REACTOR DAMAGE <= 10%", function()
  31. local value = string.format("%3d%%", math.ceil(data.reactor_damage * 100))
  32. return data.reactor_damage <= 0.10, value
  33. end)
  34.  
  35. add_rule("REACTOR COOLANT LEVEL >= 95%", function()
  36. local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
  37. return data.reactor_coolant >= 0.95, value
  38. end)
  39.  
  40. add_rule("REACTOR WASTE LEVEL <= 90%", function()
  41. local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100))
  42. return data.reactor_waste <= 0.90, value
  43. end)
  44.  
  45. add_rule("TURBINE ENERGY LEVEL <= 95%", function()
  46. local value = string.format("%3d%%", math.ceil(data.turbine_energy * 100))
  47. return data.turbine_energy <= 0.95, value
  48. end)
  49.  
  50. local function all_rules_met()
  51. for i, rule in ipairs(rules) do
  52. if not rule() then
  53. return false
  54. end
  55. end
  56. -- Allow manual emergency stop with SCRAM button
  57. return state ~= STATES.RUNNING or data.reactor_on
  58. end
  59.  
  60. ------------------------------------------------
  61.  
  62. local function update_data()
  63. data = {
  64. lever_on = redstone.getInput("top"),
  65.  
  66. reactor_on = reactor.getStatus(),
  67. reactor_burn_rate = reactor.getBurnRate(),
  68. reactor_max_burn_rate = reactor.getMaxBurnRate(),
  69. reactor_temp = reactor.getTemperature(),
  70. reactor_damage = reactor.getDamagePercent(),
  71. reactor_coolant = reactor.getCoolantFilledPercentage(),
  72. reactor_waste = reactor.getWasteFilledPercentage(),
  73.  
  74. turbine_energy = turbine.getEnergyFilledPercentage(),
  75. }
  76. end
  77.  
  78. ------------------------------------------------
  79.  
  80. local function colored(text, fg, bg)
  81. term.setTextColor(fg or colors.white)
  82. term.setBackgroundColor(bg or colors.black)
  83. term.write(text)
  84. end
  85.  
  86. local function make_section(name, x, y, w, h)
  87. for row = 1, h do
  88. term.setCursorPos(x, y + row - 1)
  89. local char = (row == 1 or row == h) and "\127" or " "
  90. colored("\127" .. string.rep(char, w - 2) .. "\127", colors.gray)
  91. end
  92.  
  93. term.setCursorPos(x + 2, y)
  94. colored(" " .. name .. " ")
  95.  
  96. return window.create(term.current(), x + 2, y + 2, w - 4, h - 4)
  97. end
  98.  
  99. local function update_info()
  100. local prev_term = term.redirect(info_window)
  101.  
  102. term.clear()
  103. term.setCursorPos(1, 1)
  104.  
  105. if state == STATES.UNKNOWN then
  106. colored("ERROR RETRIEVING DATA", colors.red)
  107. return
  108. end
  109.  
  110. colored("REACTOR: ")
  111. colored(data.reactor_on and "ON " or "OFF", data.reactor_on and colors.green or colors.red)
  112. colored(" LEVER: ")
  113. colored(data.lever_on and "ON " or "OFF", data.lever_on and colors.green or colors.red)
  114. colored(" R. LIMIT: ")
  115. colored(string.format("%4.1f", data.reactor_burn_rate), colors.blue)
  116. colored("/", colors.lightGray)
  117. colored(string.format("%4.1f", data.reactor_max_burn_rate), colors.blue)
  118.  
  119. term.setCursorPos(1, 3)
  120.  
  121. colored("STATUS: ")
  122. if state == STATES.READY then
  123. colored("READY, flip lever to start", colors.blue)
  124. elseif state == STATES.RUNNING then
  125. colored("RUNNING, flip lever to stop", colors.green)
  126. elseif state == STATES.ESTOP and not all_rules_met() then
  127. colored("EMERGENCY STOP, safety rules violated", colors.red)
  128. elseif state == STATES.ESTOP then
  129. colored("EMERGENCY STOP, toggle lever to reset", colors.red)
  130. end -- STATES.UNKNOWN cases handled above
  131.  
  132. term.redirect(prev_term)
  133. end
  134.  
  135. local estop_reasons = {}
  136.  
  137. local function update_rules()
  138. local prev_term = term.redirect(rules_window)
  139.  
  140. term.clear()
  141.  
  142. if state ~= STATES.ESTOP then
  143. estop_reasons = {}
  144. end
  145.  
  146. for i, rule in ipairs(rules) do
  147. local ok, text = rule()
  148. term.setCursorPos(1, i)
  149. if ok and not estop_reasons[i] then
  150. colored("[ OK ] ", colors.green)
  151. colored(text, colors.lightGray)
  152. else
  153. colored("[ FAIL ] ", colors.red)
  154. colored(text, colors.red)
  155. estop_reasons[i] = true
  156. end
  157. end
  158.  
  159. term.redirect(prev_term)
  160. end
  161.  
  162. ------------------------------------------------
  163.  
  164. local function main_loop()
  165. -- Search for peripherals again if one or both are missing
  166. if not state or state == STATES.UNKNOWN then
  167. reactor = peripheral.find("fissionReactorLogicAdapter")
  168. turbine = peripheral.find("turbineValve")
  169. end
  170.  
  171. if not pcall(update_data) then
  172. -- Error getting data (either reactor or turbine is nil?)
  173. data = {}
  174. state = STATES.UNKNOWN
  175. elseif data.reactor_on == nil then
  176. -- Reactor is not connected
  177. state = STATES.UNKNOWN
  178. elseif data.turbine_energy == nil then
  179. -- Turbine is not connected
  180. state = STATES.UNKNOWN
  181. elseif not state then
  182. -- Program just started, get current state from lever
  183. state = data.lever_on and STATES.RUNNING or STATES.READY
  184. elseif state == STATES.READY and data.lever_on then
  185. -- READY -> RUNNING
  186. state = STATES.RUNNING
  187. -- Activate reactor
  188. pcall(reactor.activate)
  189. data.reactor_on = true
  190. elseif state == STATES.RUNNING and not data.lever_on then
  191. -- RUNNING -> READY
  192. state = STATES.READY
  193. elseif state == STATES.ESTOP and not data.lever_on then
  194. -- ESTOP -> READY
  195. state = STATES.READY
  196. elseif state == STATES.UNKNOWN then
  197. -- UNKNOWN -> ESTOP
  198. state = data.lever_on and STATES.ESTOP or STATES.READY
  199. estop_reasons = {}
  200. end
  201.  
  202. -- Always enter ESTOP if safety rules are not met
  203. if state ~= STATES.UNKNOWN and not all_rules_met() then
  204. state = STATES.ESTOP
  205. end
  206.  
  207. -- SCRAM reactor if not running
  208. if state ~= STATES.RUNNING and reactor then
  209. pcall(reactor.scram)
  210. end
  211.  
  212. -- Update info and rules windows
  213. pcall(update_info)
  214. pcall(update_rules)
  215.  
  216. sleep() -- Other calls should already yield, this is just in case
  217. return main_loop()
  218. end
  219.  
  220. term.setPaletteColor(colors.black, 0x000000)
  221. term.setPaletteColor(colors.gray, 0x343434)
  222. term.setPaletteColor(colors.lightGray, 0xababab)
  223. term.setPaletteColor(colors.red, 0xdb2d20)
  224. term.setPaletteColor(colors.green, 0x01a252)
  225. term.setPaletteColor(colors.blue, 0x01a0e4)
  226.  
  227. term.clear()
  228. local width = term.getSize()
  229. info_window = make_section("INFORMATION", 2, 2, width - 2, 7)
  230. rules_window = make_section("SAFETY RULES", 2, 10, width - 2, 9)
  231.  
  232. parallel.waitForAny(main_loop, function()
  233. os.pullEventRaw("terminate")
  234. end)
  235.  
  236. os.reboot()
Add Comment
Please, Sign In to add comment