Advertisement
glitchdetector

EMC Graphing

Oct 14th, 2023 (edited)
942
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.76 KB | None | 0 0
  1. -- Computercraft Program
  2. -- by glitchdetector
  3.  
  4. function ReadableNumber(num, places, full)
  5.     num = tonumber(num)
  6.     if not num then return 0 end
  7.     local ret
  8.     local placeValue = ("%%.%df"):format(places or 0)
  9.     local isNegative = num < 0
  10.     num = math.abs(num)
  11.     if num >= 1000000000000 then
  12.         ret = placeValue:format(num / 1000000000000) .. (full and " trillion" or "T") -- trillion
  13.     elseif num >= 1000000000 then
  14.         ret = placeValue:format(num / 1000000000) .. (full and " billion" or "B") -- billion
  15.     elseif num >= 1000000 then
  16.         ret = placeValue:format(num / 1000000) .. (full and " million" or "M") -- million
  17.     elseif num >= 1000 and not full then
  18.         ret = placeValue:format(num / 1000) .. "k" -- thousand
  19.     elseif num >= 1 then
  20.         ret = ("%.0f"):format(num) -- hundreds
  21.     else
  22.         ret = num
  23.     end
  24.     return (isNegative and "- " or "") .. ret
  25. end
  26.  
  27. function GetEMC(link)
  28.     local items = link.list()
  29.     if not items then return 0 end
  30.     if not items[1] then return 0 end
  31.     return items[1].count or 0
  32. end
  33.  
  34. function ClearScreen(monitor)
  35.     monitor.clear()
  36.     monitor.setCursorPos(1, 1)
  37. end
  38.  
  39. function NextLine(monitor)
  40.     local x, y = monitor.getCursorPos()
  41.     monitor.setCursorPos(1, y + 1)
  42. end
  43.  
  44. function WriteCenterAligned(monitor, text)
  45.     local w, h = monitor.getSize()
  46.     local x, y = monitor.getCursorPos()
  47.     monitor.setCursorPos(math.ceil(w / 2 - #text / 2), y)
  48.     monitor.write(text)
  49. end
  50.  
  51. function WriteLeftAligned(monitor, text)
  52.     local x, y = monitor.getCursorPos()
  53.     monitor.setCursorPos(1, y)
  54.     monitor.write(text)
  55. end
  56.  
  57. function WriteRightAligned(monitor, text)
  58.     local w, h = monitor.getSize()
  59.     local x, y = monitor.getCursorPos()
  60.     monitor.setCursorPos(w - #text + 1, y)
  61.     monitor.write(text)
  62. end
  63.  
  64. -- Program Code
  65.  
  66. local Users = {
  67.     {"top", "Glitch"},
  68.     {"right", "Collins"},
  69. }
  70.  
  71. for _, user in next, Users do
  72.     user[3] = peripheral.wrap(user[1])
  73. end
  74.  
  75. local monitor = peripheral.wrap("monitor_0")
  76. local graph = peripheral.wrap("monitor_2")
  77. local last = 0
  78. local timespan = 1
  79. local timespanFactor = 60 / timespan
  80.  
  81. local Histories = {}
  82. function CalculateHistory(name, new, limit)
  83.     if not Histories[name] then Histories[name] = {} end
  84.     local history = Histories[name]
  85.  
  86.     table.insert(history, new)
  87.     while #history > limit do
  88.         table.remove(history, 1)
  89.     end
  90.     local sum = 0
  91.     for _, v in next, history do
  92.         sum = sum + v
  93.     end
  94.     return sum / #history
  95. end
  96.  
  97. function GraphData(monitor, data, title)
  98.     local w, h = monitor.getSize()
  99.     local max = -math.huge
  100.     local min = math.huge
  101.     for _, v in next, data do
  102.         if v > max then max = v end
  103.         if v < min then min = v end
  104.     end
  105.  
  106.     local range = max - min
  107.     min = min - range * 0.1
  108.     max = max + range * 0.1
  109.     range = max - min
  110.  
  111.     local scale = h / range
  112.     if range == 0 then scale = 1 end
  113.    
  114.     local nData = #data
  115.     local dataScale = nData / w
  116.     local lastPos = 0
  117.     for i = 1, w do
  118.         print("monitor " .. i .. " of " .. w)
  119.         -- get data closest to i
  120.         local dataIndex = math.floor(i * dataScale)
  121.         local v = data[dataIndex] or 0
  122.        
  123.         local bar = math.ceil((v - min) * scale)
  124.         local vPos = math.floor(h - bar + 1)
  125.        
  126.         if i > 1 then
  127.             for j = math.min(vPos, lastPos), math.max(vPos, lastPos) do
  128.                 monitor.setCursorPos(i - 1, j)
  129.                 monitor.blit(" ", "f", "0")
  130.             end
  131.         end
  132.         lastPos = vPos
  133.  
  134.         monitor.setCursorPos(i, vPos)
  135.         monitor.blit(" ", "f", "0")
  136.     end
  137.  
  138.     -- Draw min and max values
  139.     monitor.setCursorPos(1, 1)
  140.     monitor.write(ReadableNumber(max, 2, false))
  141.     monitor.setCursorPos(1, h)
  142.     monitor.write(ReadableNumber(min, 2, false))
  143.  
  144.     -- Draw current value
  145.     local current = data[#data]
  146.     local currentV = lastPos
  147.     local text = ReadableNumber(current, 2, false)
  148.     local textLen = #text
  149.     local textX = math.floor(w - textLen - 2)
  150.     monitor.setCursorPos(textX, currentV)
  151.     monitor.write(text)
  152.  
  153.     -- Draw title
  154.     local titleLen = #title
  155.     local titleX = math.floor(w / 2 - titleLen / 2)
  156.     monitor.setCursorPos(titleX, 1)
  157.     monitor.write(title)
  158. end
  159.  
  160. function Graph(monitor, data, title, timeName)
  161.     local w, h = monitor.getSize()
  162.     local x, y = monitor.getCursorPos()
  163.     local max = -math.huge
  164.     local min = math.huge
  165.     for _, v in next, data do
  166.         if v > max then max = v end
  167.         if v < min then min = v end
  168.     end
  169.  
  170.     local range = max - min
  171.     min = min - range * 0.1
  172.     max = max + range * 0.1
  173.     range = max - min
  174.  
  175.     local scale = h / range
  176.     if range == 0 then scale = 1 end
  177.     local lastPos = 0
  178.     for i = 1, #data do
  179.         local v = data[i]
  180.         local bar = math.ceil((v - min) * scale)
  181.         local vPos = math.floor(h - bar + 1)
  182.         if i > 1 then
  183.             for j = math.min(vPos, lastPos), math.max(vPos, lastPos) do
  184.                 monitor.setCursorPos(i - 1, j)
  185.                 monitor.blit(" ", "f", "0")
  186.             end
  187.         end
  188.         lastPos = vPos
  189.         monitor.setCursorPos(i, vPos)
  190.         monitor.blit(" ", "f", "0")
  191.     end
  192.     -- Draw min and max values
  193.     monitor.setCursorPos(1, 1)
  194.     monitor.write(ReadableNumber(max, 2, false))
  195.     monitor.setCursorPos(1, h)
  196.     monitor.write(ReadableNumber(min, 2, false))
  197.  
  198.     -- Draw current value
  199.     local current = data[#data]
  200.     local currentV = lastPos
  201.     local text = ReadableNumber(current, 2, false)
  202.     local textLen = #text
  203.     local textX = math.floor(w - textLen - 2)
  204.     monitor.setCursorPos(textX, currentV)
  205.     monitor.write(text)
  206.  
  207.     -- Draw title
  208.     local titleLen = #title
  209.     local titleX = math.floor(w / 2 - titleLen / 2)
  210.     monitor.setCursorPos(titleX, 1)
  211.     monitor.write(title)
  212.  
  213.     -- Footer with time name
  214.     local footer = ("<- %s %s ->"):format(#data, timeName)
  215.     local footerLen = #footer
  216.     local footerX = math.floor(w / 2 - footerLen / 2)
  217.     monitor.setCursorPos(footerX, h)
  218.     monitor.write(footer)
  219. end
  220.  
  221. -- load list of minutes from file
  222. local minutes = {}
  223. local log = fs.open("minutes.log", "r")
  224. if log then
  225.     Histories["sum"] = {}
  226.     local line = log.readLine()
  227.     while line do
  228.         table.insert(Histories["sum"], tonumber(line))
  229.         line = log.readLine()
  230.     end
  231.     log.close()
  232. end
  233.  
  234. local tick = 0
  235. while true do
  236.     ClearScreen(monitor)
  237.     WriteCenterAligned(monitor, "Energy Matter Covalence")
  238.     NextLine(monitor)
  239.     local sum = 0
  240.     for n, user in next, Users do
  241.         WriteLeftAligned(monitor, user[2])
  242.         local EMC = GetEMC(user[3])
  243.         sum = sum + EMC
  244.         WriteRightAligned(monitor, ReadableNumber(EMC, 2, false) .. " EMC")
  245.         NextLine(monitor)
  246.     end
  247.     WriteCenterAligned(monitor, ReadableNumber(sum, 2, true) .. " EMC")
  248.  
  249.     NextLine(monitor)
  250.     local difference = (sum - last)
  251.     local avgDiff = CalculateHistory("diff", difference, timespanFactor)
  252.     local isNeg = avgDiff < 0
  253.     if isNeg then
  254.         monitor.setTextColour(colors.red)
  255.     else
  256.         monitor.setTextColour(colors.green)
  257.     end
  258.     last = sum
  259.     WriteCenterAligned(monitor, (isNeg and "" or "+ ") .. ReadableNumber(avgDiff, 2, true) .. " / minute")
  260.     monitor.setTextColour(colors.white)
  261.  
  262.     graph.setBackgroundColor(colors.black)
  263.  
  264.     if tick % timespanFactor == 0 then
  265.         local w, h = graph.getSize()
  266.         CalculateHistory("sum", sum, w)
  267.         ClearScreen(graph)
  268.         Graph(graph, Histories["sum"], "EMC HISTORY", " minutes")
  269.  
  270.         local log = fs.open("minutes.log", "a")
  271.         log.writeLine(sum)
  272.         log.close()
  273.     end
  274.    
  275.     tick = tick + 1
  276.     sleep(timespan)
  277. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement