Advertisement
BombBloke

Reactor Monitor (BigReactors)

Aug 19th, 2014
493
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.05 KB | None | 0 0
  1. -- Reactor Monitor
  2. -- ----------------------------------------------------------
  3.  
  4. -- By Jeffrey Alexander, aka Bomb Bloke.
  5.  
  6. -- Keeps tabs on a BigReactors reactor.
  7. -- Automatically starts it up and shuts it down
  8. -- while graphing stats to an attached monitor.
  9.  
  10. -- ----------------------------------------------------------
  11. -- Initialise important values:
  12. -- ----------------------------------------------------------
  13.  
  14. local dataBuffer, secondsCounter, myEvent, mon, reactor, mfsu, xSize, ySize, myTimer = {}, 100
  15.  
  16. local settings = {["autoControl"] = true}
  17.  
  18. local maxTemp    = 3000  -- Alarm will sound and reactor will shutdown if this temperature is reached. Chosen somewhat at random.
  19. local resumeTemp = 1000  -- After a heat-related shutdown, reactor will reactivate at this temperature.
  20.  
  21. local maxRF = 9000000    -- Reactor will shut down if the internal power storage buffer hits this figure.
  22. local minRF = 1000000    -- Reactor will start up if the internal power storage buffer drops to this figure.
  23.  
  24. local cols = {colours.green,colours.blue,colours.yellow,colours.brown,colours.red}
  25.  
  26. -- ----------------------------------------------------------
  27. -- Functions and stuff:
  28. -- ----------------------------------------------------------
  29.  
  30. -- Returns whether a click was performed at a given location.
  31. -- If one parameter is passed, it checks to see if y is [1].
  32. -- If two parameters are passed, it checks to see if x is [1] and y is [2].
  33. -- If three parameters are passed, it checks to see if x is between [1]/[2] (non-inclusive) and y is [3].
  34. -- If four paramaters are passed, it checks to see if x is between [1]/[2] and y is between [3]/[4] (non-inclusive).
  35. local function clickedAt(...)
  36.     if myEvent[1] ~= "monitor_touch" or myEvent[2] ~= mon.side then return false end
  37.     if #arg == 1 then return (arg[1] == myEvent[4])
  38.     elseif #arg == 2 then return (myEvent[3] == arg[1] and myEvent[4] == arg[2])
  39.     elseif #arg == 3 then return (myEvent[3] > arg[1] and myEvent[3] < arg[2] and myEvent[4] == arg[3])
  40.     else return (myEvent[3] > arg[1] and myEvent[3] < arg[2] and myEvent[4] > arg[3] and myEvent[4] < arg[4]) end
  41. end
  42.  
  43. local function drawTrimmings()
  44.     mon.setTextColour(colours.black)
  45.     mon.setBackgroundColour(colours.blue)
  46.     mon.clear()
  47.    
  48.     mon.setCursorPos(2,1)
  49.     mon.setBackgroundColour(colours.grey)
  50.     mon.clearLine()
  51.     mon.setBackgroundColour(colours.lightGrey)
  52.     mon.write("Reactor Report")
  53.    
  54.     mon.setCursorPos(2,ySize)
  55.     mon.setBackgroundColour(colours.grey)
  56.     mon.clearLine()
  57.     mon.setBackgroundColour(colours.lightGrey)
  58.     mon.write("Reactor Status:")
  59.    
  60.     mon.setTextColour(colours.white)
  61.     mon.setBackgroundColour(colours.grey)
  62.    
  63.     local temp, temp2 = 0, 0
  64.    
  65.     for i=0,xSize-4 do
  66.         if bit.band(i,3) == 0 then
  67.             mon.setCursorPos(xSize-i-3,ySize-2)
  68.             mon.write(tostring(temp2))
  69.             mon.setCursorPos(xSize-i-3,ySize-1)
  70.             mon.write(tostring(temp))
  71.         end
  72.        
  73.         temp = temp + 1
  74.        
  75.         if temp > 9 then
  76.             temp = 0
  77.             temp2 = temp2 + 1
  78.         end
  79.     end
  80.    
  81.     for i=0,ySize-4 do if bit.band(i,1) == 0 then
  82.         temp = tostring(math.floor((i+0.5)/(ySize-4)*100)).."%"
  83.         mon.setCursorPos(xSize-#temp+1,ySize-3-i)
  84.         mon.write(temp)
  85.     end end
  86.    
  87.     mon.setCursorPos(xSize-2,2)
  88.     mon.write("100")
  89. end
  90.  
  91. local function drawGraph()
  92.     mon.setBackgroundColour(colours.black)
  93.     for i=2,ySize-3 do
  94.         mon.setCursorPos(1,i)
  95.         mon.write(string.rep(" ",xSize-3))
  96.     end
  97.    
  98.     local vals1, vals2, maxFuel, maxEU
  99.     repeat maxFuel = reactor.getFuelAmountMax() until maxFuel
  100.     if mfsu then repeat maxEU   = mfsu.getEUCapacity() until maxEU end
  101.    
  102.     for i=1,#dataBuffer do
  103.         vals2 = vals1
  104.        
  105.         vals1 = {
  106.         math.floor(dataBuffer[i].energyStored / 10000000 * (ySize - 4) + 0.5),
  107.         math.floor(dataBuffer[i].temperature  / 5000     * (ySize - 4) + 0.5),
  108.         math.floor(dataBuffer[i].fuelAmount   / maxFuel  * (ySize - 4) + 0.5),
  109.         math.floor(dataBuffer[i].wasteAmount  / maxFuel  * (ySize - 4) + 0.5),
  110.         mfsu and math.floor(dataBuffer[i].mfsu         / maxEU    * (ySize - 4) + 0.5)}
  111.        
  112.         mon.setBackgroundColour(cols[1])
  113.         for j=1,vals1[1] do
  114.             mon.setCursorPos(xSize-i-2,ySize-j-2)
  115.             mon.write(" ")
  116.         end
  117.  
  118.         if vals2 then for j=2,#vals1 do
  119.             paintutils.drawLine(xSize-i-2,ySize-math.max(vals1[j]+2,3),xSize-i-1,ySize-math.max(vals2[j]+2,3),cols[j])
  120.         end end
  121.     end
  122. end
  123.  
  124. local function drawButtons()
  125.     mon.setCursorPos(xSize - 9,ySize)
  126.     mon.setTextColour(colours.white)
  127.     mon.setBackgroundColour(settings.autoControl and colours.green or colours.red)
  128.     mon.write(settings.autoControl and "  Auto  " or " Manual ")
  129. end
  130.  
  131. -- ----------------------------------------------------------
  132. -- Init:
  133. -- ----------------------------------------------------------
  134.  
  135. do 
  136.     local pers = peripheral.getNames()
  137.  
  138.     for i=1,#pers do if peripheral.getType(pers[i]) == "BigReactors-Reactor" then
  139.         reactor = peripheral.wrap(pers[i])
  140.         reactor.getFuelTemperature = reactor.getFuelTemperature or reactor.getTemperature
  141.     elseif peripheral.getType(pers[i]) == "monitor" then
  142.         mon = peripheral.wrap(pers[i])
  143.         mon.side = pers[i]
  144.     elseif peripheral.getType(pers[i]) == "mfsu" then
  145.         mfsu = peripheral.wrap(pers[i])
  146.     end end
  147. end
  148.  
  149. if fs.exists("reactorSettings") then
  150.     local myFile = fs.open("reactorSettings","r")
  151.     settings = textutils.unserialize(myFile.readAll())
  152.     myFile.close()
  153. end
  154.  
  155. mon.setTextScale(.5)
  156. xSize, ySize = mon.getSize()
  157.  
  158. drawTrimmings()
  159. drawButtons()
  160.  
  161. myTimer = os.startTimer(0)
  162.  
  163. if settings.autoControl then reactor.setActive(true) end
  164.  
  165. term.setTextColour(colours.white)
  166. term.setBackgroundColour(colours.black)
  167. term.setCursorPos(1,1)
  168. term.clear()
  169.  
  170. print("Reactor monitor running. Press Q to quit to terminal.\n")
  171. print("While in auto-mode (as opposed to manual; click the indicator on the monitor to toggle), reactor will activate when the internal store drops below "..minRF.."RF, and shut down when it exceeds "..maxRF.."RF.\n")
  172. print("The green bar represents stored energy. Yellow stars indicate the amount of fuel in the reactor, blue indicates temperature levels, whereas brown is waste. Red indicates MFSU storage.\n")
  173. print("Each column on the graph represents one minute of reactor history. Oldest to newest goes from left to right.\n")
  174.  
  175. term.redirect(mon)
  176.  
  177. -- ----------------------------------------------------------
  178. -- Main program loop:
  179. -- ----------------------------------------------------------
  180.  
  181. while true do
  182.     myEvent = {os.pullEvent()}
  183.    
  184.     local temp
  185.    
  186.     -- Update display:
  187.     if myEvent[1] == "timer" and myEvent[2] == myTimer then
  188.         mon.setCursorPos(18,ySize)
  189.         mon.setTextColour(colours.white)
  190.         mon.setBackgroundColour(reactor.getActive() and colours.green or colours.red)
  191.         mon.write(reactor.getActive() and "Online" or "Offline")
  192.        
  193.         mon.setBackgroundColour(colours.grey)
  194.         mon.write(" ")
  195.        
  196.         mon.setCursorPos(26,ySize)
  197.         mon.setTextColour(colours.black)
  198.         mon.setBackgroundColour(colours.lightGrey)
  199.        
  200.         repeat temp = reactor.getEnergyProducedLastTick() until temp
  201.         mon.write(tostring(math.floor(temp)).."RF/tick")
  202.        
  203.         mon.setBackgroundColour(colours.grey)
  204.         local curX, curY = mon.getCursorPos()
  205.         mon.write(string.rep(" ",xSize-curX-10))
  206.        
  207.         secondsCounter = secondsCounter + 1
  208.        
  209.         if secondsCounter > 59 then
  210.             secondsCounter = 0
  211.             table.insert(dataBuffer,1,{})
  212.            
  213.             while not dataBuffer[1].energyStored do dataBuffer[1].energyStored = reactor.getEnergyStored() end
  214.             while not dataBuffer[1].temperature  do dataBuffer[1].temperature  = reactor.getFuelTemperature()  end
  215.             while not dataBuffer[1].fuelAmount   do dataBuffer[1].fuelAmount   = reactor.getFuelAmount()   end
  216.             while not dataBuffer[1].wasteAmount  do dataBuffer[1].wasteAmount  = reactor.getWasteAmount()  end
  217.             if mfsu then while not dataBuffer[1].mfsu         do dataBuffer[1].mfsu         = mfsu.getEUStored()  end end
  218.            
  219.             while #dataBuffer > xSize - 3 do dataBuffer[#dataBuffer] = nil end
  220.            
  221.             drawGraph()
  222.         end
  223.        
  224.         myTimer = os.startTimer(1)
  225.    
  226.     -- Redraw whole display:
  227.     elseif myEvent[1] == "monitor_resize" then
  228.         xSize, ySize = mon.getSize()
  229.         drawTrimmings()
  230.         drawGraph()
  231.         drawButtons()
  232.        
  233.     -- Quit:
  234.     elseif myEvent[1] == "char" and myEvent[2] == "q" then
  235.         reactor.setActive(false)
  236.         term.restore()
  237.         print("Exiting (reactor will be shut down)...\n")
  238.         error()
  239.        
  240.     -- Toggle automatic reactor control:
  241.     elseif clickedAt(xSize-10,xSize-2,ySize) then
  242.         settings.autoControl = not settings.autoControl
  243.         if not settings.autoControl then reactor.setActive(false) end
  244.         drawButtons()
  245.        
  246.         local myFile = fs.open("reactorSettings","w")
  247.         myFile.write(textutils.serialize(settings))
  248.         myFile.close()
  249.        
  250.     end
  251.    
  252.     repeat temp = reactor.getFuelTemperature() until temp
  253.    
  254.     if temp > maxTemp then
  255.         rs.setOutput("bottom",true)
  256.         reactor.setActive(false)
  257.        
  258.         while temp > resumeTemp do
  259.             sleep(10)
  260.             repeat temp = reactor.getFuelTemperature() until temp
  261.         end
  262.        
  263.         rs.setOutput("bottom",false)
  264.     end
  265.    
  266.     if settings.autoControl then
  267.         repeat temp = reactor.getEnergyStored() until temp
  268.        
  269.         if temp > maxRF and reactor.getActive() then
  270.             reactor.setActive(false)
  271.         elseif temp < minRF and not reactor.getActive() then
  272.             reactor.setActive(true)
  273.         end
  274.     end
  275. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement