neuroticfox

TestCon Tier 1

Jul 28th, 2021 (edited)
681
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.  
  37. function exit_msg(msg)
  38.   term.clear()
  39.   print(msg)
  40.   os.exit()
  41. end
  42.  
  43. function modify_temp(offset)
  44.   local new_temp = ideal_temp + offset
  45.   if new_temp > 8000 then
  46.     new_temp = 8000
  47.   elseif new_temp < 2000 then
  48.     new_temp = 2000
  49.   end
  50.   ideal_temp = new_temp
  51. end
  52.  
  53. local bypassfield = 0
  54. local chaosmode = 0
  55.  
  56. function modify_field(offset)
  57.   local new_strength = ideal_strength + offset
  58.   if new_strength > 100 then
  59.     new_strength = 100
  60.   elseif new_strength < 75 and chaosmode == 1 then
  61.     new_strength = 75
  62.   elseif new_strength < 1 and bypassfield == 0 then
  63.     new_strength = 1
  64.   elseif new_strength < 0.1 and bypassfield == 1 then
  65.     new_strength = 0.1
  66.   end
  67.   ideal_strength = new_strength
  68. end
  69.  
  70.  -- Buttons
  71.  
  72. local adj_button_width = 19
  73. local temp_adjust_x_offset = 68
  74. local temp_adjust_y_offset = 2
  75. local field_adjust_x_offset = temp_adjust_x_offset + adj_button_width + 2
  76. local field_adjust_y_offset = 2
  77. local status = "PeFi"
  78. local lowest_field = 100
  79. local lowest_fuel = 100
  80. local highest_temp = 0
  81. local highest_sat = 0
  82. local highest_outflow = 0
  83. local cutoff_field = 0.75
  84.  
  85.       -- Inflow PID
  86. local proportional_field_error = 0
  87. local inflow_I_sum = 0
  88. local integral_field_error = 0
  89. local derivative_field_error = 0
  90. local inflow_D_last = 0
  91. local inflow_correction = 0
  92.  
  93.     -- Outflow PID
  94. local proportional_temp_error = 0
  95. local outflow_I_sum = 0
  96. local integral_temp_error = 0
  97. local derivative_temp_error = 0
  98. local outflow_D_last = 0
  99. local outflow_correction = 0
  100. local newPow = 1
  101.  
  102.  
  103.  -- main code
  104.  
  105. flux_in.setFlowOverride(0)
  106. flux_out.setFlowOverride(0)
  107. flux_in.setOverrideEnabled(true)
  108. flux_out.setOverrideEnabled(true)
  109.  
  110. local condition = reactor.getReactorInfo()
  111. if not condition then
  112.   print("Reactor not initialized, please ensure the stabilizers are properly laid out.")
  113.   os.exit()
  114. end
  115.  
  116. ideal_strength = 15
  117.  
  118. ideal_temp = 8000
  119. cutoff_temp = 8001
  120.  
  121.  -- tweakable pid gains
  122.  
  123. inflow_P_gain = 1
  124. inflow_I_gain = 0.04
  125. inflow_D_gain = 0.05
  126.  
  127. outflow_P_gain = 500
  128. outflow_I_gain = 0.10
  129. outflow_II_gain = 0.0000003
  130. outflow_D_gain = 30000
  131.  
  132.  -- initialize main loop
  133.  
  134. inflow_I_sum = 0
  135. inflow_D_last = 0
  136.  
  137. outflow_I_sum = 0
  138. outflow_II_sum = 0
  139. outflow_D_last = 0
  140.  
  141. state = "Standby"
  142. shutting_down = false
  143.  
  144. if condition.temperature > 25 then
  145.   state = "Cooling"
  146. end
  147. if condition.temperature > 2000 then
  148.   state = "Active"
  149. end
  150.  
  151.  -- Possible states:
  152.   --Standby
  153.   --Charging
  154.   --Active
  155.   --Manual Shutdown
  156.   --Emergency Shutdown
  157.   --Cooling
  158.  
  159. event_loop = true
  160. while event_loop do
  161.  
  162.   if not component.isAvailable("draconic_reactor") then
  163.     exit_msg("Reactor disconnected, exiting")
  164.   end
  165.  
  166.   if not component.isAvailable("flux_gate") then
  167.     exit_msg("Flux gates disconnected, exiting")
  168.   end
  169.  
  170.     local info = reactor.getReactorInfo()
  171.  
  172.  -- Highest Heat Value
  173.  
  174. if info.temperature > highest_temp then
  175.   highest_temp = info.temperature
  176. end
  177.  
  178.  -- Highest Sat Value
  179.  
  180. if ((info.energySaturation / info.maxEnergySaturation) * 100) > highest_sat then
  181.   highest_sat = ((info.energySaturation / info.maxEnergySaturation) * 100)
  182. end
  183.  
  184.  -- Lowest Field Value ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  185.  
  186. if ((info.fieldStrength / info.maxFieldStrength) * 100) < lowest_field then
  187.   lowest_field = ((info.fieldStrength / info.maxFieldStrength) * 100)
  188. end
  189.  
  190.  -- Lowest Field Value
  191.  
  192. if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < lowest_fuel then
  193.   lowest_fuel = ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  194. end
  195.  
  196.  
  197. -- Key Press Control
  198. local keyps = {
  199. -- Start Button
  200. start={
  201.   action=function()
  202.     if key == keyboard.keys.q then
  203.     action=function()
  204.       cutoff_temp = 8001
  205.       ideal_temp = 8000
  206.       ideal_strength = 15
  207.       cutoff_field = 0.75
  208.     if safe then
  209.         state = "Charging"
  210.         reactor.chargeReactor()
  211.     elseif shutting_down then
  212.         state = "Active"
  213.         reactor.activateReactor()
  214.       end
  215.       end
  216.       end
  217.     end
  218.   },
  219.  
  220. chaosmode={
  221.     action=function()
  222.     if key == keyboard.keys.w then
  223.     action=function()
  224.         cutoff_temp = 19000
  225.         cutoff_field = 12.5
  226.         ideal_strength = 75
  227.         ideal_temp = 50000
  228.         chaosmode = 1
  229.     end
  230.     end
  231.     end
  232.   },
  233.  
  234. switch_gates={
  235.     action=function()
  236.     if key == keyboard.keys.e then
  237.       cutoff_temp = 10500
  238.       local old_addr = flux_in.address
  239.       flux_in = component.proxy(flux_out.address)
  240.       flux_out = component.proxy(old_addr)
  241.       end
  242.       condition=function() return safe
  243.       end
  244.     end
  245.   },
  246.  
  247. TempUp={
  248.     action=function()
  249.     if key == keyboard.keys.up then
  250.       action=function() modify_temp(100)
  251.       end
  252.       end
  253.     end
  254.   },
  255.  
  256. TempDown={
  257.     action=function()
  258.     if key == keyboard.keys.down then
  259.       action=function() modify_temp(-100)
  260.       end
  261.       end
  262.     end
  263.   },
  264.  
  265. FieldUp={
  266.     action=function()
  267.     if key == keyboard.keys.right then
  268.       action=function() modify_field(10)
  269.       end
  270.       end
  271.     end
  272.   },
  273.  
  274. FieldDown={
  275.     action=function()
  276.     if key == keyboard.keys.left then
  277.       action=function() modify_field(-10)
  278.       end
  279.       end
  280.     end
  281.   },
  282. }
  283.  
  284.  
  285.   local inflow = 0
  286.   local outflow = 0
  287.  
  288.   shutting_down = state == "Manual Shutdown" or state == "Emergency Shutdown"
  289.   running = state == "Charging" or state == "Active"
  290.   safe = state == "Standby" or state == "Cooling"
  291.  
  292.   if state == "Charging" then
  293.     inflow = 5000000
  294.  
  295.     if info.temperature > 2000 then
  296.       reactor.activateReactor()
  297.       state = "Active"
  298.     end
  299.   elseif state == "Cooling" then
  300.     if info.temperature < 25 then
  301.       state = "Standby"
  302.     end
  303.     inflow = 10
  304.     outflow = 20
  305.   elseif state == "Standby" then
  306.     inflow = 10
  307.     outflow = 20
  308.   else
  309.     -- adjust inflow rate based on field strength
  310.    
  311.     field_error = (info.maxFieldStrength * (ideal_strength / 100)) - info.fieldStrength
  312.     proportional_field_error = field_error * inflow_P_gain
  313.     inflow_I_sum = inflow_I_sum + field_error
  314.     integral_field_error = inflow_I_sum * inflow_I_gain
  315.     derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
  316.     inflow_D_last = field_error
  317.     inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
  318.     if inflow_correction < 0 then
  319.       inflow_I_sum = inflow_I_sum - field_error
  320.     end
  321.     inflow = inflow_correction
  322.  
  323.     if not shutting_down then
  324.  
  325.       -- adjust outflow rate based on core temperature
  326.  
  327.       temp_error = ideal_temp - info.temperature
  328.       proportional_temp_error = temp_error * outflow_P_gain
  329.       outflow_I_sum = outflow_I_sum + temp_error
  330.       integral_temp_error = outflow_I_sum * outflow_I_gain
  331.       if math.abs(temp_error) < 100 then
  332.         outflow_II_sum = outflow_II_sum + integral_temp_error
  333.       else
  334.         outflow_II_sum = 0
  335.       end
  336.       second_integral_temp_error = outflow_II_sum * outflow_II_gain
  337.       derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
  338.       outflow_D_last = temp_error
  339.       outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
  340.       if outflow_correction < 0 then
  341.         outflow_I_sum = outflow_I_sum - temp_error
  342.       end
  343.       outflow = outflow_correction
  344.  
  345.       -- cut off reactor in case of emergency
  346.  
  347.       if info.temperature > cutoff_temp then
  348.         print("Reactor Too Hot, shutting down")
  349.         state = "Emergency Shutdown"
  350.         reactor.stopReactor()
  351.       end
  352.       if ((info.fieldStrength / info.maxFieldStrength) * 100) < cutoff_field then
  353.         print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
  354.         state = "Emergency Shutdown"
  355.         reactor.stopReactor()
  356.       end
  357.       if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 5 then
  358.         print("Reactor Fuel Low, Shutting Down")
  359.       state = "Emergency Shutdown"
  360.       reactor.stopReactor()
  361.       end
  362.     else
  363.       if info.temperature < 2000 then
  364.         state = "Cooling"
  365.       end
  366.     end
  367.   end
  368.  
  369.   if state ~= "Active" and not shutting_down then
  370.     inflow_I_sum = 0
  371.     inflow_D_last = 0
  372.     outflow_I_sum = 0
  373.     outflow_II_sum = 0
  374.     outflow_D_last = 0
  375.   end
  376.  
  377.   if inflow < 0 then
  378.     inflow = 0
  379.   end
  380.   if outflow < 0 then
  381.     outflow = 0
  382.   end
  383.  
  384.   inflow = math.floor(inflow)
  385.   outflow = math.floor(outflow)
  386.  
  387.   flux_in.setFlowOverride(inflow)
  388.   flux_out.setFlowOverride(outflow)
  389.  
  390.   -- Draw screen
  391.  
  392.   if term.isAvailable() then
  393.  
  394.     -- Draw Values
  395.  
  396. function modify_eff(offset)
  397.   local eff = ((outflow / inflow) * 100)
  398.   if eff > 100000 then
  399.     eff = 1
  400.   end
  401. end
  402.  
  403.     local secondsToExpire = (info.maxFuelConversion - info.fuelConversion) / math.max(info.fuelConversionRate*0.00002, 0.00001)
  404.  
  405.     local left_margin = 1
  406.     local spacing = 1
  407.     local values = {
  408. string.format("ETA %2dd, %2dh, %2dm, %2ds", secondsToExpire/86400, secondsToExpire/3600 % 24, secondsToExpire/60 % 60, secondsToExpire % 60),
  409. string.format("Field:  %7.1f%%", ((info.fieldStrength / info.maxFieldStrength) * 100)),
  410. string.format("Fuel:   %7.1f%%", ((1 - info.fuelConversion / info.maxFuelConversion) * 100)),
  411. string.format("Temper: %7.1f°c", info.temperature),
  412. string.format("Temper: %7.1f°c", ideal_temp),
  413. string.format("Energy: %7.0fRF/t", outflow),
  414.               "State:  " .. state .. "",
  415. }
  416.     term.clear()
  417.    
  418.     for i, v in ipairs(values) do
  419.       term.setCursor(left_margin, i * spacing)
  420.       term.write(v)
  421.     end
  422.  
  423.     -- Draw button values
  424.       end
  425.     end
  426. term.clear()
RAW Paste Data