local configPath = "config"
-- ========= TROVA PERIFERICHE =========
local function findPeripheral(t)
for _, side in ipairs(rs.getSides()) do
if peripheral.isPresent(side) and peripheral.getType(side) == t then
return peripheral.wrap(side), side
end
end
return nil
end
-- ========= CONFIGURAZIONE =========
local function loadConfig()
if not fs.exists(configPath) then return nil end
local f = fs.open(configPath,"r")
local data=f.readAll() f.close()
local func=loadstring(data)
if func then return func() else error("Errore nel config") end
end
term.setTextColor(colors.yellow)
print("Avvio centrale di controllo...")
sleep(0.3)
local config = loadConfig()
if not config then
term.setTextColor(colors.white)
print("Configurazione non trovata. Creazione guidata...\n")
local validColors = {}
for k,v in pairs(colors) do validColors[k]=v end
local reactors = {}
while true do
write("Nome reattore: ") local name = read()
local id
repeat write("ID rednet: ") id = tonumber(read()) until id
local color
repeat write("Colore principale (white, blue, ...): ") color = read() until validColors[color]
local scramColor
repeat write("Colore reset SCRAM: ") scramColor = read() until validColors[scramColor]
table.insert(reactors,{name=name,id=id,color=color,scram_color=scramColor})
if #reactors >= 8 then break end
write("Altro reattore? (s/n): ") if read():lower()~="s" then break end
end
config = {reactors=reactors, update_interval=2}
local f = fs.open(configPath,"w")
f.write("return "..textutils.serialize(config))
f.close()
end
if type(config.update_interval)~="number" then config.update_interval=2 end
term.setTextColor(colors.cyan)
print("\n[ Inizializzazione periferiche ]")
sleep(0.3)
local modem, modemSide = findPeripheral("modem")
if not modem then error("Nessun modem trovato!") end
rednet.open(modemSide)
term.setTextColor(colors.lime)
print("✔ Modem su "..modemSide)
sleep(0.2)
local mon, monSide = findPeripheral("monitor")
if not mon then error("Nessun monitor trovato!") end
mon.setBackgroundColor(colors.black)
mon.setTextColor(colors.white)
mon.clear()
local monitorSizeX, monitorSizeY = mon.getSize()
term.setTextColor(colors.lime)
print("✔ Monitor su "..monSide)
sleep(0.5)
term.setTextColor(colors.yellow)
print("Inizializzazione completata.")
sleep(1)
term.clear()
term.setCursorPos(1,1)
-- ========= VARIABILI =========
local reactors = {}
local previousStates = {}
local scramActive = false
local reactorsInSCRAM = {} -- mappa id -> true/false
-- ========= UTILITY =========
local function colorByTemp(p)
if p < 60 then return colors.green
elseif p < 85 then return colors.orange
else return colors.red end
end
local function drawBar(x,y,w,perc,color)
local filled = math.floor(w*perc/100)
mon.setCursorPos(x,y)
mon.setBackgroundColor(colors.gray)
mon.write(string.rep(" ",w))
mon.setCursorPos(x,y)
mon.setBackgroundColor(color)
mon.write(string.rep(" ",filled))
mon.setBackgroundColor(colors.black)
end
-- ========= RACCOLTA DATI =========
local function getReactorsInfo(config)
local reactors = {}
for _,r in ipairs(config.reactors) do
term.setTextColor(colors.lightBlue)
print("Richiesta dati a "..r.name.." (ID "..r.id..")...")
local command = textutils.serialize({command = "reactor_info"})
rednet.send(r.id, command)
local start=os.clock()
local sender,msg
repeat
sender,msgTmp=rednet.receive(5)
if msgTmp then msg=textutils.unserialize(msgTmp) end
until sender==r.id or os.clock()-start>5
if sender==r.id and type(msg)=="table" and msg.type=="info" then
term.setTextColor(colors.lime)
print("Dati ricevuti da "..r.name)
reactors[r.id]=msg.data
else
term.setTextColor(colors.red)
print("Nessuna risposta da "..r.name)
reactors[r.id]=nil
end
end
return reactors
end
-- ========= UI =========
local function drawUI()
mon.setBackgroundColor(colors.black)
mon.setTextColor(colors.white)
mon.clear()
mon.setCursorPos((monitorSizeX/2)-12,1)
mon.write("=== CENTRALE NUCLEARE ===")
mon.setCursorPos((monitorSizeX/2)-9,2)
mon.write("Aggiornato: " .. textutils.formatTime(os.time(), true))
local y=4
local x=2
local reactorCount = 0
local reactorPerPage = math.floor(((monitorSizeY-3)/6)+0.5)
for _,r in ipairs(config.reactors) do
reactorCount = reactorCount+1
local info = reactors[r.id]
mon.setCursorPos(x,y)
mon.setTextColor(colors.cyan)
mon.write(r.name)
y=y+1
if info then
mon.setCursorPos(x+15,y-1)
local perc = math.floor((info.temp/info.maxHeat)*100)
if info.SCRAMState then
mon.setTextColor(colors.red) mon.write("STATO: SCRAM")
elseif info.active then
mon.setTextColor(colors.lime) mon.write("STATO: ATTIVO")
else
mon.setTextColor(colors.orange) mon.write("STATO: SPENTO")
end
mon.setTextColor(colors.yellow)
mon.setCursorPos(x+2,y)
mon.write(string.format("MaxOut:%d | Out:%d", info.maxOutput, info.effectiveOutput))
y=y+1
mon.setCursorPos(x+2,y)
mon.write(string.format("Temp:%d/%d (%d%%)", info.temp, info.maxHeat, perc))
y=y+1
drawBar(x+2,y,22,perc+30,colorByTemp(perc))
y=y+1
else
mon.setTextColor(colors.red)
mon.write(" Nessuna risposta")
y=y+1
end
y=y+2
if reactorCount % reactorPerPage == 0 then
mon.setTextColor(colors.white)
for i=4,monitorSizeY do
mon.setCursorPos(monitorSizeX/2,i)
mon.write("|")
end
x=x+(monitorSizeX/2)
y=4
end
end
end
-- ========= CONTROLLO NORMALE =========
local function checkInput()
local activeColors = rs.getBundledInput("right")
for _,r in ipairs(config.reactors) do
local isActive = colors.test(activeColors, colors[r.color])
if previousStates[r.id] ~= isActive then
local command = textutils.serialize({command="reactor_control", newState=isActive})
rednet.send(r.id, command)
previousStates[r.id] = isActive
end
end
end
-- ========= CONTROLLO SCRAM =========
local function checkSCRAM()
local foundSCRAM = false
for _,r in ipairs(config.reactors) do
local info = reactors[r.id]
if info and info.SCRAMState then
reactorsInSCRAM[r.id] = true
foundSCRAM = true
else
reactorsInSCRAM[r.id] = false
end
end
if foundSCRAM and not scramActive then
term.setTextColor(colors.red)
print("[SCRAM] Attivato! Impulso su uscita.")
rs.setBundledOutput("back", colors.orange)
sleep(1)
rs.setBundledOutput("back", 0)
scramActive = true
elseif not foundSCRAM and scramActive then
term.setTextColor(colors.lime)
print("[SCRAM] Tutti i reattori OK. SCRAM disattivo.")
scramActive = false
end
end
-- ========= CONTROLLO INPUT SCRAM =========
local function checkInputSCRAM()
if not scramActive then return end
local activeColors = rs.getBundledInput("right")
for _,r in ipairs(config.reactors) do
if reactorsInSCRAM[r.id] then
local trigger = colors.test(activeColors, colors[r.scram_color])
if trigger then
term.setTextColor(colors.yellow)
print("[SCRAM RESET] Ricevuto segnale reset da "..r.name)
rs.setBundledOutput("back", 0)
rednet.send(r.id, textutils.serialize({command="reset_SCRAM"}))
reactorsInSCRAM[r.id] = false
end
end
end
end
-- ========= LOOP PRINCIPALE =========
while true do
reactors = getReactorsInfo(config)
checkSCRAM()
checkInputSCRAM()
checkInput()
drawUI()
term.setTextColor(colors.gray)
print("Aggiornamento completato.\n")
sleep(config.update_interval)
end