neuroticfox

DC7

Jul 16th, 2021 (edited)
625
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.43 KB | None | 0 0
  1. local component = require("component")
  2. local event = require("event")
  3. local term = require("term")
  4. local gpu = component.gpu
  5.  
  6.  -- Safety Checks
  7.  
  8. if not component.isAvailable("draconic_reactor") then
  9.   print("Reactor not connected. Please connect computer to reactor with an Adapter block.")
  10.   os.exit()
  11. end
  12. reactor = component.draconic_reactor
  13. local flux_gates = {}
  14. for x,y in pairs(component.list("flux_gate")) do
  15.   flux_gates[#flux_gates+1] = x
  16. end
  17. if #flux_gates < 2 then
  18.   print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  19.   os.exit()
  20. end
  21. flux_in = component.proxy(flux_gates[1])
  22. flux_out = component.proxy(flux_gates[2])
  23. if not flux_in or not flux_out then
  24.   print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  25.   os.exit()
  26. end
  27.  
  28.  -- Functions
  29.  
  30. function exit_msg(msg)
  31.   term.clear()
  32.   print(msg)
  33.   os.exit()
  34. end
  35.  
  36. function modify_temp(offset)
  37.   local new_temp = ideal_temp + offset
  38.   if new_temp > 10000 and TO == 0 then
  39.     new_temp = 10000
  40.   elseif new_temp < 2000 then
  41.     new_temp = 2000
  42.   end
  43.   ideal_temp = new_temp
  44. end
  45.  
  46. function modify_field(offset)
  47.   local new_strength = ideal_strength + offset
  48.   if new_strength > 100 then
  49.     new_strength = 100
  50.   elseif new_strength < 1 then
  51.     new_strength = 1
  52.   end
  53.   ideal_strength = new_strength
  54. end
  55.  
  56.  -- Buttons
  57.  
  58. local adj_button_width = 19
  59. local temp_adjust_x_offset = 68
  60. local temp_adjust_y_offset = 2
  61. local field_adjust_x_offset = temp_adjust_x_offset + adj_button_width + 2
  62. local field_adjust_y_offset = 2
  63. local status = "PeFi"
  64. local lowest_field = 100
  65. local lowest_fuel = 100
  66. local highest_temp = 0
  67. local highest_sat = 0
  68. local highest_outflow = 0
  69. local buttons = {
  70.   start={
  71.     x=42,
  72.     y=2,
  73.     width=24,
  74.     height=7,
  75.     text="Start",
  76.     action=function()
  77.       if safe then
  78.         state = "Charging"
  79.         reactor.chargeReactor()
  80.       elseif shutting_down then
  81.         state = "Active"
  82.         reactor.activateReactor()
  83.       end
  84.     end,
  85.     condition=function() return safe or shutting_down end
  86.   },
  87.   shutdown={
  88.     x=42,
  89.     y=12,
  90.     width=24,
  91.     height=7,
  92.     text="Shutdown",
  93.     action=function()
  94.     cutoff_temp = 10500
  95.     ideal_temp = 8000
  96.     ideal_strength = 55
  97.     cutoff_field = 0.45
  98.       state = "Manual Shutdown"
  99.       reactor.stopReactor()
  100.     end,
  101.   },
  102.       chaosmode={
  103.     x=2,
  104.     y=40,
  105.     width=24,
  106.     height=3,
  107.     text=" Chaos Mode",
  108.     action=function()
  109.       cutoff_temp = 17500
  110.       cutoff_field = 5
  111.       ideal_strength = 75
  112.       ideal_temp = 30000
  113.       lowest_field = 200
  114.     end,
  115.     condition=function() return running end
  116.   },
  117.     analytics={
  118.     x=28,
  119.     y=40,
  120.     width=24,
  121.     height=3,
  122.     text="Reset Analytics",
  123.     action=function()
  124.       highest_temp = 0
  125.       lowest_field = 200
  126.       highest_outflow = 0
  127.       status = "PeFi"
  128.     end,
  129.   },
  130.     Explode={
  131.     x=28,
  132.     y=44,
  133.     width=24,
  134.     height=3,
  135.     text="Initiate Meltdown",
  136.     action=function()
  137.       ideal_strength = 0
  138.       ideal_temp = 30000
  139.     end,
  140.     condition=function() return running end
  141.   },
  142.     force_exit={
  143.     x=2,
  144.     y=44,
  145.     width=24,
  146.     height=3,
  147.     text="Force Exit",
  148.     action=function()
  149.       cutoff_temp = 10500
  150.       ideal_temp = 2000
  151.       ideal_strength = 55
  152.       cutoff_field = 0.45
  153.       state = "Manual Shutdown"
  154.       reactor.stopReactor()
  155.       event_loop = false
  156.     end,
  157.   },
  158.     switch_gates={
  159.     x=2,
  160.     y=40,
  161.     width=24,
  162.     height=3,
  163.     text="Swap flux gates",
  164.     action=function()
  165.       cutoff_temp = 10500
  166.       local old_addr = flux_in.address
  167.       flux_in = component.proxy(flux_out.address)
  168.       flux_out = component.proxy(old_addr)
  169.     end,
  170.     condition=function() return safe or shutting_down end
  171.   },
  172.     exit={
  173.     x=42,
  174.     y=22,
  175.     width=24,
  176.     height=7,
  177.     text="Exit",
  178.     action=function()
  179.       event_loop = false
  180.     end,
  181.     condition=function() return safe end
  182.   },
  183.   temp_up_max={
  184.     x=temp_adjust_x_offset,
  185.     y=temp_adjust_y_offset,
  186.     width=adj_button_width,
  187.     height=1,
  188.     text="Maximum",
  189.     action=function()
  190.       ideal_temp = 10500
  191.     end
  192.   },
  193.   temp_up_thousand={
  194.     x=temp_adjust_x_offset,
  195.     y=temp_adjust_y_offset+2,
  196.     width=adj_button_width,
  197.     height=1,
  198.     text="+1000",
  199.     action=function() modify_temp(1000) end
  200.   },
  201.   temp_up_hundred={
  202.     x=temp_adjust_x_offset,
  203.     y=temp_adjust_y_offset+4,
  204.     width=adj_button_width,
  205.     height=1,
  206.     text="+100",
  207.     action=function() modify_temp(100) end
  208.   },
  209.   temp_up_ten={
  210.     x=temp_adjust_x_offset,
  211.     y=temp_adjust_y_offset+6,
  212.     width=adj_button_width,
  213.     height=1,
  214.     text="+10",
  215.     action=function() modify_temp(10) end
  216.   },
  217.   temp_up_one={
  218.     x=temp_adjust_x_offset,
  219.     y=temp_adjust_y_offset+8,
  220.     width=adj_button_width,
  221.     height=1,
  222.     text="+1",
  223.     action=function() modify_temp(1) end
  224.   },
  225.   temp_down_thousand={
  226.     x=temp_adjust_x_offset,
  227.     y=temp_adjust_y_offset+18,
  228.     width=adj_button_width,
  229.     height=1,
  230.     text="-1000",
  231.     action=function() modify_temp(-1000) end
  232.   },
  233.     temp_down_max={
  234.     x=temp_adjust_x_offset,
  235.     y=temp_adjust_y_offset+20,
  236.     width=adj_button_width,
  237.     height=1,
  238.     text="Minimum",
  239.     action=function() modify_temp(-20000) end
  240.   },
  241.   temp_down_hundred={
  242.     x=temp_adjust_x_offset,
  243.     y=temp_adjust_y_offset+16,
  244.     width=adj_button_width,
  245.     height=1,
  246.     text="-100",
  247.     action=function() modify_temp(-100) end
  248.   },
  249.   temp_down_ten={
  250.     x=temp_adjust_x_offset,
  251.     y=temp_adjust_y_offset+14,
  252.     width=adj_button_width,
  253.     height=1,
  254.     text="-10",
  255.     action=function() modify_temp(-10) end
  256.   },
  257.   temp_down_one={
  258.     x=temp_adjust_x_offset,
  259.     y=temp_adjust_y_offset+12,
  260.     width=adj_button_width,
  261.     height=1,
  262.     text="-1",
  263.     action=function() modify_temp(-1) end
  264.   },
  265.   field_up_ten={
  266.     x=field_adjust_x_offset,
  267.     y=field_adjust_y_offset+3,
  268.     width=adj_button_width,
  269.     height=1,
  270.     text="+10",
  271.     action=function() modify_field(10) end
  272.   },
  273.     field_up_one={
  274.     x=field_adjust_x_offset,
  275.     y=field_adjust_y_offset+5,
  276.     width=adj_button_width,
  277.     height=1,
  278.     text="+1",
  279.     action=function() modify_field(1) end
  280.   },
  281.   field_up_tenth={
  282.     x=field_adjust_x_offset,
  283.     y=field_adjust_y_offset+7,
  284.     width=adj_button_width,
  285.     height=1,
  286.     text="+0.1",
  287.     action=function() modify_field(0.1) end
  288.   },
  289.   field_down_ten={
  290.     x=field_adjust_x_offset,
  291.     y=field_adjust_y_offset+17,
  292.     width=adj_button_width,
  293.     height=1,
  294.     text="-10",
  295.     action=function() modify_field(-10) end
  296.   },
  297.     field_down_one={
  298.     x=field_adjust_x_offset,
  299.     y=field_adjust_y_offset+15,
  300.     width=adj_button_width,
  301.     height=1,
  302.     text="-1",
  303.     action=function() modify_field(-1) end
  304.   },
  305.   field_down_tenth={
  306.     x=field_adjust_x_offset,
  307.     y=field_adjust_y_offset+13,
  308.     width=adj_button_width,
  309.     height=1,
  310.     text="-0.1",
  311.     action=function() modify_field(-0.1) end
  312.   }
  313. }
  314.  
  315.  -- main code
  316.  
  317. flux_in.setFlowOverride(0)
  318. flux_out.setFlowOverride(0)
  319. flux_in.setOverrideEnabled(true)
  320. flux_out.setOverrideEnabled(true)
  321.  
  322. local condition = reactor.getReactorInfo()
  323. if not condition then
  324.   print("Reactor not initialized, please ensure the stabilizers are properly laid out.")
  325.   os.exit()
  326. end
  327.  
  328. ideal_strength = 15
  329.  
  330. ideal_temp = 8000
  331. cutoff_temp = 10001
  332.  
  333.  -- tweakable pid gains
  334.  
  335. inflow_P_gain = 1
  336. inflow_I_gain = 0.04
  337. inflow_D_gain = 0.1
  338.  
  339. outflow_P_gain = 500
  340. outflow_I_gain = 0.5
  341. outflow_II_gain = 0.0000003
  342. outflow_D_gain = 60000
  343.  
  344.  -- initialize main loop
  345.  
  346. inflow_I_sum = 0
  347. inflow_D_last = 0
  348.  
  349. outflow_I_sum = 0
  350. outflow_II_sum = 0
  351. outflow_D_last = 0
  352.  
  353. state = "Standby"
  354. shutting_down = false
  355.  
  356. if condition.temperature > 25 then
  357.   state = "Cooling"
  358. end
  359. if condition.temperature > 2000 then
  360.   state = "Active"
  361. end
  362.  
  363.  -- Possible states:
  364.   --Standby
  365.   --Charging
  366.   --Active
  367.   --Manual Shutdown
  368.   --Emergency Shutdown
  369.   --Cooling
  370.  
  371. event_loop = true
  372. while event_loop do
  373.  
  374.   if not component.isAvailable("draconic_reactor") then
  375.     exit_msg("Reactor disconnected, exiting")
  376.   end
  377.  
  378.   if not component.isAvailable("flux_gate") then
  379.     exit_msg("Flux gates disconnected, exiting")
  380.   end
  381.  
  382.     local info = reactor.getReactorInfo()
  383.  
  384.  -- Highest Heat Value
  385.  
  386. if info.temperature > highest_temp then
  387.   highest_temp = info.temperature
  388. end
  389.  
  390.  -- Highest Sat Value
  391.  
  392. if ((info.energySaturation / info.maxEnergySaturation) * 100) > highest_sat then
  393.   highest_sat = ((info.energySaturation / info.maxEnergySaturation) * 100)
  394. end
  395.  
  396.  -- Lowest Field Value ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  397.  
  398. if ((info.fieldStrength / info.maxFieldStrength) * 100) < lowest_field then
  399.   lowest_field = ((info.fieldStrength / info.maxFieldStrength) * 100)
  400. end
  401.  
  402.  -- Lowest Field Value
  403.  
  404. if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < lowest_fuel then
  405.   lowest_fuel = ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  406. end
  407.  
  408.   local inflow = 0
  409.   local outflow = 0
  410.  
  411.   shutting_down = state == "Manual Shutdown" or state == "Emergency Shutdown"
  412.   running = state == "Charging" or state == "Active"
  413.   safe = state == "Standby" or state == "Cooling"
  414.  
  415.   if state == "Charging" then
  416.     inflow = 5000000
  417.  
  418.     if info.temperature > 2000 then
  419.       reactor.activateReactor()
  420.       state = "Active"
  421.     end
  422.   elseif state == "Cooling" then
  423.     if info.temperature < 25 then
  424.       state = "Standby"
  425.     end
  426.     inflow = 10
  427.     outflow = 20
  428.   elseif state == "Standby" then
  429.     inflow = 10
  430.     outflow = 20
  431.   else
  432.     -- adjust inflow rate based on field strength
  433.    
  434.     local field_error = (info.maxFieldStrength * (ideal_strength / 100)) - info.fieldStrength
  435.     local proportional_field_error = field_error * inflow_P_gain
  436.     inflow_I_sum = inflow_I_sum + field_error
  437.     local integral_field_error = inflow_I_sum * inflow_I_gain
  438.     local derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
  439.     inflow_D_last = field_error
  440.     local inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
  441.     if inflow_correction < 0 then
  442.       inflow_I_sum = inflow_I_sum - field_error
  443.     end
  444.     inflow = inflow_correction
  445.  
  446.     if not shutting_down then
  447.  
  448.       -- adjust outflow rate based on core temperature
  449.  
  450.       local temp_error = ideal_temp - info.temperature
  451.       local proportional_temp_error = temp_error * outflow_P_gain
  452.       outflow_I_sum = outflow_I_sum + temp_error
  453.       local integral_temp_error = outflow_I_sum * outflow_I_gain
  454.       if math.abs(temp_error) < 100 then
  455.         outflow_II_sum = outflow_II_sum + integral_temp_error
  456.       else
  457.         outflow_II_sum = 0
  458.       end
  459.       local second_integral_temp_error = outflow_II_sum * outflow_II_gain
  460.       local derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
  461.       outflow_D_last = temp_error
  462.       local outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
  463.       if outflow_correction < 0 then
  464.         outflow_I_sum = outflow_I_sum - temp_error
  465.       end
  466.       outflow = outflow_correction
  467.  
  468.       -- cut off reactor in case of emergency
  469.  
  470.       if info.temperature > cutoff_temp then
  471.         print("Reactor Too Hot, shutting down")
  472.         outflow = 0
  473.         new_strength = 55
  474.         cutoff_temp = 10001
  475.         state = "Emergency Shutdown"
  476.         status = "HiTe"
  477.         reactor.stopReactor()
  478.       end
  479.       if ((info.fieldStrength / info.maxFieldStrength) * 100) < 0.75 then
  480.         print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
  481.         outflow = 0
  482.         new_strength = 55
  483.         cutoff_temp = 10001
  484.         state = "Emergency Shutdown"
  485.         status = "LoFi"
  486.         reactor.stopReactor()
  487.       end
  488.       if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 12 then
  489.         print("Reactor Fuel Low, Shutting Down")
  490.     cutoff_temp = 10500
  491.     ideal_temp = 8000
  492.     ideal_strength = 55
  493.     cutoff_field = 0.45
  494.       state = "Manual Shutdown"
  495.       reactor.stopReactor()
  496.       end
  497.     else
  498.       if info.temperature < 2000 then
  499.         state = "Cooling"
  500.       end
  501.     end
  502.   end
  503.  
  504.   if state ~= "Active" and not shutting_down then
  505.     inflow_I_sum = 0
  506.     inflow_D_last = 0
  507.     outflow_I_sum = 0
  508.     outflow_II_sum = 0
  509.     outflow_D_last = 0
  510.   end
  511.  
  512.   if inflow < 0 then
  513.     inflow = 0
  514.   end
  515.   if outflow < 0 then
  516.     outflow = 0
  517.   end
  518.  
  519.   inflow = math.floor(inflow)
  520.   outflow = math.floor(outflow)
  521.  
  522.   flux_in.setFlowOverride(inflow)
  523.   flux_out.setFlowOverride(outflow)
  524.  
  525.   -- Draw screen
  526.  
  527.   if term.isAvailable() then
  528.  
  529.     -- Draw Values
  530.  
  531.     local left_margin = 2
  532.     local spacing = 2
  533.  
  534.     local values = {
  535.       "Ideal Field Strength: " .. ideal_strength .. "%",
  536.       "Field Strength:       " .. ((info.fieldStrength / info.maxFieldStrength) * 100) .. "%",
  537.       "Energy Saturation:    " .. ((info.energySaturation / info.maxEnergySaturation) * 100) .. "%",
  538.       "Fuel Remaining:       " .. ((1 - info.fuelConversion / info.maxFuelConversion) * 100) .. "%",
  539.       "Fuel Usage Rate:      " .. info.fuelConversionRate .. " nb/t",
  540.       "Ideal Temperature:    " .. ideal_temp .. "c",
  541.       "Temperature:          " .. info.temperature .. "c",
  542.       "Energy Inflow Rate:   " .. inflow .. " RF/t",
  543.       "Energy Outflow Rate:  " .. outflow .. " RF/t",
  544.       "True Output:          " .. (outflow - inflow) .. " RF/t",
  545.       "Energy Efficiency:    " .. ((outflow / inflow) * 100) .. "%",
  546.       "                      ",
  547.       "         Debugging Values         ",
  548.       "Lowest Field:         " .. lowest_field .. "%",
  549.       "Lowest Fuel:          " .. lowest_fuel .. "%",
  550.       "Highest Saturation:   " .. highest_sat .. "%",
  551.       "Highest Temp:         " .. highest_temp .. "c",
  552.       "Status:               " .. state .. ":" .. status
  553.     }
  554.  
  555.     if safe then
  556.       values[#values+1] = "Click if flux gates need to be swapped"
  557.     end
  558.  
  559.     term.clear()
  560.    
  561.     for i, v in ipairs(values) do
  562.       term.setCursor(left_margin, i * spacing)
  563.       term.write(v)
  564.     end
  565.  
  566.     -- Draw button values
  567.  
  568.     term.setCursor(temp_adjust_x_offset, temp_adjust_y_offset+10)
  569.     term.write("Reactor Temperature")
  570.     term.setCursor(field_adjust_x_offset+1, field_adjust_y_offset+10)
  571.     term.write("Field Strength")
  572.  
  573.     -- Draw Buttons
  574.  
  575.     gpu.setForeground(0x000000)
  576.  
  577.     for bname, button in pairs(buttons) do
  578.       if button.depressed then
  579.  
  580.         button.depressed = button.depressed - 1
  581.         if button.depressed == 0 then
  582.           button.depressed = nil
  583.         end
  584.       end
  585.       if button.condition == nil or button.condition() then
  586.         local center_color = 0xAAAAAA
  587.         local highlight_color = 0xCCCCCC
  588.         local lowlight_color = 0x808080
  589.         if button.depressed then
  590.           center_color = 0x999999
  591.           highlight_color = 0x707070
  592.           lowlight_color = 0xBBBBBB
  593.         end
  594.         gpu.setBackground(center_color)
  595.         gpu.fill(button.x, button.y, button.width, button.height, " ")
  596.         if button.width > 1 and button.height > 1 then
  597.           gpu.setBackground(lowlight_color)
  598.           gpu.fill(button.x+1, button.y+button.height-1, button.width-1, 1, " ")
  599.           gpu.fill(button.x+button.width-1, button.y, 1, button.height, " ")
  600.           gpu.setBackground(highlight_color)
  601.           gpu.fill(button.x, button.y, 1, button.height, " ")
  602.           gpu.fill(button.x, button.y, button.width, 1, " ")
  603.         end
  604.         gpu.setBackground(center_color)
  605.         term.setCursor(button.x + math.floor(button.width / 2 - #button.text / 2), button.y + math.floor(button.height / 2))
  606.         term.write(button.text)
  607.       end
  608.     end
  609.  
  610.     gpu.setBackground(0x000000)
  611.     gpu.setForeground(0xFFFFFF)
  612.   end  
  613.  
  614.   -- Wait for next tick, or manual shutdown
  615.  
  616.   local event, id, op1, op2 = event.pull(0.05)
  617.   if event == "interrupted" then
  618.     if safe then
  619.       break
  620.     end
  621.   elseif event == "touch" then
  622.    
  623.     -- Handle Button Presses
  624.  
  625.     local x = op1
  626.     local y = op2
  627.  
  628.     for bname, button in pairs(buttons) do
  629.       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
  630.         button.action()
  631.         button.depressed = 3
  632.       end
  633.     end
  634.   end
  635. end
  636.  
  637. term.clear()
Add Comment
Please, Sign In to add comment