-- Computercraft Program -- by glitchdetector function ReadableNumber(num, places, full) num = tonumber(num) if not num then return 0 end local ret local placeValue = ("%%.%df"):format(places or 0) local isNegative = num < 0 num = math.abs(num) if num >= 1000000000000 then ret = placeValue:format(num / 1000000000000) .. (full and " trillion" or "T") -- trillion elseif num >= 1000000000 then ret = placeValue:format(num / 1000000000) .. (full and " billion" or "B") -- billion elseif num >= 1000000 then ret = placeValue:format(num / 1000000) .. (full and " million" or "M") -- million elseif num >= 1000 and not full then ret = placeValue:format(num / 1000) .. "k" -- thousand elseif num >= 1 then ret = ("%.0f"):format(num) -- hundreds else ret = num end return (isNegative and "- " or "") .. ret end function GetEMC(link) local items = link.list() if not items then return 0 end if not items[1] then return 0 end return items[1].count or 0 end function ClearScreen(monitor) monitor.clear() monitor.setCursorPos(1, 1) end function NextLine(monitor) local x, y = monitor.getCursorPos() monitor.setCursorPos(1, y + 1) end function WriteCenterAligned(monitor, text) local w, h = monitor.getSize() local x, y = monitor.getCursorPos() monitor.setCursorPos(math.ceil(w / 2 - #text / 2), y) monitor.write(text) end function WriteLeftAligned(monitor, text) local x, y = monitor.getCursorPos() monitor.setCursorPos(1, y) monitor.write(text) end function WriteRightAligned(monitor, text) local w, h = monitor.getSize() local x, y = monitor.getCursorPos() monitor.setCursorPos(w - #text + 1, y) monitor.write(text) end -- Program Code local Users = { {"top", "Glitch"}, {"right", "Collins"}, } for _, user in next, Users do user[3] = peripheral.wrap(user[1]) end local monitor = peripheral.wrap("monitor_0") local graph = peripheral.wrap("monitor_2") local last = 0 local timespan = 1 local timespanFactor = 60 / timespan local Histories = {} function CalculateHistory(name, new, limit) if not Histories[name] then Histories[name] = {} end local history = Histories[name] table.insert(history, new) while #history > limit do table.remove(history, 1) end local sum = 0 for _, v in next, history do sum = sum + v end return sum / #history end function GraphData(monitor, data, title) local w, h = monitor.getSize() local max = -math.huge local min = math.huge for _, v in next, data do if v > max then max = v end if v < min then min = v end end local range = max - min min = min - range * 0.1 max = max + range * 0.1 range = max - min local scale = h / range if range == 0 then scale = 1 end local nData = #data local dataScale = nData / w local lastPos = 0 for i = 1, w do print("monitor " .. i .. " of " .. w) -- get data closest to i local dataIndex = math.floor(i * dataScale) local v = data[dataIndex] or 0 local bar = math.ceil((v - min) * scale) local vPos = math.floor(h - bar + 1) if i > 1 then for j = math.min(vPos, lastPos), math.max(vPos, lastPos) do monitor.setCursorPos(i - 1, j) monitor.blit(" ", "f", "0") end end lastPos = vPos monitor.setCursorPos(i, vPos) monitor.blit(" ", "f", "0") end -- Draw min and max values monitor.setCursorPos(1, 1) monitor.write(ReadableNumber(max, 2, false)) monitor.setCursorPos(1, h) monitor.write(ReadableNumber(min, 2, false)) -- Draw current value local current = data[#data] local currentV = lastPos local text = ReadableNumber(current, 2, false) local textLen = #text local textX = math.floor(w - textLen - 2) monitor.setCursorPos(textX, currentV) monitor.write(text) -- Draw title local titleLen = #title local titleX = math.floor(w / 2 - titleLen / 2) monitor.setCursorPos(titleX, 1) monitor.write(title) end function Graph(monitor, data, title, timeName) local w, h = monitor.getSize() local x, y = monitor.getCursorPos() local max = -math.huge local min = math.huge for _, v in next, data do if v > max then max = v end if v < min then min = v end end local range = max - min min = min - range * 0.1 max = max + range * 0.1 range = max - min local scale = h / range if range == 0 then scale = 1 end local lastPos = 0 for i = 1, #data do local v = data[i] local bar = math.ceil((v - min) * scale) local vPos = math.floor(h - bar + 1) if i > 1 then for j = math.min(vPos, lastPos), math.max(vPos, lastPos) do monitor.setCursorPos(i - 1, j) monitor.blit(" ", "f", "0") end end lastPos = vPos monitor.setCursorPos(i, vPos) monitor.blit(" ", "f", "0") end -- Draw min and max values monitor.setCursorPos(1, 1) monitor.write(ReadableNumber(max, 2, false)) monitor.setCursorPos(1, h) monitor.write(ReadableNumber(min, 2, false)) -- Draw current value local current = data[#data] local currentV = lastPos local text = ReadableNumber(current, 2, false) local textLen = #text local textX = math.floor(w - textLen - 2) monitor.setCursorPos(textX, currentV) monitor.write(text) -- Draw title local titleLen = #title local titleX = math.floor(w / 2 - titleLen / 2) monitor.setCursorPos(titleX, 1) monitor.write(title) -- Footer with time name local footer = ("<- %s %s ->"):format(#data, timeName) local footerLen = #footer local footerX = math.floor(w / 2 - footerLen / 2) monitor.setCursorPos(footerX, h) monitor.write(footer) end -- load list of minutes from file local minutes = {} local log = fs.open("minutes.log", "r") if log then Histories["sum"] = {} local line = log.readLine() while line do table.insert(Histories["sum"], tonumber(line)) line = log.readLine() end log.close() end local tick = 0 while true do ClearScreen(monitor) WriteCenterAligned(monitor, "Energy Matter Covalence") NextLine(monitor) local sum = 0 for n, user in next, Users do WriteLeftAligned(monitor, user[2]) local EMC = GetEMC(user[3]) sum = sum + EMC WriteRightAligned(monitor, ReadableNumber(EMC, 2, false) .. " EMC") NextLine(monitor) end WriteCenterAligned(monitor, ReadableNumber(sum, 2, true) .. " EMC") NextLine(monitor) local difference = (sum - last) local avgDiff = CalculateHistory("diff", difference, timespanFactor) local isNeg = avgDiff < 0 if isNeg then monitor.setTextColour(colors.red) else monitor.setTextColour(colors.green) end last = sum WriteCenterAligned(monitor, (isNeg and "" or "+ ") .. ReadableNumber(avgDiff, 2, true) .. " / minute") monitor.setTextColour(colors.white) graph.setBackgroundColor(colors.black) if tick % timespanFactor == 0 then local w, h = graph.getSize() CalculateHistory("sum", sum, w) ClearScreen(graph) Graph(graph, Histories["sum"], "EMC HISTORY", " minutes") local log = fs.open("minutes.log", "a") log.writeLine(sum) log.close() end tick = tick + 1 sleep(timespan) end