Advertisement
BigBlow_

meka induction matrix monitor

Nov 11th, 2024 (edited)
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- config
  2. local dataCorrection = 2.5 -- value to divide IM data by.
  3. local displayMinMax = false-- set to false to hide the "MIN" and "MAX" text.
  4. local screenRefreshRate = 1 -- how often to display new data in seconds.
  5. local unitFormatCaps = true -- true = X.X KRF. false = X.XkRF
  6. local showTooltips = true -- suggests adding providers when input/output is maxed.
  7. local alarmPercent = 5 -- what % to output a redstone signal. 0 to 100 to enable. -1 to disable.
  8.  
  9. --Setup
  10. mon = peripheral.find("monitor")
  11. mat = peripheral.find("inductionPort")
  12. term.clear()
  13. term.setCursorPos(1,1)
  14.  
  15. --Draw Function
  16. function draw(xmin, xmax, ymin, ymax, c)
  17.     mon.setBackgroundColor(c)
  18.     mon.setCursorPos(xmin, ymin)
  19.     if xmax ~= 1 then
  20.         for i = 1, xmax, 1 do
  21.             mon.write(" ")
  22.             mon.setCursorPos(xmin+i, ymin)
  23.         end
  24.     end
  25.     if ymax ~= 1 then
  26.         for k = 1, ymax, 1 do
  27.             mon.write(" ")
  28.             mon.setCursorPos(xmin, ymin+k)
  29.         end
  30.     end
  31.     mon.setBackgroundColor(32768)
  32. end
  33.  
  34. --DrawBar Function
  35. function drawBar(xmin, xmax, y, r, c)
  36.     for i=1, r, 1 do    
  37.         draw(xmin, xmax, y+i-1, 1, c)
  38.     end
  39. end
  40.  
  41. -- error screen
  42. function displayError(index)
  43.     local x, y = mon.getSize()
  44.     if x ~= 50 or y ~= 19 then return end
  45.  
  46.     local errorText = "ERROR"
  47.     local errors = {
  48.         "The Induction Matrix has been tampered with.",
  49.         "Induction Port not connected.",
  50.         "The Induction Matrix is incomplete."
  51.     }
  52.  
  53.     mon.clear()
  54.     -- error
  55.     mon.setTextColour(16384)
  56.     mon.setCursorPos((x/2) - (string.len(errorText)/2), (y/2)-1)
  57.     mon.write(errorText)
  58.     -- msg
  59.     mon.setTextColour(1)
  60.     mon.setCursorPos((x/2) - (string.len(errors[index])/2), y/2)
  61.     mon.write(errors[index])
  62.     printError("ERROR: " .. errors[index])
  63.  
  64.     local timer = 10
  65.     while timer > -1 do
  66.         local countdownStr = "Next attempt in " .. timer
  67.  
  68.         mon.setTextColour(1)
  69.         mon.setCursorPos((x/2) - (string.len(countdownStr)/2), (y/2)+2)
  70.         draw((x/2) - (string.len(countdownStr)/2), string.len(countdownStr) + 1, (y/2)+2, 1, 32768)
  71.         mon.setCursorPos((x/2) - (string.len(countdownStr)/2), (y/2)+2)
  72.         mon.write(countdownStr)
  73.         print(countdownStr)
  74.  
  75.         timer = timer -1
  76.         os.sleep(1)
  77.     end
  78.  
  79.     os.reboot()
  80. end
  81.  
  82. --Round Function
  83. function round(float)
  84.     local int, part = math.modf(float)
  85.     if float == math.abs(float) and part >= .5 then return int+1
  86.     elseif part <= -.5 then return int-1
  87.     end
  88.     return int
  89. end
  90.  
  91. --Round with 2 Decimals Function
  92. function roundD(exact, quantum)
  93.     local quant,frac = math.modf(exact/quantum)
  94.     return quantum * (quant + (frac > 0.5 and 1 or 0))
  95. end
  96.  
  97. -- format time
  98. local timeUnits = {
  99.     {threshold = 8553600, unit = "99+ days"},
  100.     {threshold = 86400, unit = "days", divisor = 86400},
  101.     {threshold = 3600, unit = "hours", divisor = 3600},
  102.     {threshold = 60, unit = "min", divisor = 60},
  103.     {threshold = 1, unit = "sec", divisor = 1}
  104. }
  105.  
  106. function adjustTime(time)
  107.     for _, unitData in ipairs(timeUnits) do
  108.         if time >= unitData.threshold then
  109.             local adjustedTime
  110.             if unitData.divisor and unitData.divisor ~= 1 then
  111.                 adjustedTime = string.format("%.1f", time / unitData.divisor)
  112.             elseif unitData.divisor then
  113.                 adjustedTime = math.floor(time / unitData.divisor)
  114.             else
  115.                 adjustedTime = ""
  116.             end
  117.             return string.format("%s %s", adjustedTime, unitData.unit)
  118.         end
  119.     end
  120.     return "0 sec."  -- fallback, if time is 0 or negative
  121. end
  122.  
  123. --Conversion Function
  124. function conversion(exact, text, addPlus, afterDecimalPoint)
  125.     afterDecimalPoint = afterDecimalPoint or 0.1
  126.     addPlus = addPlus or false
  127.  
  128.     local units = unitFormatCaps and {"", "K", "M", "G", "T", "P", "E", "Z", "Y"} or {"", "k", "m", "g", "t", "p", "e", "z", "y"}
  129.     local pot = 1
  130.     local absExact = math.abs(exact)
  131.  
  132.     while absExact >= (1000^pot) do
  133.         pot = pot + 1
  134.     end
  135.  
  136.     local value = roundD(exact / (1000^(pot - 1)), afterDecimalPoint)
  137.     local out = tostring(value)
  138.    
  139.     if addPlus and value > 0 then out = "+" .. out end
  140.     if text then out = out .. (unitFormatCaps and " " .. units[pot] or units[pot]) end
  141.  
  142.     return out
  143. end
  144.  
  145. -- draw static elements (runs once)
  146. function drawStatic()
  147.     --Frame Induction Matrix
  148.     draw(2, 2, 2, 1, 128)
  149.     draw(22, 13, 2, 1, 128)
  150.     draw(2, 1, 2, 17, 128)
  151.     draw(2, 33, 18, 1, 128)
  152.     draw(34, 1, 2, 17, 128)
  153.     draw(2, 33, 8, 1, 128)
  154.     mon.setCursorPos(5,2)
  155.     mon.write("Induction Matrix")
  156.  
  157.     --Status
  158.     draw(36, 2, 2, 1, 128)
  159.     draw(36, 1, 2, 9, 128)
  160.     draw(49, 1, 2, 9, 128)
  161.     draw(36, 13, 10, 1, 128)
  162.     draw(46, 4, 2, 1, 128)
  163.     mon.setCursorPos(39,2)
  164.     mon.write("Status")
  165.     mon.setCursorPos(38,7)
  166.     mon.write("Flow:")
  167.  
  168.     --Frame Stats
  169.     draw(36, 1, 12, 7, 128)
  170.     draw(49, 1, 12, 7, 128)
  171.     draw(36, 13, 18, 1, 128)
  172.     draw(36, 2, 12, 1, 128)
  173.     draw(45, 4, 12, 1, 128)
  174.     mon.setCursorPos(39,12)
  175.     mon.write("Stats")
  176.    
  177.     --energyBar
  178.     drawBar(4, 29, 4, 3, 256)
  179.  
  180.     --inputBar
  181.     drawBar(4, 29, 11, 2, 256)
  182.     mon.setCursorPos(4,10)
  183.     mon.write("Input:")
  184.     if displayMinMax then
  185.         mon.setTextColour(128)
  186.         mon.setCursorPos(4,13)
  187.         mon.write("min")
  188.         mon.setCursorPos(30,13)
  189.         mon.write("max")
  190.         mon.setTextColour(1)
  191.     end
  192.    
  193.     --outputBar
  194.     drawBar(4, 29, 15, 2, 256)
  195.     mon.setCursorPos(4,14)
  196.     mon.write("Output:")
  197.     if displayMinMax then
  198.         mon.setTextColour(128)
  199.         mon.setCursorPos(4,17)
  200.         mon.write("min")
  201.         mon.setCursorPos(30,17)
  202.         mon.write("max")
  203.         mon.setTextColour(1)
  204.     end
  205. end
  206.  
  207. -- draw charts (runs every refresh)
  208. function drawCharts()
  209.     local percent = tostring(round((energy/dataCorrection)/(maxEnergy/dataCorrection)*100) .. "%")
  210.     local percentPos = (29/2) - (string.len(percent)/2) + 4
  211.     mon.setBackgroundColor(256)
  212.     mon.setCursorPos(percentPos, 5)
  213.     mon.write(percent)
  214.    
  215.     -- output meter
  216.     drawBar(4, 29, 15, 2, 256)
  217.     drawBar(4, round((lastOutput/transferCap)*29), 15, 2, 16384)
  218.     if showTooltips and lastOutput == transferCap then
  219.         mon.setBackgroundColor(16384)
  220.         mon.setCursorPos(4, 16)
  221.         mon.write("Maxed. Add/upgrade providers")
  222.     end
  223.  
  224.     -- input meter
  225.     drawBar(4, 29, 11, 2, 256)
  226.     drawBar(4, round((lastInput/transferCap)*29), 11, 2, 32)
  227.     if showTooltips and lastInput == transferCap then
  228.         mon.setBackgroundColor(32)
  229.         mon.setCursorPos(4, 12)
  230.         mon.write("Maxed. Add/upgrade providers")
  231.     end
  232.  
  233.     -- stored energy
  234.     drawBar(4, 29, 4, 3, 256)
  235.     drawBar(4, round(filledPercentage*29), 4, 3, 8)
  236.  
  237.     mon.setBackgroundColor(256)
  238.     mon.setCursorPos(percentPos, 5)
  239.     mon.write(percent)
  240.    
  241.     mon.setBackgroundColor(32768) -- reset to black
  242. end
  243.  
  244. -- draw stats (runs every refresh)
  245. function drawStats()
  246.     local capacity = maxEnergy/dataCorrection
  247.     local input = lastInput/dataCorrection
  248.     local output = lastOutput/dataCorrection
  249.     local stored = energy/dataCorrection
  250.     local flow = input - output
  251.     local maxTransfer = transferCap/dataCorrection
  252.    
  253.    
  254.     -- STATS
  255.     mon.setBackgroundColor(32768)
  256.  
  257.     mon.setCursorPos(38,14)
  258.     mon.write("Cells: " .. installedCells)
  259.  
  260.     mon.setCursorPos(38,15)
  261.     mon.write("I/O: " .. conversion(maxTransfer, true) .. "")
  262.  
  263.     mon.setCursorPos(38,16)
  264.     mon.write("Cap: " .. conversion(capacity, false))
  265.  
  266.     -- stored energy
  267.     draw(23, 11, 2, 1, 32768)
  268.     mon.setCursorPos(24,2)
  269.     mon.write(conversion(stored, true) .. "RF")
  270.  
  271.     -- input
  272.     draw(10, 23, 10, 1, 32768)
  273.     mon.setCursorPos(11,10)
  274.     mon.write(conversion(input, true, true) .. "RF/t")
  275.  
  276.     -- output
  277.     draw(11, 22, 14, 1, 32768)
  278.     mon.setCursorPos(12,14)
  279.     mon.write(conversion(output*-1, true) .. "RF/t")
  280.  
  281.     -- status
  282.     local chargeStatus = "Charging"
  283.     local timeStatus = "Full In:"
  284.     local statusColour = 8192 -- green
  285.     if (flow < 0) then
  286.         statusColour = 16384 -- red
  287.         chargeStatus = "Depleting"
  288.         timeStatus = "Empty In:"
  289.     elseif flow == 0 then
  290.         statusColour = 16 -- red
  291.         chargeStatus = "Idle"
  292.     end
  293.  
  294.     -- Full/Empty In
  295.     draw(38, 10, 5, 1, 32768)
  296.     mon.setCursorPos(38,5)
  297.     mon.write(timeStatus)
  298.  
  299.     mon.setTextColour(statusColour)
  300.     draw(38, 10, 4, 1, 32768)
  301.     mon.setCursorPos(38,4)
  302.     mon.write(chargeStatus)
  303.  
  304.     -- time remaining
  305.     local time = "Inf."
  306.     if output < input then
  307.         time = adjustTime((capacity - stored) / (input - output) / 20)
  308.     elseif output > input then
  309.         time = adjustTime(stored / (output - input) / 20)
  310.     end
  311.    
  312.     draw(38, 10, 6, 1, 32768)
  313.     mon.setCursorPos(38,6)
  314.     mon.write(time)
  315.    
  316.     -- flow
  317.     draw(38, 10, 8, 1, 32768)
  318.     mon.setCursorPos(38,8)
  319.     mon.write(conversion(flow, true, true, 1) .. "RF/t")
  320.     mon.setTextColour(1) -- reset
  321.    
  322. end
  323.  
  324. -- protective call
  325. function protCall(func, errIndex)
  326.     local success, result = pcall(func)
  327.     if success and result then
  328.         -- Function executed successfully, process the result
  329.         return result
  330.     else
  331.         -- Function encountered an error
  332.         displayError(errIndex)
  333.     end
  334. end
  335.  
  336. -- monitor check
  337. if mon ~= nil then
  338.     local x, y = mon.getSize()
  339.     if x ~= 50 or y ~= 19 then
  340.         print("ERROR: Incorrect monitor size. Monitor should be 5 wide and 3 tall.")
  341.         return
  342.     end
  343.    
  344.     mon.setBackgroundColor(32768)
  345.     mon.clear()
  346.     mon.setTextColour(1)
  347. else
  348.     print("No monitor found.")
  349.     return
  350. end
  351. -- matrix check
  352. while not mat or not mat.isFormed() do
  353.     if not mat then
  354.         displayError(2)
  355.     elseif not mat.isFormed() then
  356.         displayError(3)
  357.     end
  358. end
  359.  
  360. function lowBatAlarm()
  361.     -- check the below line
  362.     lowBatAlarmEnabled = (alarmPercent >= 0 and alarmPercent <= 100) and (round((energy/dataCorrection)/(maxEnergy/dataCorrection)*100) <= alarmPercent) -- and (lastInput/dataCorrection) - (lastOutput/dataCorrection) <= 0)
  363.     if lowBatAlarmEnabled and not rs.getOutput("top") then
  364.         setAlarm(true)
  365.     elseif not lowBatAlarmEnabled and rs.getOutput("top") then
  366.         setAlarm(false)
  367.     end
  368. end
  369.  
  370. function setAlarm(state)
  371.     for _, side in pairs(rs.getSides()) do
  372.         rs.setOutput(side, state)
  373.     end
  374. end
  375.  
  376. -- runs once
  377. print("Induction Matrix monitor successfully loaded.")
  378. print("Script by Ordiance & Broadbent")
  379. energy, maxEnergy, installedCells, installedProviders, lastInput, lastOutput, filledPercentage, transferCap, lowBatAlarmEnabled = nil
  380. mon.clear()
  381. mon.setBackgroundColor(16384)
  382. drawStatic()
  383.  
  384. -- runs every refresh
  385. while true do
  386.     energy = protCall(mat.getEnergy, 1)
  387.     maxEnergy = protCall(mat.getMaxEnergy, 1)
  388.     installedCells = protCall(mat.getInstalledCells, 1)
  389.     installedProviders = protCall(mat.getInstalledProviders, 1)
  390.     lastInput = protCall(mat.getLastInput, 1)
  391.     lastOutput = protCall(mat.getLastOutput, 1)
  392.     filledPercentage = protCall(mat.getEnergyFilledPercentage, 1)
  393.     transferCap = protCall(mat.getTransferCap, 1)
  394.  
  395.     drawCharts()
  396.     drawStats()
  397.     lowBatAlarm()
  398.     os.sleep(screenRefreshRate)
  399. end
  400.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement