Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- ============================================================================
- -- CONTROLLO REATTORE IC2 CON LOGICA GATE INTEGRATA
- -- ============================================================================
- -- Questo programma gestisce automaticamente il reattore IC2 per l'arricchimento
- -- del materiale, con logica di controllo integrata che sostituisce i gate hardware.
- --
- -- LOGICA GATE INTEGRATA (non servono più gate fisici):
- -- - RS Latch: Gestisce la commutazione tra modalità normale e rifornimento
- -- con isteresi per evitare oscillazioni (soglie: 10s per Set, 15s per Reset)
- -- - XNOR: Garantisce che arancione e bianco non siano mai attivi contemporaneamente
- --
- -- COLORI BUNDLED REDSTONE:
- -- - Arancione (2): Modalità normale - Input/output materiale da arricchire ATTIVI
- -- - Bianco (1): Modalità rifornimento - Input/output cellule uranio ATTIVI
- -- - Nessuno (0): Sistema fermo/errore
- -- ============================================================================
- -- Funzione per verificare che il peripheral sia valido
- function getPeripheral()
- local success, s = pcall(function()
- return peripheral.wrap("bottom")
- end)
- if not success or not s then
- return nil, "Peripheral non disponibile"
- end
- return s, nil
- end
- -- Funzione per ottenere il monitor (prova più lati)
- function getMonitor()
- local sides = {"top", "left", "right", "front", "back"}
- for _, side in ipairs(sides) do
- local success, monitor = pcall(function()
- local m = peripheral.wrap(side)
- if m and m.setCursorPos then
- return m, side
- end
- return nil, nil
- end)
- if success and monitor then
- return monitor, side, nil
- end
- end
- return nil, nil, "Monitor non trovato"
- end
- -- Funzione per aggiornare il monitor con i dati del reattore
- function updateMonitor(monitor, uuid, state, title, tab, isRefueling, errorMsg)
- if not monitor then
- return false
- end
- local success, err = pcall(function()
- -- Ottieni dimensioni del monitor
- local width, height = monitor.getSize()
- if not width or not height then
- -- Fallback se getSize non disponibile
- width, height = 26, 9
- end
- -- Configura il monitor
- monitor.setTextScale(0.5) -- Testo più piccolo per monitor 2x3
- monitor.clear()
- monitor.setCursorPos(1, 1)
- -- Header
- monitor.setTextColor(colors.white)
- local header = "=== REATTORE IC2 ==="
- if string.len(header) > width then
- header = string.sub(header, 1, width)
- end
- monitor.write(header)
- monitor.setCursorPos(1, 2)
- monitor.setTextColor(colors.gray)
- monitor.write(string.rep("=", width))
- local line = 3
- -- Mostra errori se presenti
- if errorMsg then
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.red)
- monitor.write("ERRORE:")
- line = line + 1
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.orange)
- -- Tronca messaggio se troppo lungo
- local msg = string.sub(tostring(errorMsg), 1, width - 1)
- monitor.write(msg)
- line = line + 2
- elseif tab and tab.timeLeft then
- -- Stato del reattore
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.cyan)
- monitor.write("Stato: ")
- if isRefueling then
- monitor.setTextColor(colors.yellow)
- monitor.write("RIFORNIMENTO")
- else
- monitor.setTextColor(colors.green)
- monitor.write("ATTIVO")
- end
- line = line + 1
- -- Tempo rimanente
- local hours = math.floor(tab.timeLeft / 3600)
- local minutes = math.floor((tab.timeLeft % 3600) / 60)
- local seconds = tab.timeLeft % 60
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.lightBlue)
- monitor.write("Tempo:")
- line = line + 1
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.white)
- local timeStr
- if hours > 0 then
- timeStr = string.format("%02d:%02d:%02d", hours, minutes, seconds)
- else
- timeStr = string.format("%02d:%02d", minutes, seconds)
- end
- monitor.write(timeStr)
- line = line + 1
- -- Barra di avanzamento (adattata alla larghezza)
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.gray)
- monitor.write("[")
- local barWidth = math.min(width - 4, 18) -- Lascia spazio per [ e ]
- local timePercent = math.min(tab.timeLeft / 3600, 1) * 100 -- Percentuale basata su 1 ora
- local filled = math.floor((timePercent / 100) * barWidth)
- if timePercent > 50 then
- monitor.setTextColor(colors.green)
- elseif timePercent > 20 then
- monitor.setTextColor(colors.yellow)
- else
- monitor.setTextColor(colors.red)
- end
- for i = 1, barWidth do
- if i <= filled then
- monitor.write("=")
- else
- monitor.setTextColor(colors.gray)
- monitor.write("-")
- end
- end
- monitor.setTextColor(colors.gray)
- monitor.write("]")
- line = line + 1
- -- Avviso se tempo basso
- if tab.timeLeft < 60 and not isRefueling then
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.red)
- monitor.write("! ATTENZIONE !")
- if line < height - 1 then
- line = line + 1
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.orange)
- local warning = "Uranio in esaurimento"
- if string.len(warning) > width then
- warning = string.sub(warning, 1, width)
- end
- monitor.write(warning)
- end
- end
- else
- -- Nessun dato disponibile
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.orange)
- monitor.write("Dati non disponibili")
- end
- -- Footer
- if line < height then
- monitor.setCursorPos(1, height)
- monitor.setTextColor(colors.gray)
- monitor.write(string.rep("=", width))
- end
- return true
- end)
- if not success then
- return false
- end
- return true
- end
- -- Funzione per ottenere lo stato del reattore in modo sicuro
- function getReactorState(s)
- if not s then
- return nil, nil, nil, nil, "Peripheral non valido"
- end
- local success, uuid, state, title, tab = pcall(function()
- return s.get(1)
- end)
- if not success then
- return nil, nil, nil, nil, "Errore nella lettura del reattore: " .. tostring(uuid)
- end
- if not tab or type(tab) ~= "table" then
- return uuid, state, title, nil, "Dati reattore non validi"
- end
- if tab.timeLeft == nil or type(tab.timeLeft) ~= "number" then
- return uuid, state, title, tab, "timeLeft non valido"
- end
- return uuid, state, title, tab, nil
- end
- -- Costanti per la logica RS Latch con isteresi (sostituisce i gate hardware)
- local REFUEL_THRESHOLD_LOW = 10 -- Soglia per attivare rifornimento (Set)
- local REFUEL_THRESHOLD_HIGH = 15 -- Soglia per disattivare rifornimento (Reset) - isteresi
- -- Costanti per i colori bundled redstone
- local COLOR_ORANGE = 2 -- Arancione: modalità normale (input/output materiale da arricchire)
- local COLOR_WHITE = 1 -- Bianco: modalità rifornimento (input/output cellule uranio)
- local COLOR_NONE = 0 -- Nessun colore: sistema fermo
- -- Funzione che implementa la logica RS Latch integrata
- -- Gestisce la commutazione tra arancione (normale) e bianco (rifornimento) con isteresi
- -- Sostituisce il gate RS Latch hardware
- function updateReactorMode(timeLeft, currentMode)
- -- currentMode può essere: "normal" (arancione), "refuel" (bianco), o nil (inizializzazione)
- if not timeLeft or timeLeft < 0 then
- return COLOR_NONE, "error" -- Errore: dati non validi
- end
- -- Logica RS Latch con isteresi:
- -- - Set (rifornimento): quando timeLeft < REFUEL_THRESHOLD_LOW
- -- - Reset (normale): quando timeLeft >= REFUEL_THRESHOLD_HIGH
- -- - Isteresi: tra LOW e HIGH mantiene lo stato corrente (evita oscillazioni)
- if timeLeft < REFUEL_THRESHOLD_LOW then
- -- Set: attiva modalità rifornimento (bianco)
- return COLOR_WHITE, "refuel"
- elseif timeLeft >= REFUEL_THRESHOLD_HIGH then
- -- Reset: attiva modalità normale (arancione)
- return COLOR_ORANGE, "normal"
- else
- -- Zona di isteresi (tra LOW e HIGH): mantieni lo stato corrente
- if currentMode == "refuel" then
- return COLOR_WHITE, "refuel"
- else
- -- Se non c'è uno stato corrente, usa il valore più vicino alla soglia
- -- Se siamo appena scesi sotto HIGH, rimani in normale
- -- Se siamo appena saliti sopra LOW, vai in rifornimento
- -- Per sicurezza, se non c'è stato, considera normale
- return COLOR_ORANGE, "normal"
- end
- end
- end
- -- Funzione che implementa la logica XNOR integrata
- -- Garantisce che arancione e bianco non siano mai attivi contemporaneamente
- -- (già gestito automaticamente da setBundledOutput, ma questa funzione verifica la logica)
- function validateOutput(outputValue)
- -- Verifica che l'output sia valido (solo arancione, bianco o nessuno)
- if outputValue == COLOR_ORANGE or outputValue == COLOR_WHITE or outputValue == COLOR_NONE then
- return true, outputValue
- else
- -- Output non valido: spegni tutto per sicurezza
- return false, COLOR_NONE
- end
- end
- -- Funzione di compatibilità per bundled redstone (ComputerCraft 1.5 vs versioni più recenti)
- local function setBundledOutputCompat(side, color)
- -- Prova prima con rs (versioni recenti)
- if rs and rs.setBundledOutput then
- return rs.setBundledOutput(side, color)
- -- Fallback a redstone (ComputerCraft 1.5 per Minecraft 1.4.7)
- elseif redstone and redstone.setBundledOutput then
- return redstone.setBundledOutput(side, color)
- else
- error("API bundled redstone non disponibile")
- end
- end
- -- Funzione per impostare output redstone in modo sicuro con logica gate integrata
- function setOutputSafely(outputValue, errorMsg)
- -- Valida l'output (logica XNOR: solo un colore alla volta)
- local isValid, safeValue = validateOutput(outputValue)
- if not isValid then
- print("ATTENZIONE: Output non valido, uso valore sicuro")
- outputValue = safeValue
- end
- local success, err = pcall(function()
- setBundledOutputCompat("back", outputValue)
- end)
- if not success then
- print("ERRORE: Impossibile impostare output redstone: " .. tostring(err))
- if errorMsg then
- print(errorMsg)
- end
- return false
- end
- return true
- end
- function clear()
- term.clear()
- term.setCursorPos(1, 1)
- end
- clear()
- -- Rilevamento versione ComputerCraft e API disponibile
- local ccVersion = "sconosciuta"
- local bundledAPI = "nessuna"
- if rs and rs.setBundledOutput then
- bundledAPI = "rs.setBundledOutput (ComputerCraft recente)"
- ccVersion = "recente"
- elseif redstone and redstone.setBundledOutput then
- bundledAPI = "redstone.setBundledOutput (ComputerCraft 1.5 - MC 1.4.7)"
- ccVersion = "1.5"
- else
- bundledAPI = "NON DISPONIBILE"
- print("ATTENZIONE: API bundled redstone non trovata!")
- print("Il programma potrebbe non funzionare correttamente")
- end
- print("Versione ComputerCraft rilevata: " .. ccVersion)
- print("API bundled redstone: " .. bundledAPI)
- print("")
- -- Inizializzazione sicura
- local s, err = getPeripheral()
- if not s then
- print("ERRORE CRITICO: " .. err)
- print("Premere un tasto per riprovare...")
- os.pullEvent("key")
- os.reboot()
- end
- -- Inizializzazione monitor
- local monitor, monitorSide, monitorErr = getMonitor()
- if monitor then
- print("Monitor trovato sul lato: " .. monitorSide)
- else
- print("ATTENZIONE: " .. (monitorErr or "Monitor non trovato"))
- print("Il programma continuera' senza monitor")
- end
- -- Lettura iniziale dello stato
- local uuid, state, title, tab, err = getReactorState(s)
- if err then
- print("ERRORE: " .. err)
- print("Verificare la connessione del reattore")
- if monitor then
- updateMonitor(monitor, nil, nil, nil, nil, false, err)
- end
- print("Premere un tasto per continuare...")
- os.pullEvent("key")
- end
- if tab and tab.timeLeft == 0 then
- print("Caricare il reattore e premere un tasto")
- if monitor then
- updateMonitor(monitor, uuid, state, title, tab, false, "Reattore vuoto - caricare uranio")
- end
- os.pullEvent("key")
- clear()
- end
- print("Pronto")
- print("Sistema di sicurezza attivo")
- print("Logica gate integrata (XNOR + RS Latch) attiva")
- -- Variabili per il controllo di sicurezza e logica gate integrata
- local lastTimeLeft = nil
- local consecutiveErrors = 0
- local maxErrors = 5
- local currentReactorMode = nil -- "normal", "refuel", o nil (inizializzazione)
- local lastOutputValue = COLOR_NONE -- Traccia l'ultimo output per evitare cambi inutili
- -- Inizializzazione stato iniziale basato sul timeLeft corrente
- if tab and tab.timeLeft then
- local initOutput, initMode = updateReactorMode(tab.timeLeft, nil)
- currentReactorMode = initMode
- lastOutputValue = initOutput
- -- Imposta l'output iniziale
- if initMode == "normal" then
- setOutputSafely(COLOR_ORANGE, "Impossibile impostare modalità iniziale normale")
- print("Stato iniziale: MODALITA' NORMALE (arancione)")
- elseif initMode == "refuel" then
- setOutputSafely(COLOR_WHITE, "Impossibile impostare modalità iniziale rifornimento")
- print("Stato iniziale: MODALITA' RIFORNIMENTO (bianco)")
- else
- setOutputSafely(COLOR_NONE, "Impossibile impostare stato iniziale")
- print("Stato iniziale: ERRORE")
- end
- else
- -- Se non ci sono dati, inizia in modalità normale
- currentReactorMode = "normal"
- lastOutputValue = COLOR_ORANGE
- setOutputSafely(COLOR_ORANGE, "Impossibile impostare stato iniziale")
- print("Stato iniziale: MODALITA' NORMALE (dati non disponibili)")
- end
- if monitor then
- local isRefueling = (currentReactorMode == "refuel")
- updateMonitor(monitor, uuid, state, title, tab, isRefueling, nil)
- end
- while true do
- clear()
- print("Caricamento automatico materiale da arricchire in funzione")
- -- Verifica periodica della connessione del peripheral
- if consecutiveErrors > 3 then
- print("Riconnessione al peripheral...")
- s, err = getPeripheral()
- if not s then
- print("ERRORE: " .. err)
- print("Attesa 5 secondi prima di riprovare...")
- sleep(5)
- consecutiveErrors = 0
- else
- consecutiveErrors = 0
- print("Riconnesso con successo")
- end
- end
- -- Verifica e riconnessione monitor se necessario
- if not monitor or not pcall(function() monitor.getSize() end) then
- monitor, monitorSide, monitorErr = getMonitor()
- if monitor then
- print("Monitor riconnesso sul lato: " .. monitorSide)
- end
- end
- -- Lettura sicura dello stato
- uuid, state, title, tab, err = getReactorState(s)
- if err then
- consecutiveErrors = consecutiveErrors + 1
- print("ERRORE: " .. err)
- print("Tentativo " .. consecutiveErrors .. "/" .. maxErrors)
- -- Aggiorna monitor con errore (mantieni lo stato corrente)
- if monitor then
- local isRefuelingMonitor = (currentReactorMode == "refuel")
- updateMonitor(monitor, uuid, state, title, tab, isRefuelingMonitor, err)
- end
- if consecutiveErrors >= maxErrors then
- print("ERRORE CRITICO: Troppi errori consecutivi")
- print("Arresto sistema per sicurezza")
- -- In caso di errore critico, spegni tutto (COLOR_NONE)
- setOutputSafely(COLOR_NONE, "Sistema fermato per sicurezza")
- currentReactorMode = "error"
- lastOutputValue = COLOR_NONE
- if monitor then
- updateMonitor(monitor, uuid, state, title, tab, false, "SISTEMA FERMATO - Troppi errori")
- end
- print("Premere un tasto per riprovare...")
- os.pullEvent("key")
- consecutiveErrors = 0
- -- Ripristina lo stato iniziale dopo l'errore
- currentReactorMode = nil
- else
- sleep(2)
- end
- else
- consecutiveErrors = 0
- -- Validazione dei dati
- if tab and tab.timeLeft then
- -- Verifica coerenza dei dati (timeLeft non dovrebbe aumentare)
- if lastTimeLeft ~= nil and tab.timeLeft > lastTimeLeft + 5 then
- print("ATTENZIONE: Rilevato incremento anomalo del tempo")
- print("Possibile errore di lettura, attesa...")
- sleep(3)
- else
- lastTimeLeft = tab.timeLeft
- end
- local hours = math.floor(tab.timeLeft / 3600)
- local minutes = math.floor((tab.timeLeft % 3600) / 60)
- local seconds = tab.timeLeft % 60
- print("Tempo rimanente: " .. hours .. " ore, " .. minutes .. " minuti, " .. seconds .. " secondi")
- -- LOGICA GATE INTEGRATA (sostituisce XNOR e RS Latch hardware)
- -- Determina la modalità del reattore basandosi sul timeLeft
- local outputValue, newMode = updateReactorMode(tab.timeLeft, currentReactorMode)
- -- Aggiorna lo stato solo se è cambiato
- if newMode ~= currentReactorMode then
- local oldMode = currentReactorMode
- currentReactorMode = newMode
- if newMode == "refuel" then
- clear()
- print("ATTENZIONE: Uranio in esaurimento")
- print("Modalità RIFORNIMENTO attivata (bianco)")
- print("Input/output materiale da arricchire: DISATTIVATI")
- print("Input/output cellule uranio: ATTIVI")
- elseif newMode == "normal" then
- if oldMode == "refuel" then
- print("Rifornimento completato")
- end
- print("Modalità NORMALE attivata (arancione)")
- print("Input/output materiale da arricchire: ATTIVI")
- print("Input/output cellule uranio: DISATTIVATI")
- end
- end
- -- Imposta l'output solo se è cambiato (ottimizzazione)
- if outputValue ~= lastOutputValue then
- local modeName = "normale"
- if newMode == "refuel" then
- modeName = "rifornimento"
- elseif newMode == "error" then
- modeName = "errore"
- end
- setOutputSafely(outputValue, "Impossibile impostare modalità " .. modeName)
- lastOutputValue = outputValue
- if outputValue == COLOR_ORANGE then
- print("Output: ARANCIONE (normale)")
- elseif outputValue == COLOR_WHITE then
- print("Output: BIANCO (rifornimento)")
- elseif outputValue == COLOR_NONE then
- print("Output: SPENTO (errore)")
- end
- end
- -- Aggiorna monitor con dati attuali
- local isRefueling = (newMode == "refuel")
- if monitor then
- updateMonitor(monitor, uuid, state, title, tab, isRefueling, nil)
- end
- else
- print("ERRORE: Dati reattore non validi")
- consecutiveErrors = consecutiveErrors + 1
- end
- end
- sleep(1)
- end
Advertisement
Add Comment
Please, Sign In to add comment