Upload files to "Lua minecraft"
This commit is contained in:
314
Lua minecraft/6TurbineFuelFi.lua
Normal file
314
Lua minecraft/6TurbineFuelFi.lua
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
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()
|
||||||
258
Lua minecraft/Fuelfi.lua
Normal file
258
Lua minecraft/Fuelfi.lua
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
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()
|
||||||
244
Lua minecraft/Fuelfi2.lua
Normal file
244
Lua minecraft/Fuelfi2.lua
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
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()
|
||||||
244
Lua minecraft/Fuelfi3.lua
Normal file
244
Lua minecraft/Fuelfi3.lua
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
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()
|
||||||
28
Lua minecraft/LiveReactor.lua
Normal file
28
Lua minecraft/LiveReactor.lua
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
--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
|
||||||
9
Lua minecraft/Reactordata.lua
Normal file
9
Lua minecraft/Reactordata.lua
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
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)
|
||||||
18
Lua minecraft/burnrate.lua
Normal file
18
Lua minecraft/burnrate.lua
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
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())
|
||||||
252
Lua minecraft/fi.lua
Normal file
252
Lua minecraft/fi.lua
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
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()
|
||||||
257
Lua minecraft/fi2.lua
Normal file
257
Lua minecraft/fi2.lua
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
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()
|
||||||
Reference in New Issue
Block a user