Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22e47f40d8 |
@@ -1,314 +0,0 @@
|
|||||||
sleep(0)
|
|
||||||
local state, data, reactor, turbine, info_window, rules_window
|
|
||||||
|
|
||||||
local STATES = {
|
|
||||||
READY = 1, -- Reactor is off and can be started with the lever
|
|
||||||
RUNNING = 2, -- Reactor is running and all rules are met
|
|
||||||
ESTOP = 3, -- Reactor is stopped due to rule(s) being violated
|
|
||||||
UNKNOWN = 4, -- Reactor or turbine peripherals are missing
|
|
||||||
}
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local rules = {}
|
|
||||||
|
|
||||||
local function add_rule(name, fn)
|
|
||||||
table.insert(rules, function()
|
|
||||||
local ok, rule_met, value = pcall(fn)
|
|
||||||
if ok then
|
|
||||||
return rule_met, string.format("%s (%s)", name, value)
|
|
||||||
else
|
|
||||||
return false, name
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
add_rule("REACTOR TEMPERATURE <= 1200K", function()
|
|
||||||
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
|
||||||
return data.reactor_temp <= 1200, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR DAMAGE <= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
|
||||||
return data.reactor_damage <= 10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR COOLANT LEVEL >= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
|
||||||
return data.reactor_coolant >= 0.10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
|
||||||
return data.reactor_fuel >= 0.05, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR WASTE LEVEL <= 90%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100))
|
|
||||||
return data.reactor_waste <= 0.90, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 1 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
|
||||||
return data.turbine1_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 2 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine2_energy * 100))
|
|
||||||
return data.turbine2_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 3 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine3_energy * 100))
|
|
||||||
return data.turbine3_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 4 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine4_energy * 100))
|
|
||||||
return data.turbine4_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 5 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine5_energy * 100))
|
|
||||||
return data.turbine5_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 6 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine6_energy * 100))
|
|
||||||
return data.turbine6_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function all_rules_met()
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if not rule() then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Allow manual emergency stop with SCRAM button
|
|
||||||
return state ~= STATES.RUNNING or data.reactor_on
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function update_data()
|
|
||||||
data = {
|
|
||||||
lever_on = redstone.getInput("top"),
|
|
||||||
|
|
||||||
reactor_on = reactor.getStatus(),
|
|
||||||
reactor_burn_rate = reactor.getBurnRate(),
|
|
||||||
reactor_max_burn_rate = reactor.getMaxBurnRate(),
|
|
||||||
reactor_temp = reactor.getTemperature(),
|
|
||||||
reactor_damage = reactor.getDamagePercent(),
|
|
||||||
reactor_coolant = reactor.getCoolantFilledPercentage(),
|
|
||||||
reactor_waste = reactor.getWasteFilledPercentage(),
|
|
||||||
reactor_fuel = reactor.getFuelFilledPercentage(),
|
|
||||||
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
|
||||||
turbine2_energy = turbine2.getEnergyFilledPercentage(),
|
|
||||||
turbine3_energy = turbine2.getEnergyFilledPercentage(),
|
|
||||||
turbine4_energy = turbine2.getEnergyFilledPercentage(),
|
|
||||||
turbine5_energy = turbine2.getEnergyFilledPercentage(),
|
|
||||||
turbine6_energy = turbine2.getEnergyFilledPercentage(),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function colored(text, fg, bg)
|
|
||||||
term.setTextColor(fg or colors.white)
|
|
||||||
term.setBackgroundColor(bg or colors.black)
|
|
||||||
term.write(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_section(name, x, y, w, h)
|
|
||||||
for row = 1, h do
|
|
||||||
term.setCursorPos(x, y + row - 1)
|
|
||||||
local char = (row == 1 or row == h) and "\127" or " "
|
|
||||||
colored("\127" .. string.rep(char, w - 2) .. "\127", colors.gray)
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setCursorPos(x + 2, y)
|
|
||||||
colored(" " .. name .. " ")
|
|
||||||
|
|
||||||
return window.create(term.current(), x + 2, y + 2, w - 4, h - 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update_info()
|
|
||||||
local prev_term = term.redirect(info_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
if state == STATES.UNKNOWN then
|
|
||||||
colored("ERROR RETRIEVING DATA", colors.red)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
colored("REACTOR: ")
|
|
||||||
colored(data.reactor_on and "ON " or "OFF", data.reactor_on and colors.green or colors.red)
|
|
||||||
colored(" LEVER: ")
|
|
||||||
colored(data.lever_on and "ON " or "OFF", data.lever_on and colors.green or colors.red)
|
|
||||||
colored(" R. LIMIT: ")
|
|
||||||
colored(string.format("%4.2f", data.reactor_burn_rate), colors.blue)
|
|
||||||
colored("/", colors.lightGray)
|
|
||||||
colored(string.format("%4.1f", data.reactor_max_burn_rate), colors.blue)
|
|
||||||
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
|
|
||||||
colored("STATUS: ")
|
|
||||||
if state == STATES.READY then
|
|
||||||
colored("READY, flip lever to start", colors.blue)
|
|
||||||
elseif state == STATES.RUNNING then
|
|
||||||
colored("RUNNING, flip lever to stop", colors.green)
|
|
||||||
elseif state == STATES.ESTOP and not all_rules_met() then
|
|
||||||
colored("EMERGENCY STOP, safety rules violated", colors.red)
|
|
||||||
elseif state == STATES.ESTOP then
|
|
||||||
colored("EMERGENCY STOP, toggle lever to reset", colors.red)
|
|
||||||
end -- STATES.UNKNOWN cases handled above
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
local estop_reasons = {}
|
|
||||||
|
|
||||||
local function update_rules()
|
|
||||||
local prev_term = term.redirect(rules_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
|
|
||||||
if state ~= STATES.ESTOP then
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
local ok, text = rule()
|
|
||||||
term.setCursorPos(1, i)
|
|
||||||
if ok and not estop_reasons[i] then
|
|
||||||
colored("[ OK ] ", colors.green)
|
|
||||||
colored(text, colors.lightGray)
|
|
||||||
else
|
|
||||||
colored("[ FAIL ] ", colors.red)
|
|
||||||
colored(text, colors.red)
|
|
||||||
estop_reasons[i] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function main_loop()
|
|
||||||
-- Search for peripherals again if one or both are missing
|
|
||||||
if not state or state == STATES.UNKNOWN then
|
|
||||||
reactor = peripheral.wrap("fissionReactorLogicAdapter_2")
|
|
||||||
turbine1 = peripheral.wrap("turbineValve_1")
|
|
||||||
turbine2 = peripheral.wrap("turbineValve_2")
|
|
||||||
turbine3 = peripheral.wrap("turbineValve_3")
|
|
||||||
turbine4 = peripheral.wrap("turbineValve_4")
|
|
||||||
turbine5 = peripheral.wrap("turbineValve_5")
|
|
||||||
turbine6 = peripheral.wrap("turbineValve_6")
|
|
||||||
|
|
||||||
end
|
|
||||||
if not pcall(update_data) then
|
|
||||||
-- Error getting data (either reactor or turbine is nil?)
|
|
||||||
data = {}
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.reactor_on == nil then
|
|
||||||
-- Reactor is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine1_energy == nil then
|
|
||||||
-- Turbine 1 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine2_energy == nil then
|
|
||||||
-- Turbine 2 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine3_energy == nil then
|
|
||||||
-- Turbine 3 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine4_energy == nil then
|
|
||||||
-- Turbine 4 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine5_energy == nil then
|
|
||||||
-- Turbine 5 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine6_energy == nil then
|
|
||||||
-- Turbine 6 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif not state then
|
|
||||||
-- Program just started, get current state from lever
|
|
||||||
state = data.lever_on and STATES.RUNNING or STATES.READY
|
|
||||||
elseif state == STATES.READY and data.lever_on then
|
|
||||||
-- READY -> RUNNING
|
|
||||||
state = STATES.RUNNING
|
|
||||||
-- Activate reactor
|
|
||||||
pcall(reactor.activate)
|
|
||||||
data.reactor_on = true
|
|
||||||
elseif state == STATES.RUNNING and not data.lever_on then
|
|
||||||
-- RUNNING -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.ESTOP and not data.lever_on then
|
|
||||||
-- ESTOP -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.UNKNOWN then
|
|
||||||
-- UNKNOWN -> ESTOP
|
|
||||||
state = data.lever_on and STATES.ESTOP or STATES.READY
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Always enter ESTOP if safety rules are not met
|
|
||||||
if state ~= STATES.UNKNOWN and not all_rules_met() then
|
|
||||||
state = STATES.ESTOP
|
|
||||||
end
|
|
||||||
|
|
||||||
-- SCRAM reactor if not running
|
|
||||||
if state ~= STATES.RUNNING and reactor then
|
|
||||||
pcall(reactor.scram)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update info and rules windows
|
|
||||||
pcall(update_info)
|
|
||||||
pcall(update_rules)
|
|
||||||
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.turbine2_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.turbine3_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.turbine4_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.turbine5_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.turbine6_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
sleep() -- Other calls should already yield, this is just in case
|
|
||||||
return main_loop()
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setPaletteColor(colors.black, 0x000000)
|
|
||||||
term.setPaletteColor(colors.gray, 0x343434)
|
|
||||||
term.setPaletteColor(colors.lightGray, 0xababab)
|
|
||||||
term.setPaletteColor(colors.red, 0xff0000)
|
|
||||||
term.setPaletteColor(colors.green, 0x00ff00)
|
|
||||||
term.setPaletteColor(colors.blue, 0x0000ff)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
local width = term.getSize()
|
|
||||||
info_window = make_section("INFORMATION", 2, 2, width - 2, 7)
|
|
||||||
rules_window = make_section("SAFETY RULES", 2, 10, width - 2, 24)
|
|
||||||
|
|
||||||
parallel.waitForAny(main_loop, function()
|
|
||||||
os.pullEventRaw("terminate")
|
|
||||||
end)
|
|
||||||
|
|
||||||
--os.reboot()
|
|
||||||
@@ -1,258 +0,0 @@
|
|||||||
sleep(0)
|
|
||||||
local state, data, reactor, turbine, info_window, rules_window
|
|
||||||
|
|
||||||
local STATES = {
|
|
||||||
READY = 1, -- Reactor is off and can be started with the lever
|
|
||||||
RUNNING = 2, -- Reactor is running and all rules are met
|
|
||||||
ESTOP = 3, -- Reactor is stopped due to rule(s) being violated
|
|
||||||
UNKNOWN = 4, -- Reactor or turbine peripherals are missing
|
|
||||||
}
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local rules = {}
|
|
||||||
|
|
||||||
local function add_rule(name, fn)
|
|
||||||
table.insert(rules, function()
|
|
||||||
local ok, rule_met, value = pcall(fn)
|
|
||||||
if ok then
|
|
||||||
return rule_met, string.format("%s (%s)", name, value)
|
|
||||||
else
|
|
||||||
return false, name
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
add_rule("REACTOR TEMPERATURE <= 1200K", function()
|
|
||||||
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
|
||||||
return data.reactor_temp <= 1200, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR DAMAGE <= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
|
||||||
return data.reactor_damage <= 10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR COOLANT LEVEL >= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
|
||||||
return data.reactor_coolant >= 0.10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
|
||||||
return data.reactor_fuel >= 0.05, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR WASTE LEVEL <= 90%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100))
|
|
||||||
return data.reactor_waste <= 0.90, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 1 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
|
||||||
return data.turbine1_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 2 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine2_energy * 100))
|
|
||||||
return data.turbine2_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function all_rules_met()
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if not rule() then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Allow manual emergency stop with SCRAM button
|
|
||||||
return state ~= STATES.RUNNING or data.reactor_on
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function update_data()
|
|
||||||
data = {
|
|
||||||
lever_on = redstone.getInput("top"),
|
|
||||||
|
|
||||||
reactor_on = reactor.getStatus(),
|
|
||||||
reactor_burn_rate = reactor.getBurnRate(),
|
|
||||||
reactor_max_burn_rate = reactor.getMaxBurnRate(),
|
|
||||||
reactor_temp = reactor.getTemperature(),
|
|
||||||
reactor_damage = reactor.getDamagePercent(),
|
|
||||||
reactor_coolant = reactor.getCoolantFilledPercentage(),
|
|
||||||
reactor_waste = reactor.getWasteFilledPercentage(),
|
|
||||||
reactor_fuel = reactor.getFuelFilledPercentage(),
|
|
||||||
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
|
||||||
turbine2_energy = turbine2.getEnergyFilledPercentage(),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function colored(text, fg, bg)
|
|
||||||
term.setTextColor(fg or colors.white)
|
|
||||||
term.setBackgroundColor(bg or colors.black)
|
|
||||||
term.write(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_section(name, x, y, w, h)
|
|
||||||
for row = 1, h do
|
|
||||||
term.setCursorPos(x, y + row - 1)
|
|
||||||
local char = (row == 1 or row == h) and "\127" or " "
|
|
||||||
colored("\127" .. string.rep(char, w - 2) .. "\127", colors.gray)
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setCursorPos(x + 2, y)
|
|
||||||
colored(" " .. name .. " ")
|
|
||||||
|
|
||||||
return window.create(term.current(), x + 2, y + 2, w - 4, h - 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update_info()
|
|
||||||
local prev_term = term.redirect(info_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
if state == STATES.UNKNOWN then
|
|
||||||
colored("ERROR RETRIEVING DATA", colors.red)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
colored("REACTOR: ")
|
|
||||||
colored(data.reactor_on and "ON " or "OFF", data.reactor_on and colors.green or colors.red)
|
|
||||||
colored(" LEVER: ")
|
|
||||||
colored(data.lever_on and "ON " or "OFF", data.lever_on and colors.green or colors.red)
|
|
||||||
colored(" R. LIMIT: ")
|
|
||||||
colored(string.format("%4.2f", data.reactor_burn_rate), colors.blue)
|
|
||||||
colored("/", colors.lightGray)
|
|
||||||
colored(string.format("%4.1f", data.reactor_max_burn_rate), colors.blue)
|
|
||||||
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
|
|
||||||
colored("STATUS: ")
|
|
||||||
if state == STATES.READY then
|
|
||||||
colored("READY, flip lever to start", colors.blue)
|
|
||||||
elseif state == STATES.RUNNING then
|
|
||||||
colored("RUNNING, flip lever to stop", colors.green)
|
|
||||||
elseif state == STATES.ESTOP and not all_rules_met() then
|
|
||||||
colored("EMERGENCY STOP, safety rules violated", colors.red)
|
|
||||||
elseif state == STATES.ESTOP then
|
|
||||||
colored("EMERGENCY STOP, toggle lever to reset", colors.red)
|
|
||||||
end -- STATES.UNKNOWN cases handled above
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
local estop_reasons = {}
|
|
||||||
|
|
||||||
local function update_rules()
|
|
||||||
local prev_term = term.redirect(rules_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
|
|
||||||
if state ~= STATES.ESTOP then
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
local ok, text = rule()
|
|
||||||
term.setCursorPos(1, i)
|
|
||||||
if ok and not estop_reasons[i] then
|
|
||||||
colored("[ OK ] ", colors.green)
|
|
||||||
colored(text, colors.lightGray)
|
|
||||||
else
|
|
||||||
colored("[ FAIL ] ", colors.red)
|
|
||||||
colored(text, colors.red)
|
|
||||||
estop_reasons[i] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function main_loop()
|
|
||||||
-- Search for peripherals again if one or both are missing
|
|
||||||
if not state or state == STATES.UNKNOWN then
|
|
||||||
reactor = peripheral.wrap("fissionReactorLogicAdapter_2")
|
|
||||||
turbine1 = peripheral.wrap("turbineValve_1")
|
|
||||||
turbine2 = peripheral.wrap("turbineValve_2")
|
|
||||||
end
|
|
||||||
if not pcall(update_data) then
|
|
||||||
-- Error getting data (either reactor or turbine is nil?)
|
|
||||||
data = {}
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.reactor_on == nil then
|
|
||||||
-- Reactor is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine1_energy == nil then
|
|
||||||
-- Turbine 1 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine2_energy == nil then
|
|
||||||
-- Turbine 2 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif not state then
|
|
||||||
-- Program just started, get current state from lever
|
|
||||||
state = data.lever_on and STATES.RUNNING or STATES.READY
|
|
||||||
elseif state == STATES.READY and data.lever_on then
|
|
||||||
-- READY -> RUNNING
|
|
||||||
state = STATES.RUNNING
|
|
||||||
-- Activate reactor
|
|
||||||
pcall(reactor.activate)
|
|
||||||
data.reactor_on = true
|
|
||||||
elseif state == STATES.RUNNING and not data.lever_on then
|
|
||||||
-- RUNNING -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.ESTOP and not data.lever_on then
|
|
||||||
-- ESTOP -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.UNKNOWN then
|
|
||||||
-- UNKNOWN -> ESTOP
|
|
||||||
state = data.lever_on and STATES.ESTOP or STATES.READY
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Always enter ESTOP if safety rules are not met
|
|
||||||
if state ~= STATES.UNKNOWN and not all_rules_met() then
|
|
||||||
state = STATES.ESTOP
|
|
||||||
end
|
|
||||||
|
|
||||||
-- SCRAM reactor if not running
|
|
||||||
if state ~= STATES.RUNNING and reactor then
|
|
||||||
pcall(reactor.scram)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update info and rules windows
|
|
||||||
pcall(update_info)
|
|
||||||
pcall(update_rules)
|
|
||||||
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.turbine2_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
sleep() -- Other calls should already yield, this is just in case
|
|
||||||
return main_loop()
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setPaletteColor(colors.black, 0x000000)
|
|
||||||
term.setPaletteColor(colors.gray, 0x343434)
|
|
||||||
term.setPaletteColor(colors.lightGray, 0xababab)
|
|
||||||
term.setPaletteColor(colors.red, 0xff0000)
|
|
||||||
term.setPaletteColor(colors.green, 0x00ff00)
|
|
||||||
term.setPaletteColor(colors.blue, 0x0000ff)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
local width = term.getSize()
|
|
||||||
info_window = make_section("INFORMATION", 2, 2, width - 2, 7)
|
|
||||||
rules_window = make_section("SAFETY RULES", 2, 10, width - 2, 16)
|
|
||||||
|
|
||||||
parallel.waitForAny(main_loop, function()
|
|
||||||
os.pullEventRaw("terminate")
|
|
||||||
end)
|
|
||||||
|
|
||||||
--os.reboot()
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
sleep(0)
|
|
||||||
local state, data, reactor, turbine, info_window, rules_window
|
|
||||||
|
|
||||||
local STATES = {
|
|
||||||
READY = 1, -- Reactor is off and can be started with the lever
|
|
||||||
RUNNING = 2, -- Reactor is running and all rules are met
|
|
||||||
ESTOP = 3, -- Reactor is stopped due to rule(s) being violated
|
|
||||||
UNKNOWN = 4, -- Reactor or turbine peripherals are missing
|
|
||||||
}
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local rules = {}
|
|
||||||
|
|
||||||
local function add_rule(name, fn)
|
|
||||||
table.insert(rules, function()
|
|
||||||
local ok, rule_met, value = pcall(fn)
|
|
||||||
if ok then
|
|
||||||
return rule_met, string.format("%s (%s)", name, value)
|
|
||||||
else
|
|
||||||
return false, name
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
add_rule("REACTOR TEMPERATURE <= 1200K", function()
|
|
||||||
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
|
||||||
return data.reactor_temp <= 1200, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR DAMAGE <= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
|
||||||
return data.reactor_damage <= 10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR COOLANT LEVEL >= 30%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
|
||||||
return data.reactor_coolant >= 0.30, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
|
||||||
return data.reactor_fuel >= 0.05, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR WASTE LEVEL <= 90%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100))
|
|
||||||
return data.reactor_waste <= 0.90, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 1 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
|
||||||
return data.turbine1_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function all_rules_met()
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if not rule() then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Allow manual emergency stop with SCRAM button
|
|
||||||
return state ~= STATES.RUNNING or data.reactor_on
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function update_data()
|
|
||||||
data = {
|
|
||||||
lever_on = redstone.getInput("top"),
|
|
||||||
|
|
||||||
reactor_on = reactor.getStatus(),
|
|
||||||
reactor_burn_rate = reactor.getBurnRate(),
|
|
||||||
reactor_max_burn_rate = reactor.getMaxBurnRate(),
|
|
||||||
reactor_temp = reactor.getTemperature(),
|
|
||||||
reactor_damage = reactor.getDamagePercent(),
|
|
||||||
reactor_coolant = reactor.getCoolantFilledPercentage(),
|
|
||||||
reactor_waste = reactor.getWasteFilledPercentage(),
|
|
||||||
reactor_fuel = reactor.getFuelFilledPercentage(),
|
|
||||||
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function colored(text, fg, bg)
|
|
||||||
term.setTextColor(fg or colors.white)
|
|
||||||
term.setBackgroundColor(bg or colors.black)
|
|
||||||
term.write(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_section(name, x, y, w, h)
|
|
||||||
for row = 1, h do
|
|
||||||
term.setCursorPos(x, y + row - 1)
|
|
||||||
local char = (row == 1 or row == h) and "\127" or " "
|
|
||||||
colored("\127" .. string.rep(char, w - 2) .. "\127", colors.gray)
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setCursorPos(x + 2, y)
|
|
||||||
colored(" " .. name .. " ")
|
|
||||||
|
|
||||||
return window.create(term.current(), x + 2, y + 2, w - 4, h - 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update_info()
|
|
||||||
local prev_term = term.redirect(info_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
if state == STATES.UNKNOWN then
|
|
||||||
colored("ERROR RETRIEVING DATA", colors.red)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
colored("REACTOR: ")
|
|
||||||
colored(data.reactor_on and "ON " or "OFF", data.reactor_on and colors.green or colors.red)
|
|
||||||
colored(" LEVER: ")
|
|
||||||
colored(data.lever_on and "ON " or "OFF", data.lever_on and colors.green or colors.red)
|
|
||||||
colored(" R. LIMIT: ")
|
|
||||||
colored(string.format("%4.2f", data.reactor_burn_rate), colors.blue)
|
|
||||||
colored("/", colors.lightGray)
|
|
||||||
colored(string.format("%4.1f", data.reactor_max_burn_rate), colors.blue)
|
|
||||||
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
|
|
||||||
colored("STATUS: ")
|
|
||||||
if state == STATES.READY then
|
|
||||||
colored("READY, flip lever to start", colors.blue)
|
|
||||||
elseif state == STATES.RUNNING then
|
|
||||||
colored("RUNNING, flip lever to stop", colors.green)
|
|
||||||
elseif state == STATES.ESTOP and not all_rules_met() then
|
|
||||||
colored("EMERGENCY STOP, safety rules violated", colors.red)
|
|
||||||
elseif state == STATES.ESTOP then
|
|
||||||
colored("EMERGENCY STOP, toggle lever to reset", colors.red)
|
|
||||||
end -- STATES.UNKNOWN cases handled above
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
local estop_reasons = {}
|
|
||||||
|
|
||||||
local function update_rules()
|
|
||||||
local prev_term = term.redirect(rules_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
|
|
||||||
if state ~= STATES.ESTOP then
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
local ok, text = rule()
|
|
||||||
term.setCursorPos(1, i)
|
|
||||||
if ok and not estop_reasons[i] then
|
|
||||||
colored("[ OK ] ", colors.green)
|
|
||||||
colored(text, colors.lightGray)
|
|
||||||
else
|
|
||||||
colored("[ FAIL ] ", colors.red)
|
|
||||||
colored(text, colors.red)
|
|
||||||
estop_reasons[i] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function main_loop()
|
|
||||||
-- Search for peripherals again if one or both are missing
|
|
||||||
if not state or state == STATES.UNKNOWN then
|
|
||||||
reactor = peripheral.wrap("fissionReactorLogicAdapter_2")
|
|
||||||
turbine1 = peripheral.wrap("turbineValve_1")
|
|
||||||
end
|
|
||||||
if not pcall(update_data) then
|
|
||||||
-- Error getting data (either reactor or turbine is nil?)
|
|
||||||
data = {}
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.reactor_on == nil then
|
|
||||||
-- Reactor is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine1_energy == nil then
|
|
||||||
-- Turbine 1 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif not state then
|
|
||||||
-- Program just started, get current state from lever
|
|
||||||
state = data.lever_on and STATES.RUNNING or STATES.READY
|
|
||||||
elseif state == STATES.READY and data.lever_on then
|
|
||||||
-- READY -> RUNNING
|
|
||||||
state = STATES.RUNNING
|
|
||||||
-- Activate reactor
|
|
||||||
pcall(reactor.activate)
|
|
||||||
data.reactor_on = true
|
|
||||||
elseif state == STATES.RUNNING and not data.lever_on then
|
|
||||||
-- RUNNING -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.ESTOP and not data.lever_on then
|
|
||||||
-- ESTOP -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.UNKNOWN then
|
|
||||||
-- UNKNOWN -> ESTOP
|
|
||||||
state = data.lever_on and STATES.ESTOP or STATES.READY
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Always enter ESTOP if safety rules are not met
|
|
||||||
if state ~= STATES.UNKNOWN and not all_rules_met() then
|
|
||||||
state = STATES.ESTOP
|
|
||||||
end
|
|
||||||
|
|
||||||
-- SCRAM reactor if not running
|
|
||||||
if state ~= STATES.RUNNING and reactor then
|
|
||||||
pcall(reactor.scram)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update info and rules windows
|
|
||||||
pcall(update_info)
|
|
||||||
pcall(update_rules)
|
|
||||||
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
sleep() -- Other calls should already yield, this is just in case
|
|
||||||
return main_loop()
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setPaletteColor(colors.black, 0x000000)
|
|
||||||
term.setPaletteColor(colors.gray, 0x343434)
|
|
||||||
term.setPaletteColor(colors.lightGray, 0xababab)
|
|
||||||
term.setPaletteColor(colors.red, 0xff0000)
|
|
||||||
term.setPaletteColor(colors.green, 0x00ff00)
|
|
||||||
term.setPaletteColor(colors.blue, 0x0000ff)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
local width = term.getSize()
|
|
||||||
info_window = make_section("INFORMATION", 2, 2, width - 2, 7)
|
|
||||||
rules_window = make_section("SAFETY RULES", 2, 10, width - 2, 10)
|
|
||||||
|
|
||||||
parallel.waitForAny(main_loop, function()
|
|
||||||
os.pullEventRaw("terminate")
|
|
||||||
end)
|
|
||||||
|
|
||||||
--os.reboot()
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
sleep(0)
|
|
||||||
local state, data, reactor, turbine, info_window, rules_window
|
|
||||||
|
|
||||||
local STATES = {
|
|
||||||
READY = 1, -- Reactor is off and can be started with the lever
|
|
||||||
RUNNING = 2, -- Reactor is running and all rules are met
|
|
||||||
ESTOP = 3, -- Reactor is stopped due to rule(s) being violated
|
|
||||||
UNKNOWN = 4, -- Reactor or turbine peripherals are missing
|
|
||||||
}
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local rules = {}
|
|
||||||
|
|
||||||
local function add_rule(name, fn)
|
|
||||||
table.insert(rules, function()
|
|
||||||
local ok, rule_met, value = pcall(fn)
|
|
||||||
if ok then
|
|
||||||
return rule_met, string.format("%s (%s)", name, value)
|
|
||||||
else
|
|
||||||
return false, name
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
add_rule("REACTOR TEMPERATURE <= 1200K", function()
|
|
||||||
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
|
||||||
return data.reactor_temp <= 1200, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR DAMAGE <= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
|
||||||
return data.reactor_damage <= 10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR COOLANT LEVEL >= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
|
||||||
return data.reactor_coolant >= 0.10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
|
||||||
return data.reactor_fuel >= 0.05, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR WASTE LEVEL <= 90%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100))
|
|
||||||
return data.reactor_waste <= 0.90, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 1 ENERGY LEVEL <= 95%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
|
||||||
return data.turbine1_energy <= 0.95, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function all_rules_met()
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if not rule() then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Allow manual emergency stop with SCRAM button
|
|
||||||
return state ~= STATES.RUNNING or data.reactor_on
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function update_data()
|
|
||||||
data = {
|
|
||||||
lever_on = redstone.getInput("top"),
|
|
||||||
|
|
||||||
reactor_on = reactor.getStatus(),
|
|
||||||
reactor_burn_rate = reactor.getBurnRate(),
|
|
||||||
reactor_max_burn_rate = reactor.getMaxBurnRate(),
|
|
||||||
reactor_temp = reactor.getTemperature(),
|
|
||||||
reactor_damage = reactor.getDamagePercent(),
|
|
||||||
reactor_coolant = reactor.getCoolantFilledPercentage(),
|
|
||||||
reactor_waste = reactor.getWasteFilledPercentage(),
|
|
||||||
reactor_fuel = reactor.getFuelFilledPercentage(),
|
|
||||||
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function colored(text, fg, bg)
|
|
||||||
term.setTextColor(fg or colors.white)
|
|
||||||
term.setBackgroundColor(bg or colors.black)
|
|
||||||
term.write(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_section(name, x, y, w, h)
|
|
||||||
for row = 1, h do
|
|
||||||
term.setCursorPos(x, y + row - 1)
|
|
||||||
local char = (row == 1 or row == h) and "\127" or " "
|
|
||||||
colored("\127" .. string.rep(char, w - 2) .. "\127", colors.gray)
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setCursorPos(x + 2, y)
|
|
||||||
colored(" " .. name .. " ")
|
|
||||||
|
|
||||||
return window.create(term.current(), x + 2, y + 2, w - 4, h - 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update_info()
|
|
||||||
local prev_term = term.redirect(info_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
if state == STATES.UNKNOWN then
|
|
||||||
colored("ERROR RETRIEVING DATA", colors.red)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
colored("REACTOR: ")
|
|
||||||
colored(data.reactor_on and "ON " or "OFF", data.reactor_on and colors.green or colors.red)
|
|
||||||
colored(" LEVER: ")
|
|
||||||
colored(data.lever_on and "ON " or "OFF", data.lever_on and colors.green or colors.red)
|
|
||||||
colored(" R. LIMIT: ")
|
|
||||||
colored(string.format("%4.2f", data.reactor_burn_rate), colors.blue)
|
|
||||||
colored("/", colors.lightGray)
|
|
||||||
colored(string.format("%4.1f", data.reactor_max_burn_rate), colors.blue)
|
|
||||||
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
|
|
||||||
colored("STATUS: ")
|
|
||||||
if state == STATES.READY then
|
|
||||||
colored("READY, flip lever to start", colors.blue)
|
|
||||||
elseif state == STATES.RUNNING then
|
|
||||||
colored("RUNNING, flip lever to stop", colors.green)
|
|
||||||
elseif state == STATES.ESTOP and not all_rules_met() then
|
|
||||||
colored("EMERGENCY STOP, safety rules violated", colors.red)
|
|
||||||
elseif state == STATES.ESTOP then
|
|
||||||
colored("EMERGENCY STOP, toggle lever to reset", colors.red)
|
|
||||||
end -- STATES.UNKNOWN cases handled above
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
local estop_reasons = {}
|
|
||||||
|
|
||||||
local function update_rules()
|
|
||||||
local prev_term = term.redirect(rules_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
|
|
||||||
if state ~= STATES.ESTOP then
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
local ok, text = rule()
|
|
||||||
term.setCursorPos(1, i)
|
|
||||||
if ok and not estop_reasons[i] then
|
|
||||||
colored("[ OK ] ", colors.green)
|
|
||||||
colored(text, colors.lightGray)
|
|
||||||
else
|
|
||||||
colored("[ FAIL ] ", colors.red)
|
|
||||||
colored(text, colors.red)
|
|
||||||
estop_reasons[i] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function main_loop()
|
|
||||||
-- Search for peripherals again if one or both are missing
|
|
||||||
if not state or state == STATES.UNKNOWN then
|
|
||||||
reactor = peripheral.wrap("fissionReactorLogicAdapter_0")
|
|
||||||
turbine1 = peripheral.wrap("turbineValve_0")
|
|
||||||
end
|
|
||||||
if not pcall(update_data) then
|
|
||||||
-- Error getting data (either reactor or turbine is nil?)
|
|
||||||
data = {}
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.reactor_on == nil then
|
|
||||||
-- Reactor is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine1_energy == nil then
|
|
||||||
-- Turbine 1 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif not state then
|
|
||||||
-- Program just started, get current state from lever
|
|
||||||
state = data.lever_on and STATES.RUNNING or STATES.READY
|
|
||||||
elseif state == STATES.READY and data.lever_on then
|
|
||||||
-- READY -> RUNNING
|
|
||||||
state = STATES.RUNNING
|
|
||||||
-- Activate reactor
|
|
||||||
pcall(reactor.activate)
|
|
||||||
data.reactor_on = true
|
|
||||||
elseif state == STATES.RUNNING and not data.lever_on then
|
|
||||||
-- RUNNING -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.ESTOP and not data.lever_on then
|
|
||||||
-- ESTOP -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.UNKNOWN then
|
|
||||||
-- UNKNOWN -> ESTOP
|
|
||||||
state = data.lever_on and STATES.ESTOP or STATES.READY
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Always enter ESTOP if safety rules are not met
|
|
||||||
if state ~= STATES.UNKNOWN and not all_rules_met() then
|
|
||||||
state = STATES.ESTOP
|
|
||||||
end
|
|
||||||
|
|
||||||
-- SCRAM reactor if not running
|
|
||||||
if state ~= STATES.RUNNING and reactor then
|
|
||||||
pcall(reactor.scram)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update info and rules windows
|
|
||||||
pcall(update_info)
|
|
||||||
pcall(update_rules)
|
|
||||||
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
|
||||||
shell.run("reboot")
|
|
||||||
end
|
|
||||||
|
|
||||||
sleep() -- Other calls should already yield, this is just in case
|
|
||||||
return main_loop()
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setPaletteColor(colors.black, 0x000000)
|
|
||||||
term.setPaletteColor(colors.gray, 0x343434)
|
|
||||||
term.setPaletteColor(colors.lightGray, 0xababab)
|
|
||||||
term.setPaletteColor(colors.red, 0xff0000)
|
|
||||||
term.setPaletteColor(colors.green, 0x00ff00)
|
|
||||||
term.setPaletteColor(colors.blue, 0x0000ff)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
local width = term.getSize()
|
|
||||||
info_window = make_section("INFORMATION", 2, 2, width - 2, 7)
|
|
||||||
rules_window = make_section("SAFETY RULES", 2, 10, width - 2, 16)
|
|
||||||
|
|
||||||
parallel.waitForAny(main_loop, function()
|
|
||||||
os.pullEventRaw("terminate")
|
|
||||||
end)
|
|
||||||
|
|
||||||
--os.reboot()
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
--Stable data
|
|
||||||
local p=peripheral.wrap("fissionReactorLogicAdapter_2")
|
|
||||||
local maxburn= tonumber(p.getMaxBurnRate())
|
|
||||||
local Height= tonumber(p.getHeight())
|
|
||||||
local Length= tonumber(p.getLength())
|
|
||||||
local Width= tonumber(p.getWidth())
|
|
||||||
local WasteCap= tonumber(p.getWasteCapacity())
|
|
||||||
local Coolantcap= tonumber(p.getCoolantCapacity())
|
|
||||||
local FuelCap= tonumber(p.getFuelCapacity())
|
|
||||||
while true do
|
|
||||||
--Live Data
|
|
||||||
local CurrentFuel= tonumber(p.getFuel().amount)
|
|
||||||
local CurrentCoolant= tonumber(p.getCoolant().amount)
|
|
||||||
local CurrentWaste= tonumber(p.getWaste().amount)
|
|
||||||
--Math
|
|
||||||
local TotalFuel= (CurrentFuel/FuelCap)*100
|
|
||||||
TotalFuel = string.format("%4.2f", TotalFuel)
|
|
||||||
local TotalCoolant= (CurrentCoolant/Coolantcap)*100
|
|
||||||
TotalCoolant = string.format("%4.2f", TotalCoolant)
|
|
||||||
local TotalWaste= (CurrentWaste/WasteCap)*100
|
|
||||||
TotalWaste = string.format("%4.2f", TotalWaste)
|
|
||||||
--Screen Clear
|
|
||||||
term.setCursorPos(0,0)
|
|
||||||
term.clear()
|
|
||||||
--Print Data
|
|
||||||
print("Max Burnrate: " .. maxburn .."\nCoolant Capacity: "..Coolantcap.."\nCoolant Percent: "..TotalCoolant.."\nCurrent Coolant: "..CurrentCoolant.."\nFuel Capacity: ".. FuelCap.."\nFuel Percent: "..TotalFuel.."\nCurrent Fuel: "..CurrentFuel.."\nWaste Capacity: "..WasteCap.."\nWaste Percent: "..TotalWaste.."\nCurrent Waste: "..CurrentWaste.."\nHeight: "..Height.."\nLength: "..Length.."\nWidth: "..Width)
|
|
||||||
sleep(1)
|
|
||||||
end
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
local p=peripheral.wrap("fissionReactorLogicAdapter_2")
|
|
||||||
local maxburn= tonumber(p.getMaxBurnRate())
|
|
||||||
local Height= tonumber(p.getHeight())
|
|
||||||
local Length= tonumber(p.getLength())
|
|
||||||
local Width= tonumber(p.getWidth())
|
|
||||||
local WastePercent= tonumber(p.getWasteCapacity())
|
|
||||||
local Coolantcap= tonumber(p.getCoolantCapacity())
|
|
||||||
local FuelCap= tonumber(p.getFuelCapacity())
|
|
||||||
print("Max Burnrate: " .. maxburn .."\nCoolant Capacity: "..Coolantcap.."\nFuel Capacity: ".. FuelCap.."\nWaste Capacity: "..WastePercent.."\nHeight: "..Height.."\nLength: "..Length.."\nWidth: "..Width)
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
local p=peripheral.wrap("fissionReactorLogicAdapter_2")
|
|
||||||
local burn = 0
|
|
||||||
local maxburn= tonumber(p.getMaxBurnRate())
|
|
||||||
while true do
|
|
||||||
burn = tonumber(read())
|
|
||||||
if burn > maxburn then
|
|
||||||
print("Burnrate not reachable")
|
|
||||||
else
|
|
||||||
if burn > 100 then
|
|
||||||
print("Burn rate to high")
|
|
||||||
else
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
p.setBurnRate(burn)
|
|
||||||
print("Reactor Burnrate =",p.getBurnRate())
|
|
||||||
@@ -1,252 +0,0 @@
|
|||||||
sleep(0)
|
|
||||||
local state, data, reactor, turbine, info_window, rules_window
|
|
||||||
|
|
||||||
local STATES = {
|
|
||||||
READY = 1, -- Reactor is off and can be started with the lever
|
|
||||||
RUNNING = 2, -- Reactor is running and all rules are met
|
|
||||||
ESTOP = 3, -- Reactor is stopped due to rule(s) being violated
|
|
||||||
UNKNOWN = 4, -- Reactor or turbine peripherals are missing
|
|
||||||
}
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local rules = {}
|
|
||||||
|
|
||||||
local function add_rule(name, fn)
|
|
||||||
table.insert(rules, function()
|
|
||||||
local ok, rule_met, value = pcall(fn)
|
|
||||||
if ok then
|
|
||||||
return rule_met, string.format("%s (%s)", name, value)
|
|
||||||
else
|
|
||||||
return false, name
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
add_rule("REACTOR TEMPERATURE <= 5100K", function()
|
|
||||||
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
|
||||||
return data.reactor_temp <= 5100, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR DAMAGE <= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
|
||||||
return data.reactor_damage <= 10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR COOLANT LEVEL >= 50%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
|
||||||
return data.reactor_coolant >= 0.50, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR WASTE LEVEL <= 90%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100))
|
|
||||||
return data.reactor_waste <= 0.90, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 1 ENERGY LEVEL <= 30%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
|
||||||
return data.turbine1_energy <= 0.30, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
--add_rule("TURBINE 2 ENERGY LEVEL <= 30%", function()
|
|
||||||
--local value = string.format("%3d%%", math.ceil(data.turbine2_energy * 100))
|
|
||||||
--return data.turbine2_energy <= 0.30, value
|
|
||||||
--end)
|
|
||||||
|
|
||||||
local function all_rules_met()
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if not rule() then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Allow manual emergency stop with SCRAM button
|
|
||||||
return state ~= STATES.RUNNING or data.reactor_on
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function update_data()
|
|
||||||
data = {
|
|
||||||
lever_on = redstone.getInput("top"),
|
|
||||||
|
|
||||||
reactor_on = reactor.getStatus(),
|
|
||||||
reactor_burn_rate = reactor.getBurnRate(),
|
|
||||||
reactor_max_burn_rate = reactor.getMaxBurnRate(),
|
|
||||||
reactor_temp = reactor.getTemperature(),
|
|
||||||
reactor_damage = reactor.getDamagePercent(),
|
|
||||||
reactor_coolant = reactor.getCoolantFilledPercentage(),
|
|
||||||
reactor_waste = reactor.getWasteFilledPercentage(),
|
|
||||||
|
|
||||||
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
|
||||||
--turbine2_energy = turbine2.getEnergyFilledPercentage(),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function colored(text, fg, bg)
|
|
||||||
term.setTextColor(fg or colors.white)
|
|
||||||
term.setBackgroundColor(bg or colors.black)
|
|
||||||
term.write(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_section(name, x, y, w, h)
|
|
||||||
for row = 1, h do
|
|
||||||
term.setCursorPos(x, y + row - 1)
|
|
||||||
local char = (row == 1 or row == h) and "\127" or " "
|
|
||||||
colored("\127" .. string.rep(char, w - 2) .. "\127", colors.gray)
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setCursorPos(x + 2, y)
|
|
||||||
colored(" " .. name .. " ")
|
|
||||||
|
|
||||||
return window.create(term.current(), x + 2, y + 2, w - 4, h - 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update_info()
|
|
||||||
local prev_term = term.redirect(info_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
if state == STATES.UNKNOWN then
|
|
||||||
colored("ERROR RETRIEVING DATA", colors.red)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
colored("REACTOR: ")
|
|
||||||
colored(data.reactor_on and "ON " or "OFF", data.reactor_on and colors.green or colors.red)
|
|
||||||
colored(" LEVER: ")
|
|
||||||
colored(data.lever_on and "ON " or "OFF", data.lever_on and colors.green or colors.red)
|
|
||||||
colored(" R. LIMIT: ")
|
|
||||||
colored(string.format("%4.1f", data.reactor_burn_rate), colors.blue)
|
|
||||||
colored("/", colors.lightGray)
|
|
||||||
colored(string.format("%4.1f", data.reactor_max_burn_rate), colors.blue)
|
|
||||||
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
|
|
||||||
colored("STATUS: ")
|
|
||||||
if state == STATES.READY then
|
|
||||||
colored("READY, flip lever to start", colors.blue)
|
|
||||||
elseif state == STATES.RUNNING then
|
|
||||||
colored("RUNNING, flip lever to stop", colors.green)
|
|
||||||
elseif state == STATES.ESTOP and not all_rules_met() then
|
|
||||||
colored("EMERGENCY STOP, safety rules violated", colors.red)
|
|
||||||
elseif state == STATES.ESTOP then
|
|
||||||
colored("EMERGENCY STOP, toggle lever to reset", colors.red)
|
|
||||||
end -- STATES.UNKNOWN cases handled above
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
local estop_reasons = {}
|
|
||||||
|
|
||||||
local function update_rules()
|
|
||||||
local prev_term = term.redirect(rules_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
|
|
||||||
if state ~= STATES.ESTOP then
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
local ok, text = rule()
|
|
||||||
term.setCursorPos(1, i)
|
|
||||||
if ok and not estop_reasons[i] then
|
|
||||||
colored("[ OK ] ", colors.green)
|
|
||||||
colored(text, colors.lightGray)
|
|
||||||
else
|
|
||||||
colored("[ FAIL ] ", colors.red)
|
|
||||||
colored(text, colors.red)
|
|
||||||
estop_reasons[i] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function main_loop()
|
|
||||||
-- Search for peripherals again if one or both are missing
|
|
||||||
if not state or state == STATES.UNKNOWN then
|
|
||||||
reactor = peripheral.wrap("fissionReactorLogicAdapter_2")
|
|
||||||
turbine1 = peripheral.wrap("turbineValve_1")
|
|
||||||
--turbine2 = peripheral.wrap("turbineValve_2")
|
|
||||||
end
|
|
||||||
if not pcall(update_data) then
|
|
||||||
-- Error getting data (either reactor or turbine is nil?)
|
|
||||||
data = {}
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.reactor_on == nil then
|
|
||||||
-- Reactor is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine1_energy == nil then
|
|
||||||
-- Turbine 1 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
--elseif data.turbine2_energy == nil then
|
|
||||||
-- Turbine 2 is not connected
|
|
||||||
--state = STATES.UNKNOWN
|
|
||||||
elseif not state then
|
|
||||||
-- Program just started, get current state from lever
|
|
||||||
state = data.lever_on and STATES.RUNNING or STATES.READY
|
|
||||||
elseif state == STATES.READY and data.lever_on then
|
|
||||||
-- READY -> RUNNING
|
|
||||||
state = STATES.RUNNING
|
|
||||||
-- Activate reactor
|
|
||||||
pcall(reactor.activate)
|
|
||||||
data.reactor_on = true
|
|
||||||
elseif state == STATES.RUNNING and not data.lever_on then
|
|
||||||
-- RUNNING -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.ESTOP and not data.lever_on then
|
|
||||||
-- ESTOP -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.UNKNOWN then
|
|
||||||
-- UNKNOWN -> ESTOP
|
|
||||||
state = data.lever_on and STATES.ESTOP or STATES.READY
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Always enter ESTOP if safety rules are not met
|
|
||||||
if state ~= STATES.UNKNOWN and not all_rules_met() then
|
|
||||||
state = STATES.ESTOP
|
|
||||||
end
|
|
||||||
|
|
||||||
-- SCRAM reactor if not running
|
|
||||||
if state ~= STATES.RUNNING and reactor then
|
|
||||||
pcall(reactor.scram)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update info and rules windows
|
|
||||||
pcall(update_info)
|
|
||||||
pcall(update_rules)
|
|
||||||
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
|
||||||
reactor.activate()
|
|
||||||
end
|
|
||||||
--if data.turbine2_energy < 0.1 and state == data.lever_on then
|
|
||||||
--reactor.activate()
|
|
||||||
--end
|
|
||||||
|
|
||||||
sleep() -- Other calls should already yield, this is just in case
|
|
||||||
return main_loop()
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setPaletteColor(colors.black, 0x000000)
|
|
||||||
term.setPaletteColor(colors.gray, 0x343434)
|
|
||||||
term.setPaletteColor(colors.lightGray, 0xababab)
|
|
||||||
term.setPaletteColor(colors.red, 0xff0000)
|
|
||||||
term.setPaletteColor(colors.green, 0x00ff00)
|
|
||||||
term.setPaletteColor(colors.blue, 0x0000ff)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
local width = term.getSize()
|
|
||||||
info_window = make_section("INFORMATION", 2, 2, width - 2, 7)
|
|
||||||
rules_window = make_section("SAFETY RULES", 2, 10, width - 2, 10)
|
|
||||||
|
|
||||||
parallel.waitForAny(main_loop, function()
|
|
||||||
os.pullEventRaw("terminate")
|
|
||||||
end)
|
|
||||||
|
|
||||||
--os.reboot()
|
|
||||||
@@ -1,257 +0,0 @@
|
|||||||
sleep(0)
|
|
||||||
local state, data, reactor, turbine, info_window, rules_window
|
|
||||||
|
|
||||||
local STATES = {
|
|
||||||
READY = 1, -- Reactor is off and can be started with the lever
|
|
||||||
RUNNING = 2, -- Reactor is running and all rules are met
|
|
||||||
ESTOP = 3, -- Reactor is stopped due to rule(s) being violated
|
|
||||||
UNKNOWN = 4, -- Reactor or turbine peripherals are missing
|
|
||||||
}
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local rules = {}
|
|
||||||
|
|
||||||
local function add_rule(name, fn)
|
|
||||||
table.insert(rules, function()
|
|
||||||
local ok, rule_met, value = pcall(fn)
|
|
||||||
if ok then
|
|
||||||
return rule_met, string.format("%s (%s)", name, value)
|
|
||||||
else
|
|
||||||
return false, name
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
add_rule("REACTOR TEMPERATURE <= 5100K", function()
|
|
||||||
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
|
||||||
return data.reactor_temp <= 5100, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR DAMAGE <= 10%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
|
||||||
return data.reactor_damage <= 10, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR COOLANT LEVEL >= 50%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
|
||||||
return data.reactor_coolant >= 0.50, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
|
||||||
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
|
||||||
return data.reactor_fuel >= 0.05, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("REACTOR WASTE LEVEL <= 90%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100))
|
|
||||||
return data.reactor_waste <= 0.90, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 1 ENERGY LEVEL <= 30%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
|
||||||
return data.turbine1_energy <= 0.30, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
add_rule("TURBINE 2 ENERGY LEVEL <= 30%", function()
|
|
||||||
local value = string.format("%3d%%", math.ceil(data.turbine2_energy * 100))
|
|
||||||
return data.turbine2_energy <= 0.30, value
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function all_rules_met()
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
if not rule() then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Allow manual emergency stop with SCRAM button
|
|
||||||
return state ~= STATES.RUNNING or data.reactor_on
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function update_data()
|
|
||||||
data = {
|
|
||||||
lever_on = redstone.getInput("top"),
|
|
||||||
|
|
||||||
reactor_on = reactor.getStatus(),
|
|
||||||
reactor_burn_rate = reactor.getBurnRate(),
|
|
||||||
reactor_max_burn_rate = reactor.getMaxBurnRate(),
|
|
||||||
reactor_temp = reactor.getTemperature(),
|
|
||||||
reactor_damage = reactor.getDamagePercent(),
|
|
||||||
reactor_coolant = reactor.getCoolantFilledPercentage(),
|
|
||||||
reactor_waste = reactor.getWasteFilledPercentage(),
|
|
||||||
reactor_fuel = reactor.getFuelFilledPercentage(),
|
|
||||||
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
|
||||||
turbine2_energy = turbine2.getEnergyFilledPercentage(),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function colored(text, fg, bg)
|
|
||||||
term.setTextColor(fg or colors.white)
|
|
||||||
term.setBackgroundColor(bg or colors.black)
|
|
||||||
term.write(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_section(name, x, y, w, h)
|
|
||||||
for row = 1, h do
|
|
||||||
term.setCursorPos(x, y + row - 1)
|
|
||||||
local char = (row == 1 or row == h) and "\127" or " "
|
|
||||||
colored("\127" .. string.rep(char, w - 2) .. "\127", colors.gray)
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setCursorPos(x + 3, y)
|
|
||||||
colored(" " .. name .. " ")
|
|
||||||
|
|
||||||
return window.create(term.current(), x + 2, y + 2, w - 4, h - 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update_info()
|
|
||||||
local prev_term = term.redirect(info_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
if state == STATES.UNKNOWN then
|
|
||||||
colored("ERROR RETRIEVING DATA", colors.red)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
colored("REACTOR: ")
|
|
||||||
colored(data.reactor_on and "ON " or "OFF", data.reactor_on and colors.green or colors.red)
|
|
||||||
colored(" LEVER: ")
|
|
||||||
colored(data.lever_on and "ON " or "OFF", data.lever_on and colors.green or colors.red)
|
|
||||||
colored(" R. LIMIT: ")
|
|
||||||
colored(string.format("%4.2f", data.reactor_burn_rate), colors.blue)
|
|
||||||
colored("/", colors.lightGray)
|
|
||||||
colored(string.format("%4.1f", data.reactor_max_burn_rate), colors.blue)
|
|
||||||
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
|
|
||||||
colored("STATUS: ")
|
|
||||||
if state == STATES.READY then
|
|
||||||
colored("READY, flip lever to start", colors.blue)
|
|
||||||
elseif state == STATES.RUNNING then
|
|
||||||
colored("RUNNING, flip lever to stop", colors.green)
|
|
||||||
elseif state == STATES.ESTOP and not all_rules_met() then
|
|
||||||
colored("EMERGENCY STOP, safety rules violated", colors.red)
|
|
||||||
elseif state == STATES.ESTOP then
|
|
||||||
colored("EMERGENCY STOP, toggle lever to reset", colors.red)
|
|
||||||
end -- STATES.UNKNOWN cases handled above
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
local estop_reasons = {}
|
|
||||||
|
|
||||||
local function update_rules()
|
|
||||||
local prev_term = term.redirect(rules_window)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
|
|
||||||
if state ~= STATES.ESTOP then
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, rule in ipairs(rules) do
|
|
||||||
local ok, text = rule()
|
|
||||||
term.setCursorPos(1, i)
|
|
||||||
if ok and not estop_reasons[i] then
|
|
||||||
colored("[ OK ] ", colors.green)
|
|
||||||
colored(text, colors.lightGray)
|
|
||||||
else
|
|
||||||
colored("[ FAIL ] ", colors.red)
|
|
||||||
colored(text, colors.red)
|
|
||||||
estop_reasons[i] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.redirect(prev_term)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
local function main_loop()
|
|
||||||
-- Search for peripherals again if one or both are missing
|
|
||||||
if not state or state == STATES.UNKNOWN then
|
|
||||||
reactor = peripheral.wrap("fissionReactorLogicAdapter_2")
|
|
||||||
turbine1 = peripheral.wrap("turbineValve_1")
|
|
||||||
turbine2 = peripheral.wrap("turbineValve_2")
|
|
||||||
end
|
|
||||||
if not pcall(update_data) then
|
|
||||||
-- Error getting data (either reactor or turbine is nil?)
|
|
||||||
data = {}
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.reactor_on == nil then
|
|
||||||
-- Reactor is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine1_energy == nil then
|
|
||||||
-- Turbine 1 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif data.turbine2_energy == nil then
|
|
||||||
-- Turbine 2 is not connected
|
|
||||||
state = STATES.UNKNOWN
|
|
||||||
elseif not state then
|
|
||||||
-- Program just started, get current state from lever
|
|
||||||
state = data.lever_on and STATES.RUNNING or STATES.READY
|
|
||||||
elseif state == STATES.READY and data.lever_on then
|
|
||||||
-- READY -> RUNNING
|
|
||||||
state = STATES.RUNNING
|
|
||||||
-- Activate reactor
|
|
||||||
pcall(reactor.activate)
|
|
||||||
data.reactor_on = true
|
|
||||||
elseif state == STATES.RUNNING and not data.lever_on then
|
|
||||||
-- RUNNING -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.ESTOP and not data.lever_on then
|
|
||||||
-- ESTOP -> READY
|
|
||||||
state = STATES.READY
|
|
||||||
elseif state == STATES.UNKNOWN then
|
|
||||||
-- UNKNOWN -> ESTOP
|
|
||||||
state = data.lever_on and STATES.ESTOP or STATES.READY
|
|
||||||
estop_reasons = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Always enter ESTOP if safety rules are not met
|
|
||||||
if state ~= STATES.UNKNOWN and not all_rules_met() then
|
|
||||||
state = STATES.ESTOP
|
|
||||||
end
|
|
||||||
|
|
||||||
-- SCRAM reactor if not running
|
|
||||||
if state ~= STATES.RUNNING and reactor then
|
|
||||||
pcall(reactor.scram)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update info and rules windows
|
|
||||||
pcall(update_info)
|
|
||||||
pcall(update_rules)
|
|
||||||
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
|
||||||
reactor.activate()
|
|
||||||
end
|
|
||||||
if data.turbine2_energy < 0.1 and state == data.lever_on then
|
|
||||||
reactor.activate()
|
|
||||||
end
|
|
||||||
|
|
||||||
sleep() -- Other calls should already yield, this is just in case
|
|
||||||
return main_loop()
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setPaletteColor(colors.black, 0x000000)
|
|
||||||
term.setPaletteColor(colors.gray, 0x343434)
|
|
||||||
term.setPaletteColor(colors.lightGray, 0xababab)
|
|
||||||
term.setPaletteColor(colors.red, 0xff0000)
|
|
||||||
term.setPaletteColor(colors.green, 0x00ff00)
|
|
||||||
term.setPaletteColor(colors.blue, 0x0000ff)
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
local width = term.getSize()
|
|
||||||
info_window = make_section("INFORMATION", 2, 2, width - 2, 7)
|
|
||||||
rules_window = make_section("SAFETY RULES", 2, 10, width - 2, 10)
|
|
||||||
|
|
||||||
parallel.waitForAny(main_loop, function()
|
|
||||||
os.pullEventRaw("terminate")
|
|
||||||
end)
|
|
||||||
|
|
||||||
--os.reboot()
|
|
||||||
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
server_id=15
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
local file = fs.open("/disk/email.conf","r")
|
|
||||||
local conf = load("return {"..file.readAll().."}")()
|
|
||||||
local modem = peripheral.wrap("top")
|
|
||||||
modem.open(tonumber(conf.server_id))
|
|
||||||
print("Email server is running...")
|
|
||||||
|
|
||||||
while true do
|
|
||||||
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
|
||||||
if message == "35" then
|
|
||||||
modem.transmit(replyChannel, 15, 135)
|
|
||||||
else
|
|
||||||
-- Here you would handle authentication, e.g. check user:pass
|
|
||||||
print("Received credentials: " .. tostring(message))
|
|
||||||
-- You can add logic to check credentials and respond accordingly
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
local file = fs.open("/disk/email.conf","r")
|
|
||||||
local conf = load("return {"..file.readAll().."}")()
|
|
||||||
local modem = peripheral.wrap("top")
|
|
||||||
print("What is your username?")
|
|
||||||
local user = io.read()
|
|
||||||
print("Password?")
|
|
||||||
local password = io.read()
|
|
||||||
modem.open(tonumber(conf.server_id))
|
|
||||||
modem.transmit(15, 20, "35")
|
|
||||||
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
|
||||||
if message ~= 135 then
|
|
||||||
local p = shell.getRunningProgram()
|
|
||||||
shell.run(p)
|
|
||||||
end
|
|
||||||
local userpass = user..":"..pass
|
|
||||||
modem.transmit(15, 20, userpass)
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
--local tArgs = { ... }
|
|
||||||
--if #tArgs == 0 then
|
|
||||||
-- local programName = arg[0] or fs.getName(shell.getRunningProgram())
|
|
||||||
-- print("Usage: " .. programName .. " options <path>")
|
|
||||||
-- return
|
|
||||||
--end
|
|
||||||
|
|
||||||
-- Error checking
|
|
||||||
--local sPath = shell.resolve(tArgs[2])
|
|
||||||
--local bReadOnly = fs.isReadOnly(sPath)
|
|
||||||
--if fs.exists(sPath) and fs.isDir(sPath) then
|
|
||||||
-- print("Cannot edit a directory.")
|
|
||||||
-- return
|
|
||||||
--end
|
|
||||||
|
|
||||||
--local lex_context = { line = function() end, report = function() end }
|
|
||||||
|
|
||||||
--local tCompletions
|
|
||||||
--local nCompletion
|
|
||||||
|
|
||||||
--local tCompleteEnv = _ENV
|
|
||||||
--local function complete(sLine)
|
|
||||||
-- if settings.get("edit.autocomplete") then
|
|
||||||
-- local nStartPos = string.find(sLine, "[a-zA-Z0-9_%.:]+$")
|
|
||||||
-- if nStartPos then
|
|
||||||
-- sLine = string.sub(sLine, nStartPos)
|
|
||||||
-- end
|
|
||||||
-- if #sLine > 0 then
|
|
||||||
-- return textutils.complete(sLine, tCompleteEnv)
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- return nil
|
|
||||||
--end
|
|
||||||
|
|
||||||
local args = { ... }
|
|
||||||
|
|
||||||
local function printHelp()
|
|
||||||
print("options discription")
|
|
||||||
print("-m program")
|
|
||||||
print("--help or -h help")
|
|
||||||
end
|
|
||||||
|
|
||||||
if args == "--help" or args == "-h" then
|
|
||||||
printHelp()
|
|
||||||
elseif args == "-m" then
|
|
||||||
local fileName = tArgs[2]
|
|
||||||
local file = fs.open(fileName, "r")
|
|
||||||
local data = file.readAll()
|
|
||||||
file.close()
|
|
||||||
print(data.."\n [End Of File]")
|
|
||||||
else
|
|
||||||
printHelp()
|
|
||||||
end
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
url="https://git.astronand.dev/minecartchris/Lua---CC-bs/raw/branch/main/git/filePrinter/"
|
|
||||||
files=["project.file", "program.lua"]
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
shell.run("ls /git/")
|
|
||||||
print("What project would you like to update?")
|
|
||||||
local projectName = io.read()
|
|
||||||
local URL, projectFile
|
|
||||||
if fs.exists("/git/"..projectName.."/project.file") then
|
|
||||||
local file = fs.open("/git/"..projectName.."/project.file", "r")
|
|
||||||
projectFile = load("return {"..(file.readAll() or "").."}")()
|
|
||||||
file.close()
|
|
||||||
print(textutils.serialise(projectFile))
|
|
||||||
URL = projectFile.url
|
|
||||||
else
|
|
||||||
print("please enter git url or make a project file")
|
|
||||||
URL = io.read()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
fs.delete("/git/"..projectName.."/*")
|
|
||||||
--shell.run("cd /git/"..projectName)
|
|
||||||
local i = 1
|
|
||||||
local list = projectFile.files
|
|
||||||
while i < #list do
|
|
||||||
shell.run("wget "..URL.."/git/ "..projectName.."/"..list[i])
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
--shell.run("wget "..URL.."/git/ "..projectName.."/")
|
|
||||||
shell.run("cd /")
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
url="https://git.astronand.dev/minecartchris/Lua---CC-bs/raw/branch/main/updater/updaterTest",
|
|
||||||
files={"project.file"}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
return {
|
|
||||||
start = nil, -- function(version, config, products, shopState)
|
|
||||||
preProduct = nil, -- function(transaction, transactionCurrency, meta, productAddress, products) returns product, errored, errorMessage
|
|
||||||
-- If product is nil, product will be selected by the shop,
|
|
||||||
-- If product is false, customer will be refunded for no product found.
|
|
||||||
-- If product is false and errored is true, customer will be refunded with error message.
|
|
||||||
preStockCheck = nil, -- function(transaction, productsPurchased, products, amountPurchased) returns continueTransaction, errored, errorMessage, invisible
|
|
||||||
prePurchase = nil, -- function(product, amount, refundAmount, transaction, transactionCurrency) returns continueTransaction, errored, errorMessage, invisible
|
|
||||||
purchase = function(product, amount, refundAmount, transaction, transactionCurrency)
|
|
||||||
local DiscordHook = require("DiscordHook")
|
|
||||||
local success, hook = DiscordHook.createWebhook("webhook here")
|
|
||||||
if not success then
|
|
||||||
error("connection failed")
|
|
||||||
end
|
|
||||||
--local product, amount = radon.purchase()
|
|
||||||
|
|
||||||
hook.sendEmbed("your userID here", "Shop", "you shop sold "..amount.." of "..product.name.." using "..transactionCurrency.id)
|
|
||||||
end,
|
|
||||||
failedPurchase = nil, -- function(transaction, transactionCurrency, product, errorMessage)
|
|
||||||
programError = nil, -- function(err)
|
|
||||||
blink = nil, -- function(blinkState) called every 3 seconds while shop is running
|
|
||||||
configSaved = nil, -- function(config) called when config is edited (replaced)
|
|
||||||
productsSaved = nil, -- function(products) called when products object is edited (replaced)
|
|
||||||
onInventoryRefresh = nil, -- function(products, items) called when inventory is refreshed, product quantity can be set through products table
|
|
||||||
onProductSelected = nil, -- function(product, currency) called when product is clicked on the shop screen
|
|
||||||
parallel = nil, -- function() called in parallel constantly. Allowed to be blocking for usage in creating parallel apps.
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user