neuroticfox

DraCon 6.0

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