Advertisement
Kohjen

Untitled

Jul 24th, 2024 (edited)
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 31.06 KB | None | 0 0
  1. local tag = "reactorConfig"
  2. version = "0.50"
  3. --[[
  4. Program made by DrunkenKas
  5.     See github: https://github.com/Kasra-G/ReactorController/#readme
  6.  
  7. The MIT License (MIT)
  8.  
  9. Copyright (c) 2021 Kasra Ghaffari
  10.  
  11. Permission is hereby granted, free of charge, to any person obtaining a copy
  12. of this software and associated documentation files (the "Software"), to deal
  13. in the Software without restriction, including without limitation the rights
  14. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. copies of the Software, and to permit persons to whom the Software is
  16. furnished to do so, subject to the following conditions:
  17.  
  18. The above copyright notice and this permission notice shall be included in
  19. all copies or substantial portions of the Software.
  20.  
  21. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27. THE SOFTWARE.
  28. ]]
  29. local reactorType
  30. local mon, monSide, reactorSide
  31. local sizex, sizey, dim, oo, offy
  32. local btnOn, btnOff, invalidDim
  33. local minb, maxb, minrod
  34. local rod, rfLost
  35. local storedLastTick, storedThisTick, lastRFT, maxRFT = 0,0,0,1
  36. local fuelTemp, caseTemp, fuelUsage, waste, capacity = 0,0,0,0,0
  37. local t
  38. local displayingGraphMenu = false
  39. local calibrated = false
  40.  
  41. local secondsToAverage = 2
  42.  
  43. local averageStoredThisTick = 0
  44. local averageLastRFT = 0
  45. local averageRod = 0
  46. local averageFuelUsage = 0
  47. local averageWaste = 0
  48. local averageFuelTemp = 0
  49. local averageCaseTemp = 0
  50. local averageRfLost = 0
  51.  
  52. local activelyCooled = false
  53.  
  54. --table of which graphs to draw
  55. local graphsToDraw = {}
  56.  
  57. --table of all the graphs
  58. local graphs =
  59. {
  60.     "Energy Buffer",
  61.     "Control Level",
  62.     "Temperatures",
  63. }
  64.  
  65. --marks the offsets for each graph position
  66. local XOffs =
  67. {
  68.     { 4, true},
  69.     {27, true},
  70.     {50, true},
  71.     {73, true},
  72.     {96, true},
  73. }
  74.  
  75. --Draw a single point
  76. local function drawPoint(x, y, color)
  77.     if (monSide ~= nil) then
  78.         local ix,iy = mon.getCursorPos()
  79.         mon.setCursorPos(x,y)
  80.         mon.setBackgroundColor(color)
  81.         mon.write(" ")
  82.         mon.setBackgroundColor(colors.black)
  83.         mon.setCursorPos(ix,iy)
  84.     end
  85. end
  86.  
  87. --Draw a box with no fill
  88. local function drawBox(size, xoff, yoff, color)
  89.     if (monSide ~= nil) then
  90.         local x,y = mon.getCursorPos()
  91.         mon.setBackgroundColor(color)
  92.         for i=0,size[1] - 1 do
  93.             mon.setCursorPos(xoff + i + 1, yoff + 1)
  94.             mon.write(" ")
  95.             mon.setCursorPos(xoff + i + 1, yoff + size[2])
  96.             mon.write(" ")
  97.         end
  98.         for i=0, size[2] - 1 do
  99.             mon.setCursorPos(xoff + 1, yoff + i + 1)
  100.             mon.write(" ")
  101.             mon.setCursorPos(xoff + size[1], yoff + i +1)
  102.             mon.write(" ")
  103.         end
  104.         mon.setCursorPos(x,y)
  105.         mon.setBackgroundColor(colors.black)
  106.     end
  107. end
  108.  
  109. --Draw a filled box
  110. local function drawFilledBox(size, xoff, yoff, colorOut, colorIn)
  111.     if (monSide ~= nil) then
  112.         local horizLine = ""
  113.         for i=2, size[1] - 1 do
  114.             horizLine  = horizLine.." "
  115.         end
  116.         drawBox(size, xoff, yoff, colorOut)
  117.         local x,y = mon.getCursorPos()
  118.         mon.setBackgroundColor(colorIn)
  119.         for i=2, size[2] - 1 do
  120.             mon.setCursorPos(xoff + 2, yoff + i)
  121.             mon.write(horizLine)
  122.         end
  123.         mon.setBackgroundColor(colors.black)
  124.         mon.setCursorPos(x,y)
  125.     end
  126. end
  127.  
  128. --Draws text on the screen
  129. local function drawText(text, x1, y1, backColor, textColor)
  130.     if (monSide ~= nil) then
  131.         local x, y = mon.getCursorPos()
  132.         mon.setCursorPos(x1, y1)
  133.         mon.setBackgroundColor(backColor)
  134.         mon.setTextColor(textColor)
  135.         mon.write(text)
  136.         mon.setTextColor(colors.white)
  137.         mon.setBackgroundColor(colors.black)
  138.         mon.setCursorPos(x,y)
  139.     end
  140. end
  141.  
  142. --Helper method for adding buttons
  143. local function addButt(name, callBack, size, xoff, yoff, color1, color2)
  144.     if (monSide ~= nil) then
  145.         t:add(name, callBack,
  146.                 xoff + 1, yoff + 1,
  147.                 size[1] + xoff, size[2] + yoff,
  148.                 color1, color2)
  149.     end
  150. end
  151.  
  152. --adds buttons
  153. local function addButtons()
  154.     if (sizey == 24) then
  155.         oo = 1
  156.     end
  157.     addButt("On", nil, {8, 3}, dim + 7, 3 + oo,
  158.             colors.red, colors.lime)
  159.     addButt("Off", nil, {8, 3}, dim + 19, 3 + oo,
  160.             colors.red, colors.lime)
  161.     if (btnOn) then
  162.         t:toggleButton("On")
  163.     else
  164.         t:toggleButton("Off")
  165.     end
  166.     if (sizey > 24) then
  167.         addButt("+ 10", nil, {8, 3}, dim + 7, 14 + oo,
  168.                 colors.purple, colors.pink)
  169.         addButt(" + 10 ", nil, {8, 3}, dim + 19, 14 + oo,
  170.                 colors.magenta, colors.pink)
  171.         addButt("- 10", nil, {8, 3}, dim + 7, 18 + oo,
  172.                 colors.purple, colors.pink)
  173.         addButt(" - 10 ", nil, {8, 3}, dim + 19, 18 + oo,
  174.                 colors.magenta, colors.pink)
  175.     end
  176. end
  177.  
  178. --Resets the monitor
  179. local function resetMon()
  180.     if (monSide ~= nil) then
  181.         mon.setBackgroundColor(colors.black)
  182.         mon.clear()
  183.         mon.setTextScale(0.5)
  184.         mon.setCursorPos(1,1)
  185.     end
  186. end
  187.  
  188. local function getPercPower()
  189.     return averageStoredThisTick / capacity * 100
  190. end
  191.  
  192. local function rnd(num, dig)
  193.     return math.floor(10 ^ dig * num) / (10 ^ dig)
  194. end
  195.  
  196. local function getEfficiency()
  197.     return averageLastRFT / averageFuelUsage
  198. end
  199.  
  200. local function getGenRatio()
  201.     return lastRFT / capacity
  202. end
  203.  
  204. local function format(num)
  205.     if (num >= 1000000000) then
  206.         return string.format("%7.3f G", num / 1000000000)
  207.     elseif (num >= 1000000) then
  208.         return string.format("%7.3f M", num / 1000000)
  209.     elseif (num >= 1000) then
  210.         return string.format("%7.3f K", num / 1000)
  211.     elseif (num >= 1) then
  212.         return string.format("%7.3f ", num)
  213.     elseif (num >= .001) then
  214.         return string.format("%7.3f m", num * 1000)
  215.     elseif (num >= .000001) then
  216.         return string.format("%7.3f u", num * 1000000)
  217.     else
  218.         return string.format("%7.3f ", 0)
  219.     end
  220. end
  221.  
  222. local function getAvailableXOff()
  223.     for i,v in pairs(XOffs) do
  224.         if (v[2] and v[1] < dim) then
  225.             v[2] = false
  226.             return v[1]
  227.         end
  228.     end
  229.     return -1
  230. end
  231.  
  232. local function getXOff(num)
  233.     for i,v in pairs(XOffs) do
  234.         if (v[1] == num) then
  235.             return v
  236.         end
  237.     end
  238.     return nil
  239. end
  240.  
  241. local function disableGraph(name)
  242.     if (graphsToDraw[name] ~= nil) then
  243.         if (displayingGraphMenu) then
  244.             t:toggleButton(name)
  245.         end
  246.         getXOff(graphsToDraw[name])[2] = true
  247.         graphsToDraw[name] = nil
  248.     end
  249. end
  250.  
  251. local function addGraphButtons()
  252.     offy = oo - 14
  253.     for i,v in pairs(graphs) do
  254.         addButt(v, nil, {20, 3},
  255.                 dim + 7, offy + i * 3 - 1,
  256.                 colors.red, colors.lime)
  257.         if (graphsToDraw[v] ~= nil) then
  258.             t:toggleButton(v)
  259.         end
  260.     end
  261. end
  262.  
  263. local function drawGraphButtons()
  264.     drawBox({sizex - dim - 3, oo - offy - 1},
  265.             dim + 2, offy, colors.orange)
  266.     drawText(" Graph Controls ",
  267.             dim + 7, offy + 1,
  268.             colors.black, colors.orange)
  269. end
  270.  
  271. local function isGraph(name)
  272.     for i,v in pairs(graphs) do
  273.         if (v == name) then
  274.             return true
  275.         end
  276.     end
  277.     return false
  278. end
  279.  
  280. local function getGraph(num)
  281.     for i,v in pairs(graphsToDraw) do
  282.         if (v == num) then
  283.             return i
  284.         end
  285.     end
  286.     return nil
  287. end
  288.  
  289. local function enableGraph(name)
  290.     if (graphsToDraw[name] == nil) then
  291.         local e = getAvailableXOff()
  292.         if (e ~= -1) then
  293.             graphsToDraw[name] = e
  294.             if (displayingGraphMenu) then
  295.                 t:toggleButton(name)
  296.             end
  297.         end
  298.     end
  299. end
  300.  
  301. local function toggleGraph(name)
  302.     if (graphsToDraw[name] == nil) then
  303.         enableGraph(name)
  304.     else
  305.         disableGraph(name)
  306.     end
  307. end
  308.  
  309. local function drawEnergyBuffer(xoff)
  310.     local srf = sizey - 9
  311.     local off = xoff
  312.     local right = off + 19 < dim
  313.     local poff = right and off + 15 or off - 6
  314.  
  315.     drawBox({15, srf + 2}, off - 1, 4, colors.gray)
  316.     local pwr = math.floor(getPercPower() / 100
  317.             * (srf))
  318.     drawFilledBox({13, srf}, off, 5,
  319.             colors.red, colors.red)
  320.     local rndpw = rnd(getPercPower(), 2)
  321.     local color = (rndpw < maxb and rndpw > minb) and colors.green
  322.             or (rndpw >= maxb and colors.orange or colors.blue)
  323.     if (pwr > 0) then
  324.         drawFilledBox({13, pwr + 1}, off, srf + 4 - pwr,
  325.                 color, color)
  326.     end
  327.     --drawPoint(off + 14, srf + 5 - pwr, pwr > 0 and color or colors.red)
  328.     drawText(string.format(right and "%.2f%%" or "%5.2f%%", rndpw), poff, srf + 5 - pwr,
  329.             colors.black, color)
  330.     drawText("Energy Buffer", off + 1, 4,
  331.             colors.black, colors.orange)
  332.     drawText(format(averageStoredThisTick).."RF", off + 1, srf + 5 - pwr,
  333.             pwr > 0 and color or colors.red, colors.black)
  334. end
  335.  
  336. local function drawControlLevel(xoff)
  337.     local srf = sizey - 9
  338.     local off = xoff
  339.     drawBox({15, srf + 2}, off - 1, 4, colors.gray)
  340.     drawFilledBox({13, srf}, off, 5,
  341.             colors.yellow, colors.yellow)
  342.     local rodTr = math.floor(averageRod / 100
  343.             * (srf))
  344.     drawText("Control Level", off + 1, 4,
  345.             colors.black, colors.orange)
  346.     if (rodTr > 0) then
  347.         drawFilledBox({9, rodTr}, off + 2, 5,
  348.                 colors.white, colors.white)
  349.     end
  350.     drawText(string.format("%6.2f%%", averageRod), off + 4, rodTr > 0 and rodTr + 5 or 6,
  351.             rodTr > 0 and colors.white or colors.yellow, colors.black)
  352.  
  353. end
  354.  
  355. local function drawTemperatures(xoff)
  356.     local srf = sizey - 9
  357.     local off = xoff
  358.     drawBox({15, srf + 2}, off, 4, colors.gray)
  359.     --drawFilledBox({12, srf}, off, 5,
  360.     --  colors.red, colors.red)
  361.  
  362.     local tempUnit = (reactorVersion == "Bigger Reactors") and "K" or "C"
  363.     local tempFormat = "%4s"..tempUnit
  364.  
  365.     local fuelRnd = math.floor(averageFuelTemp)
  366.     local caseRnd = math.floor(averageCaseTemp)
  367.     local fuelTr = math.floor(fuelRnd / 2000
  368.             * (srf))
  369.     local caseTr = math.floor(caseRnd / 2000
  370.             * (srf))
  371.     drawText(" Case ", off + 2, 5,
  372.             colors.gray, colors.lightBlue)
  373.     drawText(" Fuel ", off + 9, 5,
  374.             colors.gray, colors.magenta)
  375.     if (fuelTr > 0) then
  376.         fuelTr = math.min(fuelTr, srf)
  377.         drawFilledBox({6, fuelTr}, off + 8, srf + 5 - fuelTr,
  378.                 colors.magenta, colors.magenta)
  379.  
  380.         drawText(string.format(tempFormat, fuelRnd..""),
  381.                 off + 10, srf + 6 - fuelTr,
  382.                 colors.magenta, colors.black)
  383.     else
  384.         drawText(string.format(tempFormat, fuelRnd..""),
  385.                 off + 10, srf + 5,
  386.                 colors.black, colors.magenta)
  387.     end
  388.  
  389.     if (caseTr > 0) then
  390.         caseTr = math.min(caseTr, srf)
  391.         drawFilledBox({6, caseTr}, off + 1, srf + 5 - caseTr,
  392.                 colors.lightBlue, colors.lightBlue)
  393.         drawText(string.format(tempFormat, caseRnd..""),
  394.                 off + 3, srf + 6 - caseTr,
  395.                 colors.lightBlue, colors.black)
  396.     else
  397.         drawText(string.format(tempFormat, caseRnd..""),
  398.                 off + 3, srf + 5,
  399.                 colors.black, colors.lightBlue)
  400.     end
  401.  
  402.     drawText("Temperatures", off + 2, 4,
  403.             colors.black, colors.orange)
  404.     drawBox({1, srf}, off + 7, 5,
  405.             colors.gray)
  406. end
  407.  
  408. local beg
  409. local function drawGraph(name, offset)
  410.     if (name == "Energy Buffer") then
  411.         drawEnergyBuffer(offset)
  412.     elseif (name == "Control Level") then
  413.         drawControlLevel(offset)
  414.     elseif (name == "Temperatures") then
  415.         drawTemperatures(offset)
  416.     end
  417. end
  418.  
  419. local function drawGraphs()
  420.     for i,v in pairs(graphsToDraw) do
  421.         if (v + 15 < dim) then
  422.             drawGraph(i,v)
  423.         end
  424.     end
  425. end
  426.  
  427. local function drawStatus()
  428.     if (dim > -1) then
  429.         drawBox({dim, sizey - 2},
  430.                 1, 1, colors.lightBlue)
  431.         drawText(" Reactor Graphs ", dim - 18, 2,
  432.                 colors.black, colors.lightBlue)
  433.         drawGraphs()
  434.     end
  435. end
  436.  
  437. local function drawControls()
  438.     if (sizey == 24) then
  439.         drawBox({sizex - dim - 3, 9}, dim + 2, oo,
  440.                 colors.cyan)
  441.         drawText(" Reactor Controls ", dim + 7, oo + 1,
  442.                 colors.black, colors.cyan)
  443.         drawText("Reactor "..(btnOn and "Online" or "Offline"),
  444.                 dim + 10, 3 + oo,
  445.                 colors.black, btnOn and colors.green or colors.red)
  446.     else
  447.         drawBox({sizex - dim - 3, 23}, dim + 2, oo,
  448.                 colors.cyan)
  449.         drawText(" Reactor Controls ", dim + 7, oo + 1,
  450.                 colors.black, colors.cyan)
  451.         drawFilledBox({20, 3}, dim + 7, 8 + oo,
  452.                 colors.red, colors.red)
  453.         drawFilledBox({(maxb - minb) / 5, 3},
  454.                 dim + 7 + minb / 5, 8 + oo,
  455.                 colors.green, colors.green)
  456.         drawText(string.format("%3s", minb.."%"), dim + 6 + minb / 5, 12 + oo,
  457.                 colors.black, colors.purple)
  458.         drawText(maxb.."%", dim + 8 + maxb / 5, 12 + oo,
  459.                 colors.black, colors.magenta)
  460.         drawText("Buffer Target Range", dim + 8, 8 + oo,
  461.                 colors.black, colors.orange)
  462.         drawText("Min", dim + 10, 14 + oo,
  463.                 colors.black, colors.purple)
  464.         drawText("Max", dim + 22, 14 + oo,
  465.                 colors.black, colors.magenta)
  466.         drawText("Reactor ".. (btnOn and "Online" or "Offline"),
  467.                 dim + 10, 3 + oo,
  468.                 colors.black, btnOn and colors.green or colors.red)
  469.     end
  470. end
  471.  
  472. local function drawStatistics()
  473.     local oS = sizey - 13
  474.     drawBox({sizex - dim - 3, sizey - oS - 1}, dim + 2, oS,
  475.             colors.blue)
  476.     drawText(" Reactor Statistics ", dim + 7, oS + 1,
  477.             colors.black, colors.blue)
  478.  
  479.     --statistics
  480.     drawText("Generating : "
  481.             ..format(averageLastRFT).."RF/t", dim + 5, oS + 3,
  482.             colors.black, colors.green)
  483.     drawText("RF Drain   "
  484.             ..(averageStoredThisTick <= averageLastRFT and "> " or ": ")
  485.             ..format(averageRfLost)
  486.             .."RF/t", dim + 5, oS + 5,
  487.             colors.black, colors.red)
  488.     drawText("Efficiency : "
  489.             ..format(getEfficiency()).."RF/B",
  490.             dim + 5, oS + 7,
  491.             colors.black, colors.green)
  492.     drawText("Fuel Usage : "
  493.             ..format(averageFuelUsage)
  494.             .."B/t", dim + 5, oS + 9,
  495.             colors.black, colors.green)
  496.     drawText("Waste      : "
  497.             ..string.format("%7d mB", waste),
  498.             dim + 5, oS + 11,
  499.             colors.black, colors.green)
  500. end
  501.  
  502. --Draw a scene
  503. local function drawScene()
  504.     if (monSide ~= nil) then
  505.         t:draw()
  506.     end
  507.     if (displayingGraphMenu) then
  508.         drawGraphButtons()
  509.     end
  510.     if (invalidDim) then
  511.         if (monSide ~= nil) then
  512.             mon.write("Invalid Monitor Dimensions")
  513.         end
  514.     else
  515.         drawControls()
  516.         drawStatus()
  517.         drawStatistics()
  518.     end
  519. end
  520.  
  521. --Redraws all the buttons
  522. --Updates the important values
  523. local function reDrawButtons()
  524.     if (monSide ~= nil) then
  525.         t = touchpoint.new(monSide)
  526.         sizex, sizey = mon.getSize()
  527.         oo = sizey - 37
  528.         dim = sizex - 33
  529.     end
  530.     --print(sizex, sizey)
  531.     if (sizex == 36) then
  532.         dim = -1
  533.     end
  534.     if (pcall(addGraphButtons)) then
  535.         drawGraphButtons()
  536.         displayingGraphMenu = true
  537.     else
  538.         if (monSide ~= nil) then
  539.             t = touchpoint.new(monSide)
  540.         end
  541.         displayingGraphMenu = false
  542.     end
  543.     local rtn = pcall(addButtons)
  544.     if (not rtn) then
  545.         if (monSide ~= nil) then
  546.             t = touchpoint.new(monSide)
  547.         end
  548.         invalidDim = true
  549.     else
  550.         invalidDim = false
  551.     end
  552.     --t:draw()
  553. end
  554.  
  555. --set rod level making sure its in the range of 0 and 100
  556. local function setRods(level)
  557.     level = math.max(level, 0)
  558.     level = math.min(level, 100)
  559.     reactor.setAllControlRodLevels(level)
  560. end
  561.  
  562. --Turns off the reactor
  563. local function turnOff()
  564.     if (btnOn) then
  565.         t:toggleButton("Off")
  566.         t:toggleButton("On")
  567.         btnOff = true
  568.         btnOn = false
  569.         setRods(100)
  570.         reactor.setActive(false)
  571.     end
  572. end
  573.  
  574. --Turns on the reactor
  575. local function turnOn()
  576.     if (btnOff) then
  577.         t:toggleButton("Off")
  578.         t:toggleButton("On")
  579.         btnOff = false
  580.         btnOn = true
  581.         reactor.setActive(true)
  582.     end
  583. end
  584.  
  585. function lerp(start, finish, t)
  586.     -- Ensure t is in the range [0, 1]
  587.     t = math.max(0, math.min(1, t))
  588.  
  589.     -- Calculate the linear interpolation
  590.     return (1 - t) * start + t * finish
  591. end
  592.  
  593.  
  594. -- Define PID controller parameters
  595. local pid = {
  596.     setpointRFT = 0,      -- Target RFT
  597.     setpointRF = 0,      -- Target RF
  598.     Kp = -.08,           -- Proportional gain
  599.     Ki = -.0015,          -- Integral gain
  600.     Kd = -.01,         -- Derivative gain
  601.     integral = 0,       -- Integral term accumulator
  602.     lastError = 0,      -- Last error for derivative term
  603. }
  604.  
  605. local function iteratePID(pid, error)
  606.     -- Proportional term
  607.     local P = pid.Kp * error
  608.  
  609.     -- Integral term
  610.     pid.integral = pid.integral + pid.Ki * error
  611.     pid.integral = math.max(math.min(100, pid.integral), -100)
  612.  
  613.     -- Derivative term
  614.     local derivative = pid.Kd * (error - pid.lastError)
  615.  
  616.     -- Calculate control rod level
  617.     local rodLevel = math.max(math.min(P + pid.integral + derivative, 100), 0)
  618.  
  619.     -- Update PID controller state
  620.     pid.lastError = error
  621.     return rodLevel
  622. end
  623.  
  624. --adjusts the level of the rods
  625. local function adjustRods()
  626.     local currentRF = storedThisTick
  627.     local diffb = maxb - minb
  628.     maxRF = maxb / 100 * capacity
  629.     minRF = minb / 100 * capacity
  630.     diffRF = diffb / 100 * capacity
  631.     local diffr = diffb / 100
  632.     local targetRFT = rfLost
  633.     local currentRFT = lastRFT
  634.     local diffRFT = currentRFT/targetRFT
  635.     local targetRF = diffRF / 2 + minRF
  636.  
  637.     pid.setpointRFT = targetRFT
  638.     pid.setpointRF = targetRF / capacity * 1000
  639.  
  640.     local errorRFT = pid.setpointRFT - currentRFT
  641.     local errorRF = pid.setpointRF - currentRF / capacity * 1000
  642.  
  643.     local W_RFT = lerp(1, 0, (math.abs(targetRF - currentRF) / capacity / (diffr / 4)))
  644.     W_RFT = math.max(math.min(W_RFT, 1), 0)
  645.  
  646.     local W_RF = (1 - W_RFT)  -- Adjust the weight for energy error
  647.  
  648.     -- Combine the errors with weights
  649.     local combinedError = W_RFT * errorRFT + W_RF * errorRF
  650.     local error = combinedError
  651.     local rftRodLevel = iteratePID(pid, error)
  652.  
  653.     -- Set control rod levels
  654.     setRods(rftRodLevel)
  655. end
  656.  
  657. --Saves the configuration of the reactor controller
  658. local function saveChanges()
  659.     local file = fs.open(tag..".txt", "w")
  660.     file.writeLine(calibrated)
  661.     if (calibrated) then
  662.         file.writeLine(capacity)
  663.         file.writeLine(maxRFT)
  664.     end
  665.     file.writeLine(maxb)
  666.     file.writeLine(minb)
  667.     file.writeLine(rod)
  668.     file.writeLine(btnOn)
  669.     for i,v in pairs(XOffs) do
  670.         local graph = getGraph(v[1])
  671.         graph = (graph == nil and "nil" or graph)
  672.         file.writeLine(graph)
  673.         file.writeLine(v[1])
  674.     end
  675.     file.close()
  676. end
  677.  
  678. --returns the side that a given peripheral type is connected to
  679. local function getPeripheral(name)
  680.     for i,v in pairs(peripheral.getNames()) do
  681.         if (peripheral.getType(v) == name) then
  682.             return v
  683.         end
  684.     end
  685.     return ""
  686. end
  687. local storedThisTickValues = {}
  688. local lastRFTValues = {}
  689. local rodValues = {}
  690. local fuelUsageValues = {}
  691. local wasteValues = {}
  692. local fuelTempValues = {}
  693. local caseTempValues = {}
  694. local rfLostValues = {}
  695.  
  696. local function updateStats()
  697.     storedLastTick = storedThisTick
  698.     if (reactorVersion == "Big Reactors") then
  699.         storedThisTick = reactor.getEnergyStored()
  700.         lastRFT = reactor.getEnergyProducedLastTick()
  701.         rod = reactor.getControlRodLevel(0)
  702.         fuelUsage = reactor.getFuelConsumedLastTick() / 1000
  703.         waste = reactor.getWasteAmount()
  704.         fuelTemp = reactor.getFuelTemperature()
  705.         caseTemp = reactor.getCasingTemperature()
  706.     elseif (reactorVersion == "Extreme Reactors") then
  707.         local bat = reactor.getEnergyStats()
  708.         local fuel = reactor.getFuelStats()
  709.  
  710.         storedThisTick = bat.energyStored
  711.         lastRFT = bat.energyProducedLastTick
  712.         capacity = bat.energyCapacity
  713.         rod = reactor.getControlRodLevel(0)
  714.         fuelUsage = fuel.fuelConsumedLastTick / 1000
  715.         waste = reactor.getWasteAmount()
  716.         fuelTemp = reactor.getFuelTemperature()
  717.         caseTemp = reactor.getCasingTemperature()
  718.     elseif (reactorVersion == "Bigger Reactors") then
  719.         storedThisTick = reactor.battery().stored()
  720.         lastRFT = reactor.battery().producedLastTick()
  721.         capacity = reactor.battery().capacity()
  722.         rod = reactor.getControlRod(0).level()
  723.         fuelUsage = reactor.fuelTank().burnedLastTick() / 1000
  724.         waste = reactor.fuelTank().waste()
  725.         fuelTemp = reactor.fuelTemperature()
  726.         caseTemp = reactor.casingTemperature()
  727.     end
  728.     rfLost = lastRFT + storedLastTick - storedThisTick
  729.     -- Add the values to the arrays
  730.     table.insert(storedThisTickValues, storedThisTick)
  731.     table.insert(lastRFTValues, lastRFT)
  732.     table.insert(rodValues, rod)
  733.     table.insert(fuelUsageValues, fuelUsage)
  734.     table.insert(wasteValues, waste)
  735.     table.insert(fuelTempValues, fuelTemp)
  736.     table.insert(caseTempValues, caseTemp)
  737.     table.insert(rfLostValues, rfLost)
  738.  
  739.     local maxIterations = 20 * secondsToAverage
  740.     while #storedThisTickValues > maxIterations do
  741.         table.remove(storedThisTickValues, 1)
  742.         table.remove(lastRFTValues, 1)
  743.         table.remove(rodValues, 1)
  744.         table.remove(fuelUsageValues, 1)
  745.         table.remove(wasteValues, 1)
  746.         table.remove(fuelTempValues, 1)
  747.         table.remove(caseTempValues, 1)
  748.         table.remove(rfLostValues, 1)
  749.     end
  750.  
  751.     -- Calculate running averages
  752.     averageStoredThisTick = calculateAverage(storedThisTickValues)
  753.     averageLastRFT = calculateAverage(lastRFTValues)
  754.     averageRod = calculateAverage(rodValues)
  755.     averageFuelUsage = calculateAverage(fuelUsageValues)
  756.     averageWaste = calculateAverage(wasteValues)
  757.     averageFuelTemp = calculateAverage(fuelTempValues)
  758.     averageCaseTemp = calculateAverage(caseTempValues)
  759.     averageRfLost = calculateAverage(rfLostValues)
  760. end
  761.  
  762.  
  763. -- Function to calculate the average of an array of values
  764. function calculateAverage(array)
  765.     local sum = 0
  766.     for _, value in ipairs(array) do
  767.         sum = sum + value
  768.     end
  769.     return sum / #array
  770. end
  771.  
  772.  
  773.  
  774. --Updates statistics and adjusts the rods
  775. local function compute()
  776.     updateStats()
  777.     if (btnOn) then
  778.         adjustRods()
  779.     end
  780. end
  781.  
  782. --The main routine that runs each tick
  783. function routine()
  784.     while (true) do
  785.         --[[
  786.         If the graphs are drawn every tick, everything
  787.         just breaks.
  788.         If the graphs are drawn every 2nd tick, my
  789.         RFLost calculation is wrong every time
  790.         If the graphs are drawn every 3rd tick, my
  791.         RFLost calculation is wrong sometimes
  792.  
  793.         THIS MAKES NO SENSE
  794.         ]]
  795.         for i = 1,4 do
  796.             compute()
  797.             sleep(0.01)
  798.         end
  799.         resetMon()
  800.         drawScene()
  801.     end
  802. end
  803.  
  804. --Manages window resizing events
  805. function resizer()
  806.     while (true) do
  807.         local event = os.pullEvent("monitor_resize")
  808.         if (event == "monitor_resize") then
  809.             reDrawButtons()
  810.         end
  811.     end
  812. end
  813.  
  814. local function calibrate()
  815.     setRods(0)
  816.     reactor.setActive(true)
  817.     sleep(15)
  818.     updateStats()
  819.     setRods(100)
  820.     reactor.setActive(false)
  821.     if (reactorVersion == "Big Reactors") then
  822.         capacity = storedThisTick
  823.     end
  824.     maxRFT = lastRFT
  825. end
  826.  
  827. --Initialize variables from either a config file or the defaults
  828. local function initializeVars()
  829.     invalidDim = false
  830.     if (not fs.exists(tag..".txt")) then
  831.         print("Config file "..tag.." not found, generating a default one!")
  832.         repeat
  833.             print("The program can be optionally calibrated. Proceed? (y/n) ")
  834.             local response = read()
  835.             if (response == "n") then
  836.                 print("Calibration skipped. Some functions may be unavailable")
  837.                 calbrated = false
  838.             elseif (response == "y") then
  839.                 print("Beginning 15 second calibration, do not turn off the reactor!")
  840.                 calibrate()
  841.                 print("Calibrated!")
  842.                 calibrated = true
  843.             end
  844.         until response == "y" or response == "n"
  845.  
  846.         maxb = 70
  847.         minb = 30
  848.         rod = 80
  849.         btnOn = false
  850.         if (monSide == nil) then
  851.             btnOn = true
  852.         end
  853.         dim = sizex - 33
  854.         oo = sizey - 37
  855.         enableGraph("Energy Buffer")
  856.         enableGraph("Control Level")
  857.         enableGraph("Temperatures")
  858.     else
  859.         local file = fs.open(tag..".txt", "r")
  860.         print("Config file "..tag.." found! Using configurated settings")
  861.  
  862.         calibrated = file.readLine() == "true"
  863.  
  864.         --read calibration information
  865.         if (calibrated) then
  866.             capacity = tonumber(file.readLine())
  867.             maxRFT = tonumber(file.readLine())
  868.         end
  869.         maxb = tonumber(file.readLine())
  870.         minb = tonumber(file.readLine())
  871.         rod = tonumber(file.readLine())
  872.         btnOn = file.readLine() == "true"
  873.  
  874.         --read Graph data
  875.         for i in pairs(XOffs) do
  876.             local graph = file.readLine()
  877.             local v1 = tonumber(file.readLine())
  878.             local v2 = true
  879.             if (graph ~= "nil") then
  880.                 v2 = false
  881.                 graphsToDraw[graph] = v1
  882.             end
  883.  
  884.             XOffs[i] = {v1, v2}
  885.  
  886.         end
  887.         file.close()
  888.     end
  889.     btnOff = not btnOn
  890.     diffb = maxb - minb
  891.     reactor.setActive(btnOn)
  892. end
  893.  
  894. --Initialize program
  895. local function initialize()
  896.     term.setBackgroundColor(colors.black)
  897.     term.clear()
  898.     term.setCursorPos(1,1)
  899.     os.loadAPI("/usr/apis/touchpoint.lua")
  900.     reactorSide = getPeripheral("BiggerReactors_Reactor")
  901.     reactorVersion = "Bigger Reactors"
  902.     reactor = peripheral.wrap(reactorSide)
  903.     if (reactor == nil) then
  904.         reactorSide = getPeripheral("BigReactors-Reactor")
  905.         reactor = peripheral.wrap(reactorSide)
  906.         if (reactor.mbIsConnected ~= nil) then
  907.             reactorVersion = "Extreme Reactors"
  908.         else
  909.             reactorVersion = "Big Reactors"
  910.         end
  911.     end
  912.     if (reactor == nil) then
  913.         reactorSide = getPeripheral("bigger-reactor")
  914.         reactor = peripheral.wrap(reactorSide)
  915.         reactorVersion = "Big Reactors"
  916.     end
  917.     monSide = getPeripheral("monitor")
  918.     monSide = monSide == "" and nil or monSide
  919.     sizex, sizey = 36, 38
  920.     if (monSide ~= nil) then
  921.         mon = peripheral.wrap(monSide)
  922.         sizex, sizey = mon.getSize()
  923.         resetMon()
  924.     end
  925.     if(isActivelyCooled()) then
  926.         activelyCooled = true
  927.     end
  928.     return reactor ~= nil
  929. end
  930.  
  931. --Entry point
  932. function threadMain()
  933.     repeat
  934.         local good = initialize()
  935.         if (not good) then
  936.             print("Reactor could not be detected! Trying again")
  937.             sleep(1)
  938.         else
  939.             print("Reactor detected! Proceeding with initialization: ")
  940.         end
  941.     until (good)
  942.     initializeVars()
  943.     reDrawButtons()
  944.     saveChanges()
  945.     print("Reactor initialization done!")
  946.     sleep(2)
  947.     term.clear()
  948.     term.setCursorPos(1,1)
  949.     os.startThread(resizer)
  950.     os.startThread(routine)
  951.     print("Reactor Controller Version "..version)
  952.     print("Reactor Mod: "..reactorVersion)
  953.     if(activelyCooled) then
  954.         print("Reactor is ctivly cooled")
  955.     else
  956.         print("Reactor is not activly cooled")
  957.     end
  958.     --main loop
  959.     --local lastTime = 0
  960.  
  961.     os.startTimer(0.01)
  962.     while (true) do
  963.         local event, p1
  964.         if (monSide ~= nil) then
  965.             event, p1 = t:handleEvents(os.pullEvent("monitor_touch"))
  966.         else
  967.             event = os.pullEvent("monitor_touch")
  968.         end
  969.         if (event == "button_click") then
  970.             if (p1 == "Off") then
  971.                 turnOff()
  972.             elseif (p1 == "On") then
  973.                 turnOn()
  974.             elseif (p1 == "+ 10") then
  975.                 minb = math.min(maxb - 10, minb + 10)
  976.             elseif (p1 == "- 10") then
  977.                 minb = math.max(0, minb - 10)
  978.             elseif (p1 == " + 10 ") then
  979.                 maxb = math.min(100, maxb + 10)
  980.             elseif (p1 == " - 10 ") then
  981.                 maxb = math.max(minb + 10, maxb - 10)
  982.             elseif (isGraph(p1)) then
  983.                 toggleGraph(p1)
  984.             end
  985.             saveChanges()
  986.         end
  987.     end
  988. end
  989.  
  990. --thread stuff below here
  991. local threads = {}
  992. local starting = {}
  993. local eventFilter = nil
  994.  
  995. rawset(os, "startThread", function(fn, blockTerminate)
  996.     table.insert(starting, {
  997.         cr = coroutine.create(fn),
  998.         blockTerminate = blockTerminate or false,
  999.         error = nil,
  1000.         dead = false,
  1001.         filter = nil
  1002.     })
  1003. end)
  1004.  
  1005. local function tick(t, evt, ...)
  1006.     if t.dead then return end
  1007.     if t.filter ~= nil and evt ~= t.filter then return end
  1008.     if evt == "terminate" and t.blockTerminate then return end
  1009.  
  1010.     coroutine.resume(t.cr, evt, ...)
  1011.     t.dead = (coroutine.status(t.cr) == "dead")
  1012. end
  1013.  
  1014. local function tickAll()
  1015.     if #starting > 0 then
  1016.         local clone = starting
  1017.         starting = {}
  1018.         for _,v in ipairs(clone) do
  1019.             tick(v)
  1020.             table.insert(threads, v)
  1021.         end
  1022.     end
  1023.     local e
  1024.     if eventFilter then
  1025.         e = {eventFilter(coroutine.yield())}
  1026.     else
  1027.         e = {coroutine.yield()}
  1028.     end
  1029.     local dead = nil
  1030.     for k,v in ipairs(threads) do
  1031.         tick(v, unpack(e))
  1032.         if v.dead then
  1033.             if dead == nil then dead = {} end
  1034.             table.insert(dead, k - #dead)
  1035.         end
  1036.     end
  1037.     if dead ~= nil then
  1038.         for _,v in ipairs(dead) do
  1039.             table.remove(threads, v)
  1040.         end
  1041.     end
  1042. end
  1043.  
  1044. rawset(os, "setGlobalEventFilter", function(fn)
  1045.     if eventFilter ~= nil then error("This can only be set once!") end
  1046.     eventFilter = fn
  1047.     rawset(os, "setGlobalEventFilter", nil)
  1048. end)
  1049.  
  1050. if type(threadMain) == "function" then
  1051.     os.startThread(threadMain)
  1052. else
  1053.     os.startThread(function() shell.run("shell") end)
  1054. end
  1055.  
  1056. while #threads > 0 or #starting > 0 do
  1057.     tickAll()
  1058. end
  1059.  
  1060. print("All threads terminated!")
  1061. print("Exiting thread manager")
  1062.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement