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
- -- 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 = "Charging"
- 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 = "Active"
- 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 = "Manual Shutdown"
- 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 = "Manual Shutdown"
- 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 Y8gPvV48 dc9; cls; dc9")
- 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 = "Standby"
- shutting_down = false
- if condition.temperature > 25 then
- state = "Cooling"
- end
- if condition.temperature > 2000 then
- state = "Active"
- 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 == "Manual Shutdown" or state == "Emergency Shutdown"
- running = state == "Charging" or state == "Active"
- safe = state == "Standby" or state == "Cooling"
- if state == "Charging" then
- inflow = 5000000
- if info.temperature > 2000 then
- reactor.activateReactor()
- state = "Active"
- end
- elseif state == "Cooling" then
- if info.temperature < 25 then
- state = "Standby"
- end
- inflow = 10
- outflow = 20
- elseif state == "Standby" 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 = "Emergency Shutdown"
- status = "HiTe"
- reactor.stopReactor()
- end
- if ((info.fieldStrength / info.maxFieldStrength) * 100) < cutoff_field then
- print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
- state = "Emergency Shutdown"
- 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 = "Emergency Shutdown"
- status = "LoFu"
- reactor.stopReactor()
- elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 5 and chaosmode == 1 then
- print("Reactor Fuel Low, Shutting Down")
- state = "Emergency Shutdown"
- status = "LoFu"
- reactor.stopReactor()
- end
- else
- if info.temperature < 2000 then
- state = "Cooling"
- end
- end
- end
- if state ~= "Active" 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 = "ub/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: | %7.1f%% [%10.1fRF] |", ((info.fieldStrength / info.maxFieldStrength) * 100), ((info.fieldStrength / info.maxFieldStrength) * 100000000)),
- "----------------------------┼----------------------------┤",
- 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 ",
- " ",
- string.format("Max Field Drop: | %5.2f%% ", lowest_field),
- string.format("Lowest Recorded Fuel: | %5.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: | %6.2f nb/t ", highest_use),
- "Status: | " .. state .. "-" .. status .. " ",
- "----------------------------------------------------------",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- 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