diff --git a/build.sh b/build.sh index 54d44e8..8afaa59 100755 --- a/build.sh +++ b/build.sh @@ -30,5 +30,9 @@ mkdir -p dist/release luamin -f dist/telem.lua > dist/release/telem.min.lua luamin -f dist/vendor.lua > dist/release/vendor.min.lua +echo 'publishing to computer #0...' +cp dist/telem.lua /home/codespace/.local/share/craftos-pc/computer/0/telem/init.lua +cp dist/vendor.lua /home/codespace/.local/share/craftos-pc/computer/0/telem/vendor.lua + # echo 'tarring...' # tar -cf src.tar src \ No newline at end of file diff --git a/src/telem/lib/output.lua b/src/telem/lib/output.lua index 93558bd..513a715 100644 --- a/src/telem/lib/output.lua +++ b/src/telem/lib/output.lua @@ -8,6 +8,7 @@ return { -- Basalt basalt = { label = require 'telem.lib.output.basalt.LabelOutputAdapter', + graph = require 'telem.lib.output.basalt.GraphOutputAdapter', }, -- Plotter diff --git a/src/telem/lib/output/basalt/GraphOutputAdapter.lua b/src/telem/lib/output/basalt/GraphOutputAdapter.lua new file mode 100644 index 0000000..595b641 --- /dev/null +++ b/src/telem/lib/output/basalt/GraphOutputAdapter.lua @@ -0,0 +1,131 @@ +local o = require 'telem.lib.ObjectModel' +local t = require 'telem.lib.util' + +local OutputAdapter = require 'telem.lib.OutputAdapter' +local MetricCollection = require 'telem.lib.MetricCollection' + +local GraphOutputAdapter = o.class(OutputAdapter) +GraphOutputAdapter.type = 'GraphOutputAdapter' + +GraphOutputAdapter.MAX_ENTRIES = 50 +GraphOutputAdapter.SCALE_TICK = 10 + +local function graphtrackrange (self) + local min = self.graphdata[1] + local max = self.graphdata[1] + + for k,v in ipairs(self.graphdata) do + if v < min then min = v end + if v > max then max = v end + end + + return min,max +end + +function GraphOutputAdapter:constructor (frame, filter, bg, fg, fontSize) + self:super('constructor') + + self.bBaseFrame = assert(frame, 'Frame is required') + self.filter = assert(filter, 'Filter is required') + + self.graphdata = {} + + self:register(bg, fg, fontSize) +end + +function GraphOutputAdapter:register (bg, fg, fontSize) + local currentmin = 0 + local currentmax = 1000 + + self.tick = 0 + + self.bInnerFrame = self.bBaseFrame:addFrame() + :setBackground(bg) + :setSize('{parent.w}', '{parent.h}') + + local fGraph = self.bInnerFrame:addFrame('fGraph'):setBackground(colors.black) + :setPosition(1,1) + :setSize('{parent.w - 2}', '{parent.h - 6}') + + local fLabel = self.bInnerFrame:addFrame('fLabel'):setBackground(colors.black) + :setSize('{parent.w - 2}', 4) + :setPosition(1,'{parent.h - 5}') + + local fLabelMax = self.bInnerFrame:addFrame('fLabelMax'):setBackground(colors.black) + :setSize(6, 1) + :setPosition('{parent.w - 7}',1) + + local fLabelMin = self.bInnerFrame:addFrame('fLabelMin'):setBackground(colors.black) + :setSize(6, 1) + :setPosition('{parent.w - 7}','{fLabel.y - 2}') + + self.label = fLabel:addLabel() + :setText("-----") + :setPosition('{parent.w/2-self.w/2}', 2) + :setForeground(colors.white) + :setBackground(colors.black) + + self.graph = fGraph:addGraph() + :setPosition(1,1) + :setSize('{parent.w - 1}', '{parent.h - 1}') + :setMaxEntries(self.MAX_ENTRIES) + :setBackground(colors.black) + :setGraphColor(colors.red) + :setGraphSymbol('\127') + + self.graphscale = fGraph:addGraph() + :setGraphType('scatter') + :setPosition(1,'{parent.h - 1}') + :setSize('{parent.w - 1}', 2) + :setMaxEntries(self.MAX_ENTRIES) + :setBackground(colors.transparent) + :setGraphSymbol('|') + + self.labelmax = fLabelMax:addLabel() + :setPosition(1,1) + :setText('-----') + :setForeground(colors.white) + :setBackground(colors.black) + + self.labelmin = fLabelMin:addLabel() + :setPosition(1,1) + :setText('-----') + :setForeground(colors.white) + :setBackground(colors.black) + + self.graph:setMinValue(currentmin):setMaxValue(currentmax) +end + +function GraphOutputAdapter:write (collection) + assert(o.instanceof(collection, MetricCollection), 'Collection must be a MetricCollection') + + local resultMetric = collection:find(self.filter) + + assert(resultMetric, 'could not find metric') + + t.constrainAppend(self.graphdata, resultMetric.value, self.MAX_ENTRIES) + + local newmin, newmax = graphtrackrange(self) + + self.graph:setMinValue(newmin):setMaxValue(newmax) + + self.graph:addDataPoint(resultMetric.value) + + self.label:setFontSize(2) + self.label:setText(t.shortnum(resultMetric.value)) + + if self.tick == self.SCALE_TICK then + self.graphscale:addDataPoint(100) + self.tick = 1 + else + self.graphscale:addDataPoint(50) + self.tick = self.tick + 1 + end + + self.labelmax:setText(t.shortnum(newmax)) + self.labelmin:setText(t.shortnum(newmin)) + + return self +end + +return GraphOutputAdapter \ No newline at end of file diff --git a/src/telem/lib/output/plotter/ChartLineOutputAdapter.lua b/src/telem/lib/output/plotter/ChartLineOutputAdapter.lua index 73b84b9..4a0d3e9 100644 --- a/src/telem/lib/output/plotter/ChartLineOutputAdapter.lua +++ b/src/telem/lib/output/plotter/ChartLineOutputAdapter.lua @@ -95,7 +95,7 @@ function ChartLineOutputAdapter:write (collection) local minrange = 0.000001 if not flatlabel then - flatlabel = tostring(actualmin) + flatlabel = t.shortnum2(actualmin) end actualmin = actualmin - minrange / 2 @@ -113,19 +113,21 @@ function ChartLineOutputAdapter:write (collection) self.plotter:chartLine(self.plotData, self.MAX_ENTRIES, actualmin, actualmax, self.fg) - local maxString = tostring(actualmax) - local minString = tostring(actualmin) + local maxString = t.shortnum2(actualmax) + local minString = t.shortnum2(actualmin) self.win.setVisible(false) self.plotter:render() + self.win.setTextColor(self.fg) + self.win.setBackgroundColor(self.bg) if not flatlabel then self.win.setCursorPos(self.plotter.box.term_width - #maxString + 1, 1) - self.win.write(actualmax) + self.win.write(maxString) self.win.setCursorPos(self.plotter.box.term_width - #minString + 1, self.plotter.box.term_height) - self.win.write(actualmin) + self.win.write(minString) else self.win.setCursorPos(self.plotter.box.term_width - #flatlabel + 1, self.plotter.math.round(self.plotter.box.term_height / 2)) self.win.write(flatlabel) diff --git a/src/telem/lib/util.lua b/src/telem/lib/util.lua index 9cb48e3..d3f8526 100644 --- a/src/telem/lib/util.lua +++ b/src/telem/lib/util.lua @@ -61,6 +61,44 @@ local function shortnum(n) end end +-- based on https://rosettacode.org/wiki/Suffixation_of_decimal_numbers#Python +local function shortnum2(num, digits, base) + if not base then base = 10 end + + local suffixes = {'', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'X', 'W', 'V', 'U', 'googol'} + + local exponent_distance = 10 + if base == 2 then + exponent_distance = 10 + else + exponent_distance = 3 + end + + num = string.gsub(num, ',', '') + local num_sign = string.sub(num, 1, 1) == '+' or string.sub(num, 1, 1) == '-' and string.sub(num, 1, 1) or '' + + num = math.abs(tonumber(num)) + + local suffix_index = 0 + if base == 10 and num >= 1e100 then + suffix_index = 13 + num = num / 1e100 + elseif num > 1 then + local magnitude = math.floor(math.log(num, base)) + suffix_index = math.min(math.floor(magnitude / exponent_distance), 12) + num = num / (base ^ (exponent_distance * suffix_index)) + end + + local num_str = '' + if digits then + num_str = string.format('%.' .. digits .. 'f', num) + else + num_str = string.format('%.3f', num):gsub('0+$', ''):gsub('%.$', '') + end + + return num_sign .. num_str .. suffixes[suffix_index + 1] .. (base == 2 and 'i' or '') +end + local function constrainAppend (data, value, width) local removed = 0 @@ -81,5 +119,6 @@ return { skpairs = skpairs, sleep = os.sleep or tsleep, shortnum = shortnum, + shortnum2 = shortnum2, constrainAppend = constrainAppend, } \ No newline at end of file