Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Reactor Monitor
- -- ----------------------------------------------------------
- -- By Jeffrey Alexander, aka Bomb Bloke.
- -- Keeps tabs on a BigReactors reactor.
- -- Automatically starts it up and shuts it down
- -- while graphing stats to an attached monitor.
- -- ----------------------------------------------------------
- -- Initialise important values:
- -- ----------------------------------------------------------
- local dataBuffer, secondsCounter, myEvent, mon, reactor, mfsu, xSize, ySize, myTimer = {}, 100
- local settings = {["autoControl"] = true}
- local maxTemp = 3000 -- Alarm will sound and reactor will shutdown if this temperature is reached. Chosen somewhat at random.
- local resumeTemp = 1000 -- After a heat-related shutdown, reactor will reactivate at this temperature.
- local maxRF = 9000000 -- Reactor will shut down if the internal power storage buffer hits this figure.
- local minRF = 1000000 -- Reactor will start up if the internal power storage buffer drops to this figure.
- local cols = {colours.green,colours.blue,colours.yellow,colours.brown,colours.red}
- -- ----------------------------------------------------------
- -- Functions and stuff:
- -- ----------------------------------------------------------
- -- Returns whether a click was performed at a given location.
- -- If one parameter is passed, it checks to see if y is [1].
- -- If two parameters are passed, it checks to see if x is [1] and y is [2].
- -- If three parameters are passed, it checks to see if x is between [1]/[2] (non-inclusive) and y is [3].
- -- If four paramaters are passed, it checks to see if x is between [1]/[2] and y is between [3]/[4] (non-inclusive).
- local function clickedAt(...)
- if myEvent[1] ~= "monitor_touch" or myEvent[2] ~= mon.side then return false end
- if #arg == 1 then return (arg[1] == myEvent[4])
- elseif #arg == 2 then return (myEvent[3] == arg[1] and myEvent[4] == arg[2])
- elseif #arg == 3 then return (myEvent[3] > arg[1] and myEvent[3] < arg[2] and myEvent[4] == arg[3])
- else return (myEvent[3] > arg[1] and myEvent[3] < arg[2] and myEvent[4] > arg[3] and myEvent[4] < arg[4]) end
- end
- local function drawTrimmings()
- mon.setTextColour(colours.black)
- mon.setBackgroundColour(colours.blue)
- mon.clear()
- mon.setCursorPos(2,1)
- mon.setBackgroundColour(colours.grey)
- mon.clearLine()
- mon.setBackgroundColour(colours.lightGrey)
- mon.write("Reactor Report")
- mon.setCursorPos(2,ySize)
- mon.setBackgroundColour(colours.grey)
- mon.clearLine()
- mon.setBackgroundColour(colours.lightGrey)
- mon.write("Reactor Status:")
- mon.setTextColour(colours.white)
- mon.setBackgroundColour(colours.grey)
- local temp, temp2 = 0, 0
- for i=0,xSize-4 do
- if bit.band(i,3) == 0 then
- mon.setCursorPos(xSize-i-3,ySize-2)
- mon.write(tostring(temp2))
- mon.setCursorPos(xSize-i-3,ySize-1)
- mon.write(tostring(temp))
- end
- temp = temp + 1
- if temp > 9 then
- temp = 0
- temp2 = temp2 + 1
- end
- end
- for i=0,ySize-4 do if bit.band(i,1) == 0 then
- temp = tostring(math.floor((i+0.5)/(ySize-4)*100)).."%"
- mon.setCursorPos(xSize-#temp+1,ySize-3-i)
- mon.write(temp)
- end end
- mon.setCursorPos(xSize-2,2)
- mon.write("100")
- end
- local function drawGraph()
- mon.setBackgroundColour(colours.black)
- for i=2,ySize-3 do
- mon.setCursorPos(1,i)
- mon.write(string.rep(" ",xSize-3))
- end
- local vals1, vals2, maxFuel, maxEU
- repeat maxFuel = reactor.getFuelAmountMax() until maxFuel
- if mfsu then repeat maxEU = mfsu.getEUCapacity() until maxEU end
- for i=1,#dataBuffer do
- vals2 = vals1
- vals1 = {
- math.floor(dataBuffer[i].energyStored / 10000000 * (ySize - 4) + 0.5),
- math.floor(dataBuffer[i].temperature / 5000 * (ySize - 4) + 0.5),
- math.floor(dataBuffer[i].fuelAmount / maxFuel * (ySize - 4) + 0.5),
- math.floor(dataBuffer[i].wasteAmount / maxFuel * (ySize - 4) + 0.5),
- mfsu and math.floor(dataBuffer[i].mfsu / maxEU * (ySize - 4) + 0.5)}
- mon.setBackgroundColour(cols[1])
- for j=1,vals1[1] do
- mon.setCursorPos(xSize-i-2,ySize-j-2)
- mon.write(" ")
- end
- if vals2 then for j=2,#vals1 do
- paintutils.drawLine(xSize-i-2,ySize-math.max(vals1[j]+2,3),xSize-i-1,ySize-math.max(vals2[j]+2,3),cols[j])
- end end
- end
- end
- local function drawButtons()
- mon.setCursorPos(xSize - 9,ySize)
- mon.setTextColour(colours.white)
- mon.setBackgroundColour(settings.autoControl and colours.green or colours.red)
- mon.write(settings.autoControl and " Auto " or " Manual ")
- end
- -- ----------------------------------------------------------
- -- Init:
- -- ----------------------------------------------------------
- do
- local pers = peripheral.getNames()
- for i=1,#pers do if peripheral.getType(pers[i]) == "BigReactors-Reactor" then
- reactor = peripheral.wrap(pers[i])
- reactor.getFuelTemperature = reactor.getFuelTemperature or reactor.getTemperature
- elseif peripheral.getType(pers[i]) == "monitor" then
- mon = peripheral.wrap(pers[i])
- mon.side = pers[i]
- elseif peripheral.getType(pers[i]) == "mfsu" then
- mfsu = peripheral.wrap(pers[i])
- end end
- end
- if fs.exists("reactorSettings") then
- local myFile = fs.open("reactorSettings","r")
- settings = textutils.unserialize(myFile.readAll())
- myFile.close()
- end
- mon.setTextScale(.5)
- xSize, ySize = mon.getSize()
- drawTrimmings()
- drawButtons()
- myTimer = os.startTimer(0)
- if settings.autoControl then reactor.setActive(true) end
- term.setTextColour(colours.white)
- term.setBackgroundColour(colours.black)
- term.setCursorPos(1,1)
- term.clear()
- print("Reactor monitor running. Press Q to quit to terminal.\n")
- 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")
- 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")
- print("Each column on the graph represents one minute of reactor history. Oldest to newest goes from left to right.\n")
- term.redirect(mon)
- -- ----------------------------------------------------------
- -- Main program loop:
- -- ----------------------------------------------------------
- while true do
- myEvent = {os.pullEvent()}
- local temp
- -- Update display:
- if myEvent[1] == "timer" and myEvent[2] == myTimer then
- mon.setCursorPos(18,ySize)
- mon.setTextColour(colours.white)
- mon.setBackgroundColour(reactor.getActive() and colours.green or colours.red)
- mon.write(reactor.getActive() and "Online" or "Offline")
- mon.setBackgroundColour(colours.grey)
- mon.write(" ")
- mon.setCursorPos(26,ySize)
- mon.setTextColour(colours.black)
- mon.setBackgroundColour(colours.lightGrey)
- repeat temp = reactor.getEnergyProducedLastTick() until temp
- mon.write(tostring(math.floor(temp)).."RF/tick")
- mon.setBackgroundColour(colours.grey)
- local curX, curY = mon.getCursorPos()
- mon.write(string.rep(" ",xSize-curX-10))
- secondsCounter = secondsCounter + 1
- if secondsCounter > 59 then
- secondsCounter = 0
- table.insert(dataBuffer,1,{})
- while not dataBuffer[1].energyStored do dataBuffer[1].energyStored = reactor.getEnergyStored() end
- while not dataBuffer[1].temperature do dataBuffer[1].temperature = reactor.getFuelTemperature() end
- while not dataBuffer[1].fuelAmount do dataBuffer[1].fuelAmount = reactor.getFuelAmount() end
- while not dataBuffer[1].wasteAmount do dataBuffer[1].wasteAmount = reactor.getWasteAmount() end
- if mfsu then while not dataBuffer[1].mfsu do dataBuffer[1].mfsu = mfsu.getEUStored() end end
- while #dataBuffer > xSize - 3 do dataBuffer[#dataBuffer] = nil end
- drawGraph()
- end
- myTimer = os.startTimer(1)
- -- Redraw whole display:
- elseif myEvent[1] == "monitor_resize" then
- xSize, ySize = mon.getSize()
- drawTrimmings()
- drawGraph()
- drawButtons()
- -- Quit:
- elseif myEvent[1] == "char" and myEvent[2] == "q" then
- reactor.setActive(false)
- term.restore()
- print("Exiting (reactor will be shut down)...\n")
- error()
- -- Toggle automatic reactor control:
- elseif clickedAt(xSize-10,xSize-2,ySize) then
- settings.autoControl = not settings.autoControl
- if not settings.autoControl then reactor.setActive(false) end
- drawButtons()
- local myFile = fs.open("reactorSettings","w")
- myFile.write(textutils.serialize(settings))
- myFile.close()
- end
- repeat temp = reactor.getFuelTemperature() until temp
- if temp > maxTemp then
- rs.setOutput("bottom",true)
- reactor.setActive(false)
- while temp > resumeTemp do
- sleep(10)
- repeat temp = reactor.getFuelTemperature() until temp
- end
- rs.setOutput("bottom",false)
- end
- if settings.autoControl then
- repeat temp = reactor.getEnergyStored() until temp
- if temp > maxRF and reactor.getActive() then
- reactor.setActive(false)
- elseif temp < minRF and not reactor.getActive() then
- reactor.setActive(true)
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement