Advertisement
BigBlow_

inductionMatrixMonitor

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