neuroticfox

TestCon Tier 1

Jul 28th, 2021 (edited)
977
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.45 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. local screen = component.screen
  6.  
  7.  -- DynamicRes
  8.  
  9. local ratioX, ratioY = screen.getAspectRatio()
  10. local maxX, maxY = gpu.maxResolution()
  11. gpu.setResolution(math.min(ratioX*55, maxX), math.min(ratioY*25,maxY))
  12.  
  13.  -- Safety Checks
  14.  
  15. if not component.isAvailable("draconic_reactor") then
  16.   print("Reactor not connected. Please connect computer to reactor with an Adapter block.")
  17.   os.exit()
  18. end
  19. reactor = component.draconic_reactor
  20. local flux_gates = {}
  21. for x,y in pairs(component.list("flux_gate")) do
  22.   flux_gates[#flux_gates+1] = x
  23. end
  24. if #flux_gates < 2 then
  25.   print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  26.   os.exit()
  27. end
  28. flux_in = component.proxy(flux_gates[1])
  29. flux_out = component.proxy(flux_gates[2])
  30. if not flux_in or not flux_out then
  31.   print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  32.   os.exit()
  33. end
  34.  
  35.  -- Functions
  36. function exit_msg(msg)
  37.   term.clear()
  38.   print(msg)
  39.   os.exit()
  40. end
  41.  
  42. function modify_temp(offset)
  43.   local new_temp = ideal_temp + offset
  44.   if new_temp > 8000 then
  45.     new_temp = 8000
  46.   elseif new_temp < 2000 then
  47.     new_temp = 2000
  48.   end
  49.   ideal_temp = new_temp
  50. end
  51.  
  52. local bypassfield = 0
  53. local chaosmode = 0
  54.  
  55. function modify_field(offset)
  56.   local new_strength = ideal_strength + offset
  57.   if new_strength > 100 then
  58.     new_strength = 100
  59.   elseif new_strength < 25 and chaosmode == 1 then
  60.     new_strength = 25
  61.   elseif new_strength < 1 then
  62.     new_strength = 1
  63.   end
  64.   ideal_strength = new_strength
  65. end
  66.  
  67.  -- Buttons
  68.  
  69.  
  70. local adj_button_width = 19
  71. local temp_adjust_x_offset = 62
  72. local temp_adjust_y_offset = 2
  73. local field_adjust_x_offset = temp_adjust_x_offset + adj_button_width + 2
  74. local field_adjust_y_offset = 2
  75. local status = "PeFi"
  76. local lowest_field = 100
  77. local lowest_fuel = 100
  78. local highest_temp = 0
  79. local highest_sat = 0
  80. local highest_outflow = 0
  81. local cutoff_field = 0.05
  82.  
  83.       -- Inflow PID
  84. local proportional_field_error = 0
  85. local inflow_I_sum = 0
  86. local integral_field_error = 0
  87. local derivative_field_error = 0
  88. local inflow_D_last = 0
  89. local inflow_correction = 0
  90.  
  91.     -- Outflow PID
  92. local proportional_temp_error = 0
  93. local outflow_I_sum = 0
  94. local integral_temp_error = 0
  95. local derivative_temp_error = 0
  96. local outflow_D_last = 0
  97. local outflow_correction = 0
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106. local buttons = {
  107.   start={
  108.     x=2,
  109.     y=19,
  110.     width=18,
  111.     height=1,
  112.     text="Start",
  113.     action=function()
  114.       if safe then
  115.         state = "Charging"
  116.         reactor.chargeReactor()
  117.       elseif shutting_down then
  118.         state = "Active"
  119.         ideal_strength = 5
  120.         chaosmode = 0
  121.         reactor.activateReactor()
  122.       end
  123.     end,
  124.     condition=function() return safe or shutting_down end
  125.   },
  126.     shutdown={
  127.     x=22,
  128.     y=19,
  129.     width=18,
  130.     height=1,
  131.     text="Shutdown",
  132.     action=function()
  133.     cutoff_temp = 8001
  134.     ideal_temp = 8000
  135.     ideal_strength = 100
  136.     cutoff_field = 0.1
  137.     chaosmode = 0
  138.       state = "Manual Shutdown"
  139.       reactor.stopReactor()
  140.     end,
  141.     condition=function() return running end
  142.   },
  143.         chaosmode={
  144.     x=2,
  145.     y=19,
  146.     width=18,
  147.     height=1,
  148.     text=" Chaos Mode",
  149.     action=function()
  150.         if chaosmode == 0 then
  151.             chaosmode = 1
  152.             cutoff_temp = 19750
  153.             ideal_strength = 25
  154.             cutoff_field = 5
  155.             ideal_temp = 69420
  156.             lowest_field = 100
  157.         elseif chaosmode == 1 then
  158.             chaosmode = 0
  159.             ideal_strength = 5
  160.             cutoff_field = 0.5
  161.             ideal_temp = 8000
  162.             lowest_field = 100
  163.         end
  164.     end,
  165.     condition=function() return running end
  166.   },
  167.     switch_gates={
  168.     x=22,
  169.     y=19,
  170.     width=18,
  171.     height=1,
  172.     text="Swap flux gates",
  173.     action=function()
  174.       cutoff_temp = 8100
  175.       local old_addr = flux_in.address
  176.       flux_in = component.proxy(flux_out.address)
  177.       flux_out = component.proxy(old_addr)
  178.     end,
  179.     condition=function() return safe end
  180.   }
  181. }
  182.  
  183.  -- main code
  184.  
  185. flux_in.setFlowOverride(0)
  186. flux_out.setFlowOverride(0)
  187. flux_in.setOverrideEnabled(true)
  188. flux_out.setOverrideEnabled(true)
  189.  
  190. local condition = reactor.getReactorInfo()
  191. if not condition then
  192.   print("Reactor not initialized, please ensure the stabilizers are properly laid out.")
  193.   os.exit()
  194. end
  195.  
  196. ideal_strength = 5
  197.  
  198. ideal_temp = 8000
  199. cutoff_temp = 8100
  200.  
  201.  -- tweakable pid gains
  202.  
  203. inflow_P_gain = 1
  204. inflow_I_gain = 0.04
  205. inflow_D_gain = 0.05
  206.  
  207. outflow_P_gain = 500
  208. outflow_I_gain = 0.10
  209. outflow_II_gain = 0.0000003
  210. outflow_D_gain = 30000
  211.  
  212.  -- initialize main loop
  213.  
  214. inflow_I_sum = 0
  215. inflow_D_last = 0
  216.  
  217. outflow_I_sum = 0
  218. outflow_II_sum = 0
  219. outflow_D_last = 0
  220.  
  221. state = "Standby"
  222. shutting_down = false
  223.  
  224. if condition.temperature > 25 then
  225.   state = "Cooling"
  226. end
  227. if condition.temperature > 2000 then
  228.   state = "Active"
  229. end
  230.  
  231.  -- Possible states:
  232.   --Standby
  233.   --Charging
  234.   --Active
  235.   --Manual Shutdown
  236.   --Emergency Shutdown
  237.   --Cooling
  238.  
  239. event_loop = true
  240. while event_loop do
  241.  
  242.   if not component.isAvailable("draconic_reactor") then
  243.     exit_msg("Reactor disconnected, exiting")
  244.   end
  245.  
  246.   if not component.isAvailable("flux_gate") then
  247.     exit_msg("Flux gates disconnected, exiting")
  248.   end
  249.  
  250.     local info = reactor.getReactorInfo()
  251.  
  252.  -- Highest Heat Value
  253.  
  254. if info.temperature > highest_temp then
  255.   highest_temp = info.temperature
  256. end
  257.  
  258.  -- Highest Sat Value
  259.  
  260. if ((info.energySaturation / info.maxEnergySaturation) * 100) > highest_sat then
  261.   highest_sat = ((info.energySaturation / info.maxEnergySaturation) * 100)
  262. end
  263.  
  264.  -- Lowest Field Value ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  265.  
  266. if ((info.fieldStrength / info.maxFieldStrength) * 100) < lowest_field then
  267.   lowest_field = ((info.fieldStrength / info.maxFieldStrength) * 100)
  268. end
  269.  
  270.  -- Lowest Field Value
  271.  
  272. if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < lowest_fuel then
  273.   lowest_fuel = ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  274. end
  275.  
  276.   local inflow = 0
  277.   local outflow = 0
  278.  
  279.   shutting_down = state == "Manual Shutdown" or state == "Emergency Shutdown"
  280.   running = state == "Charging" or state == "Active"
  281.   safe = state == "Standby" or state == "Cooling"
  282.  
  283.   if state == "Charging" then
  284.     inflow = 5000000
  285.  
  286.     if info.temperature > 2000 then
  287.       reactor.activateReactor()
  288.       state = "Active"
  289.     end
  290.   elseif state == "Cooling" then
  291.     if info.temperature < 25 then
  292.       state = "Standby"
  293.     end
  294.     inflow = 10
  295.     outflow = 20
  296.   elseif state == "Standby" then
  297.     inflow = 10
  298.     outflow = 20
  299.   else
  300.     -- adjust inflow rate based on field strength
  301.  
  302.     field_error = (info.maxFieldStrength * (ideal_strength / 100)) - info.fieldStrength
  303.     proportional_field_error = field_error * inflow_P_gain
  304.     inflow_I_sum = inflow_I_sum + field_error
  305.     integral_field_error = inflow_I_sum * inflow_I_gain
  306.     derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
  307.     inflow_D_last = field_error
  308.     inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
  309.     if inflow_correction < 0 then
  310.       inflow_I_sum = inflow_I_sum - field_error
  311.     end
  312.     inflow = inflow_correction
  313.  
  314.     if not shutting_down then
  315.  
  316.       -- adjust outflow rate based on core temperature
  317.  
  318.       temp_error = ideal_temp - info.temperature
  319.       proportional_temp_error = temp_error * outflow_P_gain
  320.       outflow_I_sum = outflow_I_sum + temp_error
  321.       integral_temp_error = outflow_I_sum * outflow_I_gain
  322.       if math.abs(temp_error) < 100 then
  323.         outflow_II_sum = outflow_II_sum + integral_temp_error
  324.       else
  325.         outflow_II_sum = 0
  326.       end
  327.       second_integral_temp_error = outflow_II_sum * outflow_II_gain
  328.       derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
  329.       outflow_D_last = temp_error
  330.       outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
  331.       if outflow_correction < 0 then
  332.         outflow_I_sum = outflow_I_sum - temp_error
  333.       end
  334.       outflow = outflow_correction
  335.  
  336.       -- cut off reactor in case of emergency
  337.  
  338.       if info.temperature > cutoff_temp then
  339.         print("Reactor Too Hot, shutting down")
  340.         state = "Emergency Shutdown"
  341.         status = "HiTe"
  342.         reactor.stopReactor()
  343.       end
  344.       if ((info.fieldStrength / info.maxFieldStrength) * 100) < cutoff_field then
  345.         print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
  346.         state = "Emergency Shutdown"
  347.         status = "LoFi"
  348.         reactor.stopReactor()
  349.       end
  350.       if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 1.25 then
  351.         print("Reactor Fuel Low, Shutting Down")
  352.       state = "Emergency Shutdown"
  353.       status = "LoFu"
  354.       reactor.stopReactor()
  355.       end
  356.     else
  357.       if info.temperature < 2000 then
  358.         state = "Cooling"
  359.       end
  360.     end
  361.   end
  362.  
  363.   if state ~= "Active" and not shutting_down then
  364.     inflow_I_sum = 0
  365.     inflow_D_last = 0
  366.     outflow_I_sum = 0
  367.     outflow_II_sum = 0
  368.     outflow_D_last = 0
  369.   end
  370.  
  371.   if inflow < 0 then
  372.     inflow = 0
  373.   end
  374.   if outflow < 0 then
  375.     outflow = 0
  376.   end
  377.  
  378.   inflow = math.floor(inflow)
  379.   outflow = math.floor(outflow)
  380.  
  381.   flux_in.setFlowOverride(inflow)
  382.   flux_out.setFlowOverride(outflow)
  383.  
  384.   -- Draw screen
  385.  
  386.   if term.isAvailable() then
  387.  
  388.     -- Draw Values
  389.  
  390. function modify_eff(offset)
  391.   local eff = ((outflow / inflow) * 100)
  392.   if eff > 100000 then
  393.     eff = 1
  394.   end
  395. end
  396.  
  397.     local secondsToExpire = (info.maxFuelConversion - info.fuelConversion) / math.max(info.fuelConversionRate*0.00002, 0.00001)
  398.  
  399.     local left_margin = 2
  400.     local spacing = 1
  401.     local values = {
  402.               "- v1b [5ZSvUzx7]",
  403.               " ",
  404.               "                  Reactor Statistics",
  405.               "-----------------------------------------------------",
  406. string.format("Time Until Refuel:          |   %3dd, %2dh, %2dm, %2ds    ", secondsToExpire/86400, secondsToExpire/3600 % 24, secondsToExpire/60 % 60, secondsToExpire % 60),
  407. string.format("Ideal Field:                |   %5.1f%%           ", ideal_strength),
  408. string.format("Current Field:              | %7.1f%%                   ", ((info.fieldStrength / info.maxFieldStrength) * 100), ((info.fieldStrength / info.maxFieldStrength) * 100000000)),
  409.               "----------------------------|------------------------",
  410. string.format("Fuel Remaining:             |    %5.1f%%", ((1 - info.fuelConversion / info.maxFuelConversion) * 100)),
  411. string.format("Fuel Use Rate:              | %9.1f nb/t      ", info.fuelConversionRate),
  412.               "----------------------------|------------------------",
  413. string.format("Temperature                 |   %7.1f°c            ", info.temperature),
  414. string.format("Ideal Temperature:          |   %7.1f°c            ", ideal_temp),
  415.               "----------------------------|------------------------",
  416. string.format("Energy Input:               | %12.1f RF/t       ", inflow),
  417. string.format("Energy Output:              | %12.1f RF/t        ", outflow),
  418. string.format("Energy Profit:              | %12.1f RF/t      ", (outflow - inflow)),
  419.               "-----------------------------------------------------",
  420. }
  421.  
  422.  
  423.     term.clear()
  424.  
  425.     for i, v in ipairs(values) do
  426.       term.setCursor(left_margin, i * spacing)
  427.       term.write(v)
  428.     end
  429.  
  430.     -- Draw Buttons
  431.  
  432.     gpu.setForeground(0x000000)
  433.  
  434.     for bname, button in pairs(buttons) do
  435.       if button.depressed then
  436.  
  437.         button.depressed = button.depressed - 1
  438.         if button.depressed == 0 then
  439.           button.depressed = nil
  440.         end
  441.       end
  442.       if button.condition == nil or button.condition() then
  443.         local center_color = 0xAAAAAA
  444.         local highlight_color = 0xCCCCCC
  445.         local lowlight_color = 0x808080
  446.         if button.depressed then
  447.           center_color = 0x999999
  448.           highlight_color = 0x707070
  449.           lowlight_color = 0xBBBBBB
  450.         end
  451.         gpu.setBackground(center_color)
  452.         gpu.fill(button.x, button.y, button.width, button.height, " ")
  453.         if button.width > 1 and button.height > 1 then
  454.           gpu.setBackground(lowlight_color)
  455.           gpu.fill(button.x+1, button.y+button.height-1, button.width-1, 1, " ")
  456.           gpu.fill(button.x+button.width-1, button.y, 1, button.height, " ")
  457.           gpu.setBackground(highlight_color)
  458.           gpu.fill(button.x, button.y, 1, button.height, " ")
  459.           gpu.fill(button.x, button.y, button.width, 1, " ")
  460.         end
  461.         gpu.setBackground(center_color)
  462.         term.setCursor(button.x + math.floor(button.width / 2 - #button.text / 2), button.y + math.floor(button.height / 2))
  463.         term.write(button.text)
  464.       end
  465.     end
  466.  
  467.     gpu.setBackground(0x000000)
  468.     gpu.setForeground(0xFFFFFF)
  469.   end
  470.  
  471.   -- Wait for next tick, or manual shutdown
  472.  
  473.   local event, id, op1, op2 = event.pull(0.05)
  474.   if event == "interrupted" then
  475.     if safe then
  476.       break
  477.     end
  478.   elseif event == "touch" then
  479.  
  480.     -- Handle Button Presses
  481.  
  482.     local x = op1
  483.     local y = op2
  484.  
  485.     for bname, button in pairs(buttons) do
  486.       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
  487.         button.action()
  488.         button.depressed = 3
  489.       end
  490.     end
  491.   end
  492.   os.sleep()
  493. end
  494.  
  495. term.clear()
Add Comment
Please, Sign In to add comment