Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local event = require("event")
- local term = require("term")
- local gpu = component.gpu
- local screen = component.screen
- local unicode= require("unicode")
- -- DynamicRes
- local ratioX, ratioY = screen.getAspectRatio()
- local maxX, maxY = gpu.maxResolution()
- gpu.setResolution(math.min(ratioX*55, maxX), math.min(ratioY*25,maxY))
- -- Safety Checks
- if not component.isAvailable("draconic_reactor") then
- print("Reactor not connected. Please connect computer to reactor with an Adapter block.")
- os.exit()
- end
- reactor = component.draconic_reactor
- local flux_gates = {}
- for x,y in pairs(component.list("flux_gate")) do
- flux_gates[#flux_gates+1] = x
- end
- if #flux_gates < 2 then
- print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
- os.exit()
- end
- flux_in = component.proxy(flux_gates[1])
- flux_out = component.proxy(flux_gates[2])
- if not flux_in or not flux_out then
- print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
- os.exit()
- end
- -- Functions
- function exit_msg(msg)
- term.clear()
- print(msg)
- os.exit()
- end
- function modify_temp(offset)
- local new_temp = ideal_temp + offset
- if new_temp > 8000 then
- new_temp = 8000
- elseif new_temp < 2000 then
- new_temp = 2000
- end
- ideal_temp = new_temp
- end
- local bypassfield = 0
- local chaosmode = 0
- function modify_field(offset)
- local new_strength = ideal_strength + offset
- if new_strength > 99 then
- new_strength = 99
- elseif new_strength < 75 and chaosmode == 1 then
- new_strength = 75
- elseif new_strength < 0.5 then
- new_strength = 0.5
- end
- ideal_strength = new_strength
- end
- -- Buttons
- local adj_button_width = 19
- local temp_adjust_x_offset = 62
- local temp_adjust_y_offset = 2
- local field_adjust_x_offset = temp_adjust_x_offset + adj_button_width + 2
- local field_adjust_y_offset = 2
- local status = "PeFi"
- local lowest_field = 100
- local lowest_fuel = 100
- local highest_temp = 0
- local highest_sat = 0
- local highest_outflow = 0
- local cutoff_field = 0.75
- local highest_use = 0.1
- -- Inflow PID
- local proportional_field_error = 0
- local inflow_I_sum = 0
- local integral_field_error = 0
- local derivative_field_error = 0
- local inflow_D_last = 0
- local inflow_correction = 0
- -- Outflow PID
- local proportional_temp_error = 0
- local outflow_I_sum = 0
- local integral_temp_error = 0
- local derivative_temp_error = 0
- local outflow_D_last = 0
- local outflow_correction = 0
- local buttons = {
- start={
- x=2,
- y=30,
- width=18,
- height=1,
- text="Start",
- action=function()
- if safe then
- chaosmode = 0
- shutdownE = 0
- ideal_strength = 15
- cutoff_field = 0.4
- ideal_temp = 8000
- lowest_field = 99
- state = "CHRG"
- reactor.chargeReactor()
- shutdownE = 0
- elseif shutting_down then
- chaosmode = 0
- shutdownE = 0
- ideal_strength = 15
- cutoff_field = 0.4
- ideal_temp = 8000
- lowest_field = 99
- state = "ACTV"
- reactor.activateReactor()
- end
- end,
- condition=function() return safe or shutting_down end
- },
- shutdown={
- x=2,
- y=30,
- width=18,
- height=1,
- text="Shutdown",
- action=function()
- cutoff_temp = 8001
- ideal_temp = 8000
- ideal_strength = 15
- cutoff_field = 0.75
- chaosmode = 0
- shutdownE = 1
- state = "MASD"
- reactor.stopReactor()
- end,
- condition=function() return running end
- },
- chaosmode={
- x=2,
- y=32,
- width=18,
- height=1,
- text=" Chaos Mode",
- action=function()
- if chaosmode == 0 then
- chaosmode = 1
- shutdownE = 0
- cutoff_temp = 19750
- ideal_strength = 99
- cutoff_field = 20
- ideal_temp = 55537
- lowest_field = 99
- elseif chaosmode == 1 then
- chaosmode = 0
- shutdownE = 0
- ideal_strength = 15
- cutoff_field = 0.4
- ideal_temp = 8000
- lowest_field = 99
- end
- end,
- condition=function() return running end
- },
- analytics={
- x=42,
- y=30,
- width=18,
- height=1,
- text="Reset Analytics",
- action=function()
- highest_temp = 0
- lowest_field = 200
- highest_outflow = 0
- highest_sat = 0
- status = "PeFi"
- end,
- },
- force_exit={
- x=22,
- y=30,
- width=18,
- height=1,
- text="Force Exit",
- action=function()
- chaosmode = 0
- shutdownE = 0
- ideal_strength = 99
- cutoff_field = 0.4
- ideal_temp = 8000
- lowest_field = 99
- state = "MASD"
- reactor.stopReactor()
- gpu.setResolution(gpu.maxResolution())
- event_loop = false
- end,
- condition=function() return running or shutting_down end
- },
- update={
- x=22,
- y=32,
- width=18,
- height=1,
- text="Update",
- action=function()
- reactor.stopReactor()
- os.execute("pastebin get -f 8gYugLnR dc10; cls; rm dc9; dc10")
- end,
- },
- switch_gates={
- x=2,
- y=32,
- width=18,
- height=1,
- text="Swap flux gates",
- action=function()
- cutoff_temp = 10500
- local old_addr = flux_in.address
- flux_in = component.proxy(flux_out.address)
- flux_out = component.proxy(old_addr)
- end,
- condition=function() return safe end
- },
- exit={
- x=22,
- y=30,
- width=18,
- height=1,
- text="Exit",
- action=function()
- event_loop = false
- end,
- condition=function() return safe end
- },
- temp_up_max={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset,
- width=adj_button_width,
- height=1,
- text="Maximum",
- action=function()
- ideal_temp = 8000
- end
- },
- temp_up_thousand={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+2,
- width=adj_button_width,
- height=1,
- text="+1000",
- action=function() modify_temp(1000) end
- },
- temp_up_hundred={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+4,
- width=adj_button_width,
- height=1,
- text="+100",
- action=function() modify_temp(100) end
- },
- temp_up_ten={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+6,
- width=adj_button_width,
- height=1,
- text="+10",
- action=function() modify_temp(10) end
- },
- temp_up_one={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+8,
- width=adj_button_width,
- height=1,
- text="+1",
- action=function() modify_temp(1) end
- },
- temp_down_thousand={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+18,
- width=adj_button_width,
- height=1,
- text="-1000",
- action=function() modify_temp(-1000) end
- },
- temp_down_max={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+20,
- width=adj_button_width,
- height=1,
- text="Minimum",
- action=function() modify_temp(-20000) end
- },
- temp_down_hundred={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+16,
- width=adj_button_width,
- height=1,
- text="-100",
- action=function() modify_temp(-100) end
- },
- temp_down_ten={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+14,
- width=adj_button_width,
- height=1,
- text="-10",
- action=function() modify_temp(-10) end
- },
- temp_down_one={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+12,
- width=adj_button_width,
- height=1,
- text="-1",
- action=function() modify_temp(-1) end
- },
- field_up_ten={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+3,
- width=adj_button_width,
- height=1,
- text="+10",
- action=function() modify_field(10) end
- },
- field_up_one={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+5,
- width=adj_button_width,
- height=1,
- text="+1",
- action=function() modify_field(1) end
- },
- field_up_tenth={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+7,
- width=adj_button_width,
- height=1,
- text="+0.1",
- action=function() modify_field(0.1) end
- },
- field_down_ten={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+17,
- width=adj_button_width,
- height=1,
- text="-10",
- action=function() modify_field(-10) end
- },
- field_down_one={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+15,
- width=adj_button_width,
- height=1,
- text="-1",
- action=function() modify_field(-1) end
- },
- field_down_tenth={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+13,
- width=adj_button_width,
- height=1,
- text="-0.1",
- action=function() modify_field(-0.1) end
- }
- }
- -- main code
- flux_in.setFlowOverride(0)
- flux_out.setFlowOverride(0)
- flux_in.setOverrideEnabled(true)
- flux_out.setOverrideEnabled(true)
- local condition = reactor.getReactorInfo()
- if not condition then
- print("Reactor not initialized, please ensure the stabilizers are properly laid out.")
- os.exit()
- end
- ideal_strength = 15
- ideal_temp = 8000
- cutoff_temp = 8001
- -- tweakable pid gains
- inflow_P_gain = 1
- inflow_I_gain = 0.04
- inflow_D_gain = 0.05
- outflow_P_gain = 500
- outflow_I_gain = 0.10
- outflow_II_gain = 0.0000003
- outflow_D_gain = 30000
- -- initialize main loop
- inflow_I_sum = 0
- inflow_D_last = 0
- outflow_I_sum = 0
- outflow_II_sum = 0
- outflow_D_last = 0
- state = "STBY"
- shutting_down = false
- if condition.temperature > 25 then
- state = "CLNG"
- end
- if condition.temperature > 2000 then
- state = "ACTV"
- end
- -- Possible states:
- --Standby
- --Charging
- --Active
- --Manual Shutdown
- --Emergency Shutdown
- --Cooling
- event_loop = true
- while event_loop do
- if not component.isAvailable("draconic_reactor") then
- exit_msg("Reactor disconnected, exiting")
- end
- if not component.isAvailable("flux_gate") then
- exit_msg("Flux gates disconnected, exiting")
- end
- local info = reactor.getReactorInfo()
- -- Highest Heat Value
- if info.temperature > highest_temp then
- highest_temp = info.temperature
- end
- -- Highest Sat Value
- if ((info.energySaturation / info.maxEnergySaturation) * 100) > highest_sat then
- highest_sat = ((info.energySaturation / info.maxEnergySaturation) * 100)
- end
- -- Lowest Field Value ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
- if ((info.fieldStrength / info.maxFieldStrength) * 100) < lowest_field then
- lowest_field = ((info.fieldStrength / info.maxFieldStrength) * 100)
- end
- -- Lowest Fuel Value
- if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < lowest_fuel then
- lowest_fuel = ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
- end
- -- Lowest Fuel Use Rate
- if info.fuelConversionRate > highest_use then
- highest_use = info.fuelConversionRate
- end
- local inflow = 0
- local outflow = 0
- shutting_down = state == "MASD" or state == "ESHD"
- running = state == "CHRG" or state == "ACTV"
- safe = state == "STBY" or state == "CLNG"
- if state == "CHRG" then
- inflow = 5000000
- if info.temperature > 2000 then
- reactor.activateReactor()
- state = "ACTV"
- end
- elseif state == "CLNG" then
- if info.temperature < 25 then
- state = "STBY"
- end
- inflow = 10
- outflow = 20
- elseif state == "STBY" then
- inflow = 10
- outflow = 20
- else
- -- adjust inflow rate based on field strength
- field_error = (info.maxFieldStrength * (ideal_strength / 100)) - info.fieldStrength
- proportional_field_error = field_error * inflow_P_gain
- inflow_I_sum = inflow_I_sum + field_error
- integral_field_error = inflow_I_sum * inflow_I_gain
- derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
- inflow_D_last = field_error
- inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
- if inflow_correction < 0 then
- inflow_I_sum = inflow_I_sum - field_error
- end
- inflow = inflow_correction
- if not shutting_down then
- -- adjust outflow rate based on core temperature
- temp_error = ideal_temp - info.temperature
- proportional_temp_error = temp_error * outflow_P_gain
- outflow_I_sum = outflow_I_sum + temp_error
- integral_temp_error = outflow_I_sum * outflow_I_gain
- if math.abs(temp_error) < 100 then
- outflow_II_sum = outflow_II_sum + integral_temp_error
- else
- outflow_II_sum = 0
- end
- second_integral_temp_error = outflow_II_sum * outflow_II_gain
- derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
- outflow_D_last = temp_error
- outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
- if outflow_correction < 0 then
- outflow_I_sum = outflow_I_sum - temp_error
- end
- outflow = outflow_correction
- -- cut off reactor in case of emergency
- if info.temperature > cutoff_temp then
- print("Reactor Too Hot, shutting down")
- state = "ESHD"
- status = "HiTe"
- reactor.stopReactor()
- end
- if ((info.fieldStrength / info.maxFieldStrength) * 100) < cutoff_field then
- print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
- state = "ESHD"
- status = "LoFi"
- reactor.stopReactor()
- end
- if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 1.25 and chaosmode == 0 then
- print("Reactor Fuel Low, Shutting Down")
- state = "ESHD"
- status = "LoFu"
- reactor.stopReactor()
- elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 5 and chaosmode == 1 then
- print("Reactor Fuel Low, Shutting Down")
- state = "ESHDn"
- status = "LoFu"
- reactor.stopReactor()
- end
- else
- if info.temperature < 2000 then
- state = "CLNG"
- end
- end
- end
- if state ~= "ACTV" and not shutting_down then
- inflow_I_sum = 0
- inflow_D_last = 0
- outflow_I_sum = 0
- outflow_II_sum = 0
- outflow_D_last = 0
- end
- if inflow < 0 then
- inflow = 0
- end
- if outflow < 0 then
- outflow = 0
- end
- inflow = math.floor(inflow)
- outflow = math.floor(outflow)
- flux_in.setFlowOverride(inflow)
- flux_out.setFlowOverride(outflow)
- -- Draw screen
- if term.isAvailable() then
- -- Draw Values
- function modify_eff(offset)
- local eff = ((outflow / inflow) * 100)
- if eff > 100000 then
- eff = 1
- end
- end
- -- Get Temp Rise
- oldTemp = currentTemp or info.temperature
- currentTemp = info.temperature
- oldTempRate = tempChangeRate or currentTemp - oldTemp
- tempChangeRate = currentTemp - oldTemp
- tempAccel = tempChangeRate - oldTempRate
- if tempAccel == 0 then
- tempAccel = 0.001
- end
- -- Get Fuel Use Rate
- oldFuel = currentFuel or (info.maxFuelConversion - info.fuelConversion)
- currentFuel = (info.maxFuelConversion - info.fuelConversion)
- oldUseRate = fuelUseRate or math.max(info.fuelConversionRate*20, 0.1)
- fuelUseRate = math.max(info.fuelConversionRate*20, 0.1)
- fuelAccel = math.max(fuelUseRate - oldUseRate, 0.1)
- -- Fuel Conversion Rate
- if info.fuelConversionRate > 999 then
- fuelConversionRate = (info.fuelConversionRate / 1000)
- fuelMeasure = (unicode.char(956)).." b/t"
- elseif info.fuelConversionRate > 999999 then
- fuelConversionRate = (info.fuelConversionRate / 1000000)
- fuelMeasure = " mb/t"
- else
- fuelConversionRate = info.fuelConversionRate
- fuelMeasure = " nb/t"
- end
- -- Inflow Modification
- if chaosmode == 1 or info.temperature > 10000 then
- inflowMod = -1
- else inflowMod = inflow
- end
- -- Outflow Modification
- if chaosmode == 1 then
- outflowMod = -1
- else outflowMod = outflow
- end
- if chaosmode == 1 then
- profitMod = -1
- else profitMod = (outflow - inflow)
- end
- -- Efficiency Modification
- if chaosmode == 1 then
- efficiencyMod = -1
- else efficiencyMod = ((outflow / inflow) * 100)
- end
- -- DrawData
- --local secondsToExpire = (fuelUseRate + math.abs(fuelUseRate^2 - 2*fuelAccel*currentFuel)^0.5)/fuelAccel
- local secondsToExpire = (info.maxFuelConversion - info.fuelConversion) / math.max(info.fuelConversionRate*0.00002, 0.00001)
- local left_margin = 2
- local spacing = 1
- local values = {
- "- v9.5b [Y8gPvV48]",
- " ",
- " Reactor Statistics",
- "┌───────────────────────────┬────────────────────────────┐",
- string.format("│Time Until Refuel: │ %5dd, %2dh, %2dm, %2ds │", secondsToExpire/86400, secondsToExpire /3600 % 24, secondsToExpire/60 % 60, secondsToExpire % 60),
- string.format("│Ideal Field: │ %5.1f%% │", ideal_strength),
- string.format("│Current Field: │ %5.1f%% │", ((info.fieldStrength / info.maxFieldStrength) * 100)),
- "├───────────────────────────┼────────────────────────────┤",
- string.format("│Fuel Remaining: │ %7.3f%% │", ((1 - info.fuelConversion / info.maxFuelConversion) * 100)),
- string.format("│Fuel Use Rate: │ %7.3f" .. fuelMeasure .. " │", fuelConversionRate),
- "├───────────────────────────┼────────────────────────────┤",
- string.format("│Temperature │ %7.1f°c [%7.1f°f] │", info.temperature, ((info.temperature * 1.8) + 32)),
- string.format("│Ideal Temperature: │ %7.1f°c [%7.1f°f] │", ideal_temp, ((ideal_temp * 1.8) + 32)),
- "├───────────────────────────┼────────────────────────────┤",
- string.format("│Energy Input: │ %12.1f RF/t │", inflowMod),
- string.format("│Energy Output: │ %12.1f RF/t │", outflowMod),
- string.format("│Energy Efficiency: │ %12.1f%% │", efficiencyMod),
- string.format("│Energy Profit: │ %13.1f RF/t │", profitMod),
- "└───────────────────────────┴────────────────────────────┘",
- " Debug Information ",
- "┌───────────────────────────┬────────────────────────────┐",
- "│Status: │ " .. state .. "-" .. status .. " │",
- string.format("│Max Field Drop: │ %6.2f%% │", lowest_field),
- string.format("│Lowest Recorded Fuel: │ %6.2f%% │", lowest_fuel),
- string.format("│Max Temp Spike: │ %8.2f │", highest_temp),
- string.format("│Max Saturation: │ %6.2f%% │", highest_sat),
- string.format("│Max Fuel Use: │ %9.2f nb/t │", highest_use),
- "└───────────────────────────┴────────────────────────────┘",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- string.format("Max Fuel [nb]: %4.3f", (info.maxFuelConversion * 1000000)),
- string.format("Fuel Remaining [nb]: %4.3f", ((info.maxFuelConversion - info.fuelConversion) * 1000000)),
- string.format("Temperature Rise: %4.3f", tempAccel),
- " PID Values",
- " ",
- string.format("I: P%12.1f, IS%12.1f, I%12.1f, D%12.1f, DL%12.1f, C%12.1f", proportional_field_error, inflow_I_sum, integral_field_error, derivative_field_error, inflow_D_last, inflow_correction),
- string.format("O: P%12.1f, IS%12.1f, I%12.1f, D%12.1f, DL%12.1f, C%12.1f", proportional_temp_error, outflow_I_sum, integral_temp_error, derivative_temp_error, outflow_D_last, outflow_correction),
- }
- term.clear()
- for i, v in ipairs(values) do
- term.setCursor(left_margin, i * spacing)
- term.write(v)
- end
- -- Draw button values
- term.setCursor(temp_adjust_x_offset, temp_adjust_y_offset+10)
- term.write("Reactor Temperature")
- term.setCursor(field_adjust_x_offset+1, field_adjust_y_offset+10)
- term.write("Field Strength")
- -- Draw Buttons
- gpu.setForeground(0x000000)
- for bname, button in pairs(buttons) do
- if button.depressed then
- button.depressed = button.depressed - 1
- if button.depressed == 0 then
- button.depressed = nil
- end
- end
- if button.condition == nil or button.condition() then
- local center_color = 0xAAAAAA
- local highlight_color = 0xCCCCCC
- local lowlight_color = 0x808080
- if button.depressed then
- center_color = 0x999999
- highlight_color = 0x707070
- lowlight_color = 0xBBBBBB
- end
- gpu.setBackground(center_color)
- gpu.fill(button.x, button.y, button.width, button.height, " ")
- if button.width > 1 and button.height > 1 then
- gpu.setBackground(lowlight_color)
- gpu.fill(button.x+1, button.y+button.height-1, button.width-1, 1, " ")
- gpu.fill(button.x+button.width-1, button.y, 1, button.height, " ")
- gpu.setBackground(highlight_color)
- gpu.fill(button.x, button.y, 1, button.height, " ")
- gpu.fill(button.x, button.y, button.width, 1, " ")
- end
- gpu.setBackground(center_color)
- term.setCursor(button.x + math.floor(button.width / 2 - #button.text / 2), button.y + math.floor(button.height / 2))
- term.write(button.text)
- end
- end
- gpu.setBackground(0x000000)
- gpu.setForeground(0xFFFFFF)
- end
- -- Wait for next tick, or manual shutdown
- local event, id, op1, op2 = event.pull(0.05)
- if event == "interrupted" then
- if safe then
- break
- end
- elseif event == "touch" then
- -- Handle Button Presses
- local x = op1
- local y = op2
- for bname, button in pairs(buttons) do
- if (button.condition == nil or button.condition()) and x >= button.x and x <= button.x + button.width and y >= button.y and y <= button.y + button.height then
- button.action()
- button.depressed = 3
- end
- end
- end
- os.sleep()
- end
- term.clear()
Add Comment
Please, Sign In to add comment