neuroticfox

DraCon 5.0 [Experimental] (M-0.25-1-10-M)

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