Advertisement
Koridev

rd

Mar 27th, 2025 (edited)
266
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.16 KB | None | 0 0
  1. -- dashboard.lua
  2. -- Zentraler "Server", holt Daten von allen Reactor-Clients per rednet,
  3. -- zeigt sie grafisch an und steuert per "KI" die Rod-Level, um
  4. -- möglichst hohen Output bei minimalem Verbrauch zu erzielen.
  5.  
  6. ---------------------------------------------
  7. -- 1) KONFIG
  8. ---------------------------------------------
  9. local monSide   = "top"  -- dein Monitor
  10. local modemSide = "bottom"    -- Wo dein Modem (Wireless/Wired)
  11. local batterySide = nil    -- Falls du zusätzlich eine Battery am Dashboard hast? (optional)
  12. local refreshInterval = 5  -- alle X Sekunden aktualisieren
  13.  
  14. -- Reaktorliste: "id" = Computer-ID, "name" = Anzeige, "auto" = KI an/aus
  15. local reactors = {
  16.   {
  17.     id = 9,               -- ID deines Reaktor-Computers
  18.     name = "Reactor 1",
  19.     auto = true,
  20.     rodLevel = 0,  
  21.     lastRF   = 0,
  22.     fuelPct  = 0,
  23.     temp     = 0
  24.   },
  25.   {
  26.     id = 6,
  27.     name = "Reactor 2",
  28.     auto = false,
  29.     rodLevel = 0,
  30.     lastRF   = 0,
  31.     fuelPct  = 0,
  32.     temp     = 0
  33.   },
  34.   -- bel. mehr ...
  35. }
  36.  
  37. ---------------------------------------------
  38. -- 2) PERIPHERIE
  39. ---------------------------------------------
  40. local mon = peripheral.wrap(monSide)
  41. if not mon then error("Monitor an '"..monSide.."' nicht gefunden!") end
  42. mon.setTextScale(0.5)
  43. local w,h = mon.getSize()
  44.  
  45. local modem = peripheral.wrap(modemSide)
  46. if not modem then error("Modem an '"..modemSide.."' nicht gefunden!") end
  47. rednet.open(modemSide)
  48.  
  49. -- Falls du eine separate Battery an diesem Computer hast:
  50. local battery = nil
  51. if batterySide then
  52.   battery = peripheral.wrap(batterySide)
  53. end
  54.  
  55. ---------------------------------------------
  56. -- 3) GLOBALE VARIABLEN
  57. ---------------------------------------------
  58. local currentScreen = "main"
  59. local currentDetail = 1   -- Index in 'reactors'
  60. local batteryPercent = 0
  61. -- Um Fuel/Effizienz zu optimieren, speichern wir (pro Reaktor) "bestRodLevel" etc.
  62. -- Hier kann man später "KI" historical data anlegen.
  63.  
  64. ---------------------------------------------
  65. -- 4) HILFSMETHODEN
  66. ---------------------------------------------
  67. local function clear()
  68.   mon.setBackgroundColor(colors.black)
  69.   mon.clear()
  70.   mon.setCursorPos(1,1)
  71. end
  72.  
  73. local function centerText(y,text,col)
  74.   col = col or colors.white
  75.   mon.setTextColor(col)
  76.   local x = math.floor((w-#text)/2)
  77.   mon.setCursorPos(x+1,y)
  78.   mon.write(text)
  79. end
  80.  
  81. -- Reaktordaten abholen
  82. local function getReactorData(clientID)
  83.   rednet.send(clientID, {cmd="GET_DATA"}, "REACTOR_PROTO")
  84.   local sender, resp = rednet.receive("REACTOR_PROTO", 3)
  85.   if sender == clientID and type(resp)=="table" then
  86.     return resp
  87.   end
  88.   return nil
  89. end
  90.  
  91. local function setReactorActive(clientID, active)
  92.   rednet.send(clientID, {cmd="SET_ACTIVE", active=active}, "REACTOR_PROTO")
  93.   -- Wir ignorieren die Antwort hier, du könntest sie abwarten.
  94. end
  95.  
  96. local function setReactorRodLevel(clientID, level)
  97.   rednet.send(clientID, {cmd="SET_ROD_LEVEL", level=level}, "REACTOR_PROTO")
  98. end
  99.  
  100. -- Optionaler Batteriestand, falls du eine am Dashboard hast
  101. local function getBatteryPercent()
  102.   if not battery then return 100 end
  103.   local stored = battery.getEnergyStored()
  104.   local cap    = battery.getMaxEnergyStored()
  105.   if cap<=0 then return 100 end
  106.   return math.floor((stored/cap)*100)
  107. end
  108.  
  109. ---------------------------------------------
  110. -- 5) KI-LOGIK (erweitert)
  111. ---------------------------------------------
  112. -- Idee: Wir wollen "maximale" Leistung - ABER minimalen Fuel-Verbrauch.
  113. -- - Wenn Reaktor "auto" = true, wir machen Feintuning:
  114. --   1) Wenn Battery < 50% => Reaktor an, rods senken (0% => max Output).
  115. --   2) Wenn Battery > 95% => Reaktor aus (Rod 100% => minimal Verbrauch).
  116. --   3) Wenn Reaktor an, wir gucken "fuelConsumed" vs "energyProduced" => Effizienz
  117. --   4) Kleines "Delta-Testing": wir probieren rod +5, checken ob Battery stable.
  118. --      Wenn stable => Beibehalten, so sparst du Fuel.
  119. --      Wenn Battery sinkt => rod -5.
  120.  
  121. -- Wir brauchen also "alt-Batterie" + "alt-Fuel" => statische Ansätze
  122. local oldBattery = 100
  123.  
  124. local function autoLogic()
  125.   batteryPercent = getBatteryPercent()
  126.   local deltaB = batteryPercent - oldBattery
  127.   oldBattery = batteryPercent
  128.  
  129.   for _, r in ipairs(reactors) do
  130.     if r.auto then
  131.       -- Not-Aus? Battery < 50 => Reaktor an, rods => 0 (mehr Power)
  132.       if batteryPercent < 50 then
  133.         setReactorActive(r.id, true)
  134.         r.isOnline = true
  135.         local newRod = 0
  136.         setReactorRodLevel(r.id, newRod)
  137.         r.rodLevel = newRod
  138.       end
  139.  
  140.       -- Battery > 95 => Reaktor aus
  141.       if batteryPercent > 95 then
  142.         setReactorActive(r.id, false)
  143.         r.isOnline = false
  144.       end
  145.  
  146.       -- Feinsteuerung, wenn Reaktor online
  147.       if r.isOnline then
  148.         -- Haben wir "energyProduced" und "fuelConsumed"? -> in r eingetragen
  149.         if r.energyProduced and r.fuelConsumed then
  150.           -- "Effizienz" = energyProduced / fuelConsumed (units ???)
  151.           -- Pseudocode:
  152.           -- Falls battery stable (deltaB ~ 0) => rods + 1 => test
  153.           -- Falls battery sinkt => rods - 2 ...
  154.           if math.abs(deltaB) < 1 then
  155.             -- annähern
  156.             local newRod = math.min(100, r.rodLevel + 1)
  157.             setReactorRodLevel(r.id, newRod)
  158.             r.rodLevel = newRod
  159.           elseif deltaB < 0 then
  160.             -- wir verlieren Energie => rods -1
  161.             local newRod = math.max(0, r.rodLevel - 1)
  162.             setReactorRodLevel(r.id, newRod)
  163.             r.rodLevel = newRod
  164.           elseif deltaB > 3 then
  165.             -- wir laden stark => rods +1
  166.             local newRod = math.min(100, r.rodLevel + 1)
  167.             setReactorRodLevel(r.id, newRod)
  168.             r.rodLevel = newRod
  169.           end
  170.         end
  171.       end
  172.     end
  173.   end
  174. end
  175.  
  176. ---------------------------------------------
  177. -- 6) GRAFIK: HAUPTMENÜ
  178. ---------------------------------------------
  179. local function drawMain()
  180.   clear()
  181.   centerText(1, "Multi Reactor Dashboard", colors.cyan)
  182.   mon.setTextColor(colors.white)
  183.   mon.setCursorPos(2,2)
  184.   mon.write("Battery: "..batteryPercent.."%")
  185.  
  186.   local colCount=2
  187.   local boxW, boxH=24,5
  188.   local startY=3
  189.   local i=1
  190.   for row=0,10 do
  191.     for col=0,colCount-1 do
  192.       local rr = reactors[i]
  193.       if not rr then return end
  194.  
  195.       local x=col*(boxW+1)+2
  196.       local y=row*(boxH+1)+startY
  197.  
  198.       -- Box
  199.       mon.setTextColor(colors.white)
  200.       mon.setCursorPos(x,y)
  201.       mon.write("+"..string.rep("-",boxW-2).."+")
  202.       for rrow=1, boxH-2 do
  203.         mon.setCursorPos(x, y+rrow)
  204.         mon.write("|"..string.rep(" ", boxW-2).."|")
  205.       end
  206.       mon.setCursorPos(x, y+boxH-1)
  207.       mon.write("+"..string.rep("-",boxW-2).."+")
  208.  
  209.       -- Name
  210.       mon.setCursorPos(x+2,y+1)
  211.       mon.write(rr.name)
  212.  
  213.       -- Online
  214.       mon.setCursorPos(x+2,y+2)
  215.       if rr.isOnline then
  216.         mon.setTextColor(colors.lime)
  217.         mon.write("Online")
  218.       else
  219.         mon.setTextColor(colors.red)
  220.         mon.write("Offline")
  221.       end
  222.  
  223.       -- Auto
  224.       mon.setCursorPos(x+2,y+3)
  225.       mon.setTextColor(rr.auto and colors.lime or colors.gray)
  226.       mon.write("[Auto:"..tostring(rr.auto).."]")
  227.  
  228.       i=i+1
  229.       if i>#reactors then return end
  230.     end
  231.   end
  232. end
  233.  
  234. ---------------------------------------------
  235. -- 7) GRAFIK: DETAIL
  236. ---------------------------------------------
  237. local function drawDetail(idx)
  238.   local r = reactors[idx]
  239.   if not r then return end
  240.  
  241.   clear()
  242.   centerText(1, r.name.." Detail", colors.cyan)
  243.  
  244.   mon.setCursorPos(2,3)
  245.   mon.setTextColor(r.isOnline and colors.lime or colors.red)
  246.   mon.write("Status: "..(r.isOnline and "Online" or "Offline"))
  247.  
  248.   -- Fuel %
  249.   local fPct = 0
  250.   if (r.fuelAmountMax or 0)>0 then
  251.     fPct = math.floor(r.fuelAmount / r.fuelAmountMax *100)
  252.   end
  253.  
  254.   mon.setCursorPos(2,4)
  255.   mon.setTextColor(colors.white)
  256.   mon.write(("Fuel: %d%%"):format(fPct))
  257.  
  258.   mon.setCursorPos(2,5)
  259.   mon.write(("Rod: %d%%"):format(r.rodLevel or 0))
  260.  
  261.   mon.setCursorPos(2,6)
  262.   mon.write(("RF/t: %.1f"):format(r.energyProduced or 0))
  263.  
  264.   mon.setCursorPos(2,7)
  265.   mon.write(("FuelC/t: %.4f"):format(r.fuelConsumed or 0))
  266.  
  267.   mon.setCursorPos(2,8)
  268.   mon.write(("Temp: %.1fC (Casing: %.1fC)"):format(r.fuelTemp or 0, r.casingTemp or 0))
  269.  
  270.   mon.setCursorPos(2,9)
  271.   mon.write(("Reactivity: %.1f%%"):format(r.reactivity or 0))
  272.  
  273.   mon.setCursorPos(2,11)
  274.   mon.setTextColor(colors.gray)
  275.   mon.write("[ Toggle ON/OFF ]")
  276.   mon.setCursorPos(2,12)
  277.   mon.write("[Auto Mode: "..(r.auto and "On" or "Off").."]")
  278.  
  279.   mon.setCursorPos(2,h)
  280.   mon.setTextColor(colors.yellow)
  281.   mon.write("[ Zurueck ]")
  282. end
  283.  
  284. ---------------------------------------------
  285. -- 8) TOUCH-HANDLER
  286. ---------------------------------------------
  287. local function clickMain(x,y)
  288.   local colCount=2
  289.   local boxW,boxH=24,5
  290.   local startY=3
  291.   local i=1
  292.   for row=0,10 do
  293.     for col=0,colCount-1 do
  294.       local rx = col*(boxW+1)+2
  295.       local ry = row*(boxH+1)+startY
  296.       if x>=rx and x<=rx+boxW-1 and y>=ry and y<=ry+boxH-1 then
  297.         if reactors[i] then
  298.           currentDetail=i
  299.           currentScreen="detail"
  300.           drawDetail(i)
  301.         end
  302.         return
  303.       end
  304.       i=i+1
  305.       if i>#reactors then return end
  306.     end
  307.   end
  308. end
  309.  
  310. local function clickDetail(x,y)
  311.   local r = reactors[currentDetail]
  312.   if not r then return end
  313.  
  314.   if y==h then
  315.     -- [Zurueck]
  316.     currentScreen="main"
  317.     drawMain()
  318.     return
  319.   end
  320.  
  321.   if x>=2 and x<=17 and y==11 then
  322.     -- Toggle On/Off
  323.     local newState = not r.isOnline
  324.     setReactorActive(r.id, newState)
  325.     r.isOnline = newState
  326.     drawDetail(currentDetail)
  327.     return
  328.   end
  329.   if x>=2 and x<=17 and y==12 then
  330.     r.auto=not r.auto
  331.     drawDetail(currentDetail)
  332.     return
  333.   end
  334. end
  335.  
  336. ---------------------------------------------
  337. -- 9) UPDATE-LOOP
  338. ---------------------------------------------
  339. local function updateAll()
  340.   -- Batteriestand
  341.   batteryPercent = getBatteryPercent()
  342.  
  343.   -- Hol Daten vom Client
  344.   for _,rx in ipairs(reactors) do
  345.     local data = getReactorData(rx.id)
  346.     if data then
  347.       rx.isOnline        = data.active
  348.       rx.energyProduced  = data.energyProduced or 0
  349.       rx.fuelAmount      = data.fuelAmount or 0
  350.       rx.fuelAmountMax   = data.fuelAmountMax or 1
  351.       rx.fuelConsumed    = data.fuelConsumed or 0
  352.       rx.reactivity      = data.reactivity or 0
  353.       rx.fuelTemp        = data.fuelTemp or 0
  354.       rx.casingTemp      = data.casingTemp or 0
  355.       rx.rodLevel        = data.rodLevel or 0
  356.       rx.energyStored    = data.energyStored or 0
  357.       rx.energyCapacity  = data.energyCapacity or 1
  358.     else
  359.       rx.isOnline = false
  360.     end
  361.   end
  362.  
  363.   -- KI
  364.   autoLogic()
  365. end
  366.  
  367. local function mainLoop()
  368.   updateAll()
  369.   drawMain()
  370.  
  371.   local timerID = os.startTimer(refreshInterval)
  372.   while true do
  373.     local e, p1, p2, p3 = os.pullEvent()
  374.     if e=="timer" and p1==timerID then
  375.       updateAll()
  376.       if currentScreen=="main" then
  377.         drawMain()
  378.       else
  379.         drawDetail(currentDetail)
  380.       end
  381.       timerID = os.startTimer(refreshInterval)
  382.  
  383.     elseif e=="monitor_touch" then
  384.       local x,y = p2,p3
  385.       if currentScreen=="main" then
  386.         clickMain(x,y)
  387.       else
  388.         clickDetail(x,y)
  389.       end
  390.     end
  391.   end
  392. end
  393.  
  394. mainLoop()
  395.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement