Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ----------------------
- -- SafeReactor - a Big Reactors control program [ComputerCraft version]
- -- by Kai Kikuchi
- -- version: 0.23 - (BETA - STILL IN DEVELOP)
- --
- -- Source code: http://pastebin.com/7M3hziBV
- -- Sample screenshot: https://imgur.com/higRKAX
- -- OpenComputers WIP: http://pastebin.com/k40ktpxK
- --
- -- This program manages a Big Reactors reactor (both passive and active)
- -- and turbines, making it very fuel efficient
- --
- -- How to install on ComputerCraft:
- -- - type: pastebin run nPwUtAHc
- -- - press Enter
- ----------------------
- vern=2301
- version="0.23"
- updateTimer=0
- local function checkUpdate()
- print("checking for update...")
- shell.run("pastebin","get","2geNdJma","srver")
- local updverfile = io.open("srver", "r")
- if updverfile then
- local updverfilel=""
- updverfilel=updverfile:read()
- updverfile:close()
- shell.run("rm","srver")
- updverfilel=tonumber(updverfilel)
- print("Current version number is "..vern)
- print("Online version number is "..updverfilel)
- if updverfilel > vern then
- print("new version found... updating!")
- shell.run("pastebin","get","7M3hziBV","srtmp")
- local srtmpf=io.open("srtmp","r")
- if srtmpf~=nil then
- srtmpf:close(srtmpf)
- shell.run("rm", "sr")
- shell.run("rename","srtmp","sr")
- print()
- print("Rebooting...")
- print()
- sleep(3)
- shell.run("reboot")
- error()
- else
- print("Update failed... :(")
- end
- end
- else
- print("Failed to check for update...")
- end
- updateTimer = os.startTimer(100000)
- end
- checkUpdate()
- local function round(num, idp)
- local mult = 10^(idp or 0)
- return math.floor(num * mult + 0.5) / mult
- end
- local function curln(m, x)
- if m then
- curX, curY=m.getCursorPos()
- m.setCursorPos(x, curY+1)
- end
- end
- local function curxm(m, x)
- if m then
- curX, curY=m.getCursorPos()
- m.setCursorPos(x, curY)
- end
- end
- local function rfkrf(rf)
- if rf >= 1000 then
- return round(rf/1000, 2).." kRF"
- else
- return rf.." RF"
- end
- end
- local function periList(peripheralName)
- local periList = peripheral.getNames()
- local j=1
- local result={}
- for i=1, #periList do
- if peripheral.getType(periList[i]) == peripheralName then
- result[j]=periList[i]
- j=j+1
- end
- end
- if j==1 then
- return false
- else
- return result
- end
- end
- activeSignState=false
- local function activeSign()
- if activeSignState then
- activeSignState=false
- return "/"
- else
- activeSignState=true
- return "\\"
- end
- end
- scoreT={}
- scoreTi=1
- local function scoreCalc(energy, fuel, tCore, tCasing)
- if energy>0 and fuel>0 then
- scoreT[scoreTi]=(((energy/20)+(energy/fuel))/18)-(tCore-tCasing)
- if scoreT[scoreTi] < 0 then
- scoreT[scoreTi]=0
- end
- if scoreTi>49 then
- scoreTi=1
- else
- scoreTi=scoreTi+1
- end
- end
- local j=0
- local score=0
- for i=1,50 do
- if scoreT[i] then
- score=score+scoreT[i]
- j=j+1
- end
- end
- if j<40 then
- return "-"
- else
- return round((score/j), 0)
- end
- end
- local function events()
- while true do
- p1 = ""
- p2 = ""
- p1, p2 = os.pullEventRaw()
- if p1=="peripheral" or p1=="peripheral_detach" or (p1=="timer" and p2==updateTimer) then
- print("Rebooting...")
- shell.run("reboot")
- error()
- elseif p1=="monitor_resize" then
- if mSkipEvent then
- mSkipEvent=false
- else
- mWrap.setTextScale(0.5)
- mSizeW, mSizeH = mWrap.getSize()
- if tCount then
- monitorTextScaleMult=math.min(mSizeW/55, mSizeH/(16+(tCount*2)))
- else
- monitorTextScaleMult=math.min(mSizeW/55, mSizeH/24)
- end
- monitorTextScaleMultFloor=math.floor(monitorTextScaleMult)
- if monitorTextScaleMult-monitorTextScaleMultFloor > 0.49 then
- monitorTextScaleMultFloor=monitorTextScaleMultFloor+0.5
- end
- if monitorTextScaleMultFloor < 0.5 then
- monitorTextScaleMultFloor=0.5
- end
- mWrap.setTextScale(monitorTextScaleMultFloor)
- m.reposition(1, 1, mSizeW, mSizeH)
- mSkipEvent=true
- end
- elseif p1=="terminate" then
- --
- error("Terminated")
- end
- end
- end
- -- still in develop
- local function gui()
- if mSide then
- while true do
- m.setCursorPos(1, 1)
- m.write("Lets hope this works... "..activeSign())
- m.setVisible(true)
- m.setVisible(false)
- sleep(2)
- end
- end
- end
- rSide=periList("BigReactors-Reactor")
- if rSide then
- r=peripheral.wrap(rSide[1])
- else
- print("No reactor found. Exiting...")
- error()
- end
- mSide=periList("monitor")
- if mSide then
- mWrap = peripheral.wrap(mSide[1])
- mWrap.setTextScale(0.5)
- mSizeW, mSizeH = mWrap.getSize()
- m=window.create(mWrap, 1, 1, mSizeW, mSizeH, false)
- else
- m=window.create(term.native(), 0,0,0,0, false)
- end
- tSide=periList("BigReactors-Turbine")
- if tSide then
- t={}
- for k,v in ipairs(tSide) do
- t[k]=peripheral.wrap(v)
- end
- end
- shell.run("label", "set", "\"SafeReactor Controller\"")
- term.clear()
- term.setCursorPos(1,1)
- print("SafeReactor v."..version.." by Kai Kikuchi")
- print("Tips:")
- print("- hold Ctrl+R to reboot")
- print("- hold Ctrl+T to terminate")
- print("- edit config file with: edit config")
- term.setCursorPos(1,8)
- if not fs.exists("config") then
- cf=fs.open("config", "w")
- if cf then
- configDefault = [[
- -- passive reactor settings
- -- when running, this is the level of all rods
- -- (0-100)
- runningRodLevel=0
- -- buffers level (0-100)
- --- overload level
- ---- if buffer is under this %, it will alert you
- ---- with a message on screen and outputs a inverted
- ---- redstone signal on the right side of computer
- bOverloadLevel=10
- --- running level
- ---- under this level, the computer will start
- ---- producing energy
- bRunningLevel=75
- --- standby level
- ---- if buffer is more than this value, it will
- ---- stop generating energy
- bStandbyLevel=90
- -- acttive reactor/turbines settings
- -- turbines optimal speed (RPM)
- turbineSetSpeed=1800
- -- turbines flow rate (mB/t)
- fluidFlowRate=2000
- ]]
- cf.write(configDefault)
- cf.close()
- print("A new config file has been created! You may edit it with: edit config")
- else
- print("An error occurred while opening config file")
- end
- end
- if not os.loadAPI("config") then
- print("An error occurred while opening config file")
- error()
- end
- if r.isActivelyCooled() then
- if t then
- if config.turbineSetSpeed then
- turbineSetSpeed=config.turbineSetSpeed
- else
- turbineSetSpeed=1800
- end
- if config.fluidFlowRate then
- fluidFlowRate=config.fluidFlowRate
- else
- fluidFlowRate=2000
- end
- lastStoredPower={}
- storedPower={}
- status={}
- storedPowerTick={}
- maxEnergy={}
- energyOutput={}
- tCount=0
- for k,turbine in ipairs(t) do
- storedPower[k]=0
- lastStoredPower[k]=0
- status[k]=0
- storedPowerTick[k]=os.clock()
- maxEnergy[k]=0
- energyOutput[k]=0
- turbine.setInductorEngaged(true)
- sleep(0.10)
- turbine.setFluidFlowRateMax(fluidFlowRate)
- tCount=tCount+1
- end
- if mSide then
- monitorTextScaleMult=math.min(mSizeW/55, mSizeH/(16+(tCount*2)))
- monitorTextScaleMultFloor=math.floor(monitorTextScaleMult)
- if monitorTextScaleMult-monitorTextScaleMultFloor > 0.49 then
- monitorTextScaleMultFloor=monitorTextScaleMultFloor+0.5
- end
- if monitorTextScaleMultFloor < 0.5 then
- monitorTextScaleMultFloor=0.5
- end
- mWrap.setTextScale(monitorTextScaleMultFloor)
- mSkipEvent=true
- end
- reactorSetEcoModeCount=100
- function activeReactor()
- while true do
- m.clear()
- m.setCursorPos(1, 3)
- turbineCount=0
- turbineFlowRate=0
- reactorSetEcoMode=true
- totalMaxEnergy=0
- totalEnergyOutput=0
- for k,turbine in ipairs(t) do
- if turbine.getConnected() then
- if turbine.getActive() then
- turbineCount=turbineCount+1
- turbineSpeed=turbine.getRotorSpeed();
- startTick=storedPowerTick[k]
- storedPowerTick[k]=os.clock()
- lastStoredPower[k]=storedPower[k]
- storedPower[k]=turbine.getEnergyStored()
- energy=round(turbine.getEnergyProducedLastTick(), 0)
- timeElapsed=round((storedPowerTick[k]-startTick)*20, 2)
- energyOutputCalculated=false
- if (lastStoredPower[k] < 980000 and storedPower[k] < 980000) then
- energyOutput[k]=round((lastStoredPower[k] - storedPower[k] + (energy*timeElapsed)) / timeElapsed, 0)
- if energyOutput[k] < 0 then
- energyOutput[k] = 0
- end
- energyOutputCalculated=true
- end
- totalEnergyOutput=totalEnergyOutput+energyOutput[k]
- if energy > 0 then
- maxEnergy[k] = energy
- end
- totalMaxEnergy=totalMaxEnergy+maxEnergy[k]
- --m.write(k..": "..round(turbineSpeed,0).."RPM "..round(storedPower[k]/10000, 0).."% "..rfkrf(energyOutput[k]).."/t")
- m.write(k..": "..round(turbineSpeed,0).."RPM ")
- if turbineSpeed > turbineSetSpeed+5 or (status[k]==4 and turbineSpeed > turbineSetSpeed) then
- -- overspeed!
- m.write(rfkrf(energyOutput[k]).."/t")
- turbine.setInductorEngaged(true)
- turbine.setFluidFlowRateMax(0)
- status[k]=4
- elseif turbineSpeed < turbineSetSpeed-20 or (status[k]==3 and turbineSpeed < turbineSetSpeed) then
- -- spool up
- m.write("Spooling-up")
- turbine.setInductorEngaged(false)
- turbine.setFluidFlowRateMax(fluidFlowRate)
- turbineFlowRate=turbineFlowRate+turbine.getFluidFlowRateMax()
- status[k]=3
- else
- m.write(rfkrf(energyOutput[k]).."/t")
- if storedPower[k] < 200000 then
- if storedPower[k] < 100000 and energyOutputCalculated and energyOutput[k] >= energy then
- -- overload
- status[k]=2
- else
- status[k]=0
- end
- -- running
- turbine.setInductorEngaged(true)
- if energy-energyOutput[k] > energy/2 then
- -- little energy output, no reactor activation
- sleep(0.2)
- turbine.setInductorEngaged(false)
- turbine.setFluidFlowRateMax(0)
- status[k]=1
- else
- turbineFlowRate=turbineFlowRate+turbine.getFluidFlowRateMax()
- if turbineSpeed < turbineSetSpeed+100 then
- turbine.setFluidFlowRateMax(fluidFlowRate)
- end
- end
- elseif storedPower[k] >= 800000 then
- -- full
- turbine.setInductorEngaged(false)
- turbine.setFluidFlowRateMax(0)
- status[k]=1
- end
- end
- if status[k]==0 then
- -- m.write("RUN")
- reactorSetEcoMode=false
- elseif status[k]==1 then
- -- m.write("ECO")
- elseif status[k]==2 then
- -- m.write("OL!")
- reactorSetEcoMode=false
- elseif status[k]==3 then
- -- m.write("SUP")
- reactorSetEcoMode=false
- elseif status[k]==4 then
- -- m.write("OS!")
- end
- else
- m.write(k..": not active")
- end
- else
- m.write(k..": not connected")
- end
- curln(m, 1)
- end
- -- reactor
- casingTemp=r.getCasingTemperature()
- coreTemp=r.getFuelTemperature()
- -- rodLevel=0
- -- c=r.getNumberOfControlRods()
- rodLevel=round(r.getControlRodLevel(0), 0)
- if rodLevel > 100 then
- rodLevel = 100
- elseif rodLevel < 0 then
- rodLevel = 0
- end
- fuelConsumed=r.getFuelConsumedLastTick()
- m.write("R: "..rodLevel.."% "..round(r.getHotFluidProducedLastTick()/1000, 0).." B/t "..round(casingTemp, 0).."C ")
- if reactorSetEcoMode then
- if reactorSetEcoModeCount>0 then
- reactorSetEcoModeCount=reactorSetEcoModeCount-1
- end
- else
- reactorSetEcoModeCount=20
- end
- if turbineFlowRate>0 or reactorSetEcoModeCount>0 then
- if not (lastCasingTemp == nil) then
- if casingTemp > 600 then
- if lastCasingTemp <= casingTemp then
- if casingTemp > 2000 then
- r.setAllControlRodLevels(rodLevel+4)
- m.write("V")
- else
- r.setAllControlRodLevels(rodLevel+1)
- m.write("v ")
- end
- else
- m.write("v ")
- end
- if turbineFlowRate <= r.getHotFluidProducedLastTick() then
- -- m.write(">RUN")
- elseif (rodLevel==0 and coreTemp < 400) then
- -- is this "Tiny Reactors"?
- else
- -- not enough water
- -- m.write(">NEL")
- end
- elseif casingTemp < 400 then
- if lastCasingTemp >= casingTemp then
- if turbineFlowRate == r.getHotFluidProducedLastTick() then
- r.setAllControlRodLevels(rodLevel-1)
- else
- r.setAllControlRodLevels(rodLevel-2)
- end
- end
- -- m.write("^ >RUN")
- else
- -- m.write("* >RUN")
- end
- end
- lastCasingTemp=casingTemp
- else
- r.setAllControlRodLevels(100)
- -- m.write("- >ECO")
- end
- curln(m, 1)
- curln(m, 1)
- -- Summary info
- m.write("Capacity: "..rfkrf(totalMaxEnergy).."/t")
- curln(m, 1)
- m.write("Output: "..rfkrf(totalEnergyOutput).."/t")
- curln(m, 1)
- m.write("Fuel burnup: "..round(fuelConsumed, 3).." mB/t")
- curln(m, 1)
- m.write("Score: "..scoreCalc(totalMaxEnergy, fuelConsumed, coreTemp, casingTemp))
- curln(m, 1)
- sleep(0.5)
- end
- end
- parallel.waitForAll(activeReactor, events, gui)
- else
- print("Reactor is actively cooled, but there is no turbine")
- error()
- end
- else
- rodStat=2
- statCol=16
- bOverloadLevel=config.bOverloadLevel*100000
- bRunningLevel=config.bRunningLevel*100000
- bStandbyLevel=config.bStandbyLevel*100000
- storedPower=0
- lastStoredPower=0
- energyOutput=0
- maxEnergy=0
- r.setAllControlRodLevels(config.runningRodLevel)
- if mSide then
- monitorTextScaleMult=math.min(mSizeW/55, mSizeH/24)
- monitorTextScaleMultFloor=math.floor(monitorTextScaleMult)
- if monitorTextScaleMult-monitorTextScaleMultFloor > 0.49 then
- monitorTextScaleMultFloor=monitorTextScaleMultFloor+0.5
- end
- if monitorTextScaleMultFloor < 0.5 then
- monitorTextScaleMultFloor=0.5
- end
- mWrap.setTextScale(monitorTextScaleMultFloor)
- mSkipEvent=true
- end
- local function passiveReactor()
- while true do
- m.clear()
- m.setCursorPos(1, 3)
- if r.getConnected() then
- coreTemp=round(r.getFuelTemperature(), 0)
- casingTemp=round(r.getCasingTemperature(), 0)
- lastStoredPower=storedPower
- storedPower=r.getEnergyStored()
- energy=round(r.getEnergyProducedLastTick(), 0)
- if energy > maxEnergy then
- maxEnergy = energy
- end
- energyOutput=round((lastStoredPower - storedPower + (energy*20)) / 20, 0)
- if energyOutput < 0 then
- energyOutput = 0
- end
- -- control rods
- if storedPower < bOverloadLevel and energyOutput >= energy then
- rodStat=1
- r.setAllControlRodLevels(config.runningRodLevel)
- elseif storedPower < bRunningLevel then
- rodStat=2
- r.setAllControlRodLevels(config.runningRodLevel)
- elseif storedPower >= bStandbyLevel then
- rodStat=3
- r.setAllControlRodLevels(100)
- end
- -- fuel amount
- fuelAmount=(r.getFuelAmountMax()/r.getFuelAmount())
- fuelConsumed=r.getFuelConsumedLastTick()
- -- display info
- m.clearLine()
- m.write("Heat (int|ext)")
- curxm(m, statCol)
- m.write(": "..coreTemp.."C|"..casingTemp.."C")
- curln(m, 1)
- m.clearLine()
- m.write("Output")
- curxm(m, statCol)
- m.write(": "..rfkrf(energyOutput).."/t")
- curln(m, 1)
- m.clearLine()
- m.write("Buffer (10 mRF)")
- curxm(m, statCol)
- m.write(": "..round(storedPower/100000, 2).." %")
- curln(m, 1)
- m.clearLine()
- m.write("Production")
- curxm(m, statCol)
- m.write(": "..rfkrf(energy).."/t")
- curln(m, 1)
- m.clearLine()
- m.write("Max. Production")
- curxm(m, statCol)
- m.write(": "..rfkrf(maxEnergy).."/t")
- curln(m, 1)
- m.clearLine()
- m.write("Fuel burnup: ")
- curxm(m, statCol)
- m.write(": "..round(fuelConsumed, 3).." mB/t")
- curln(m, 1)
- m.clearLine()
- m.write("Score")
- curxm(m, statCol)
- m.write(": "..scoreCalc(maxEnergy, fuelConsumed, coreTemp, casingTemp))
- m.setCursorPos(1, 10)
- m.clearLine()
- rs.setOutput("right", true)
- if r.getActive() then
- if fuelAmount > 1.4 then
- m.write("Status: online - fuel needed!")
- rs.setOutput("right", false)
- elseif casingTemp > 2000 then
- m.write("Status: online - OVERHEAT!")
- rs.setOutput("right", false)
- if casingTemp > 3000 then
- r.setActive(false)
- end
- else
- if rodStat == 1 then
- m.write("Status: online - overload!")
- rs.setOutput("right", false)
- elseif rodStat == 2 then
- m.write("Status: online - running")
- elseif rodStat == 3 then
- m.write("Status: online - standby")
- if (storedPower/100000) > 99 then
- bStandbyLevel=bStandbyLevel-1
- end
- else
- m.write("Status: Error")
- end
- end
- else
- m.setCursorPos(1, 10)
- m.clearLine()
- m.write("Status: offline")
- end
- else
- m.setCursorPos(1, 10)
- m.clearLine()
- m.write("Status: no reactor")
- end
- sleep(0.5)
- end
- end
- parallel.waitForAll(passiveReactor, events, gui)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement