Fingercomp 4 409 Опубликовано: 16 января, 2017 (изменено) Вот такая красота теперь возможна благодаря моей новой либе charts. Пока что имеем гистограммчики и прогрессбары. У обоих точность до 1/8 символа. Документация Контейнер Сидит в charts.Container. Его задача: хранить базовые параметры типа цвета по умолчанию, самого графика. Собственно, это абстракция над объектами графика. Атрибуты Container.gpu — прокси видеокарты, на которой рисовать график. Container.fg — цвет "текста" по умолчанию. Container.bg — цвет фона по умолчанию. Container.x и Container.y — это координаты левого верхнего угла контейнера. Container.payloadX, Container.payloadY — координаты графика относительно левого верхнего угла контейнера. Пока лучше не трогать, потом что-нибудь с ними придумаю. Container.width, Container.height — ширина и высота, соответственно, графика. Container.payload — сам объект графика. Методы Container:draw() — рисует график. Так как сам по себе бесполезен, пример кода здесь не нужен. Стороны Спит и живёт в charts.sides. Это таблица, которая содержит четыре значения: sides.TOP, sides.BOTTOM, sides.LEFT, sides.RIGHT. Требуется для настройки графиков. Гистограмма Очень прикольная вещь. Рисует вертикальные столбцы шириной в 1 символ с высотой в соответствии с числовым значением из таблицы. Атрибуты Histogram.values — таблица значений гистограммы. Histogram.align — указывает, как брать значения гистограммы. Если здесь выставить sides.LEFT, то будут браться первые w (по ширине контейнера) значений из таблицы и рисоваться в том же порядке. Если же тут будет sides.RIGHT, то будут браться последние w значений из таблицы и рисоваться в том же порядке, но справа. Короче, проще взять и попробовать. Histogram.colorFunc — это задаваемая функция для рассчёта значений цвета столбца и фона в зависимости. Возвращает цвет столбца и цвет фона. Принимает следующие параметры, по порядку: Индекс элемента в таблице значений. Нормализованное значение (от нуля до единицы), или, если хотите, отношение значения к максимальному. Само значение. Объект гистограммы. Объект контейнера. Histogram.min — самое что ни на есть минимальнейшее возможное значение гистограммы. Все значения должны быть больше или равны этому. Histogram.max — самое что ни на есть максимальнейшее возможное значение гистограммы. Все значения должны быть меньше или равны этому. Histogram.level.y — это высота уровня голограммы. По умолчанию равно нулю, так что все столбцы растут вверх, но можно поднять его. Значение ≥ 1 поднимает уровень на соответствующее число символов. Значение в полуинтервале [0; 1) задают нормализованную высоту уровня (например, 0.5 — это посередине гистограммы). Значения меньше нуля отсчитывают уровень с самой верхней позиции, где -1 — это самая высокая точка. Histogram.level.value — это число, значения ниже которого будут отображаться столбиками, направленными вниз, а значения выше — столбиками, направленными вверх. Примеры кода local charts = require("charts") local container = charts.Container() local payload = charts.Histogram() payload.max = 80 payload.align = charts.sides.RIGHT payload.colorFunc = function(index, norm, value, self, container) return 0x20ff20 end container.payload = payload for i = 1, 400, 1 do table.insert(payload.values, math.random(0, 80)) container:draw() os.sleep(.05) end local charts = require("charts") local event = require("event") local gpu = require("component").gpu local container = charts.Container() container.width, container.height = gpu.getViewport() local payload = charts.Histogram() payload.max = 1 payload.min = -1 payload.level.value = 0 payload.level.y = .5 payload.align = charts.sides.RIGHT payload.colorFunc = function(index, perc, value, self, container) return value >= 0 and 0xafff20 or 0x20afff end container.payload = payload for i = 1, math.huge, 1 do table.insert(payload.values, math.sin(math.rad(i * 3))) if #payload.values > container.width then table.remove(payload.values, 1) end container:draw() if event.pull(.05, "interrupted") then break end end Прогресс бар Это прогресс бар. Атрибуты ProgressBar.value — числовое значение прогрессбара. ProgressBar.max — максимальное значение прогрессбара. ProgressBar.min — минимальное значение прогрессбара. ProgressBar.direction — направление прогрессбара. Туда будет стремиться полоска, с этой стороны будет конец прогрессбара. Не запутайтесь: это не сторона начала. ProgressBar.colorFunc — функция, возвращающая цвет полоски и фона прогрессбара для переданных аргументов: Самое значение прогрессбара. Нормализованное значение. Объект прогрессбара. Объект контейнера. Пример кода local charts = require("charts") local term = require("term") local event = require("event") local cleft = charts.Container() cleft.x, cleft.y, cleft.width, cleft.height = 1, 1, 50, 2 local pleft = charts.ProgressBar() pleft.direction = charts.sides.LEFT pleft.value = 0 pleft.colorFunc = function(_, perc) if perc >= .9 then return 0x20afff elseif perc >= .75 then return 0x20ff20 elseif perc >= .5 then return 0xafff20 elseif perc >= .25 then return 0xffff20 elseif perc >= .1 then return 0xffaf20 else return 0xff2020 end end cleft.payload = pleft local cright = charts.Container() cright.x, cright.y, cright.width, cright.height = 1, 4, 50, 2 local pright = charts.ProgressBar() pright.direction = charts.sides.RIGHT pright.value = 0 pright.colorFunc = pleft.colorFunc cright.payload = pright local ctop = charts.Container() ctop.x, ctop.y, ctop.width, ctop.height = 55, 1, 2, 20 local ptop = charts.ProgressBar() ptop.direction = charts.sides.TOP ptop.value = 0 ptop.colorFunc = pleft.colorFunc ctop.payload = ptop local cbottom = charts.Container() cbottom.x, cbottom.y, cbottom.width, cbottom.height = 59, 1, 2, 20 local pbottom = charts.ProgressBar() pbottom.direction = charts.sides.BOTTOM pbottom.value = 0 pbottom.colorFunc = pleft.colorFunc cbottom.payload = pbottom for i = 0, 100, 1 do term.clear() cleft.gpu.set(5, 10, "Value: " .. ("%.2f"):format(i / 100) .. " [" .. ("%3d"):format(i) .. "%]") cleft.gpu.set(5, 11, "Max: " .. pleft.min) cleft.gpu.set(5, 12, "Min: " .. pleft.max) pleft.value, pright.value, ptop.value, pbottom.value = i / 100, i / 100, i / 100, i / 100 cleft:draw() ctop:draw() cright:draw() cbottom:draw() if event.pull(0.05, "interrupted") then term.clear() break end end event.pull("interrupted") term.clear() Это были два вида графического представления данных, самых распространённых в программах для OpenComputers. Так что теперь вам, слава коду, не придётся больше никогда писать опять свои ловисипеды для этого. Либу, однако, я продолжу допиливать. У меня есть ещё несколько идей насчёт очень крутых фич, которые я как-нибудь потом реализую. Установка Установите hpm: http://computercraft.ru/topic/1855-repozitorii-programm-hel/?do=findComment&comment=27287 Поставьте пакет с помощью данной команды: hpm install charts. Изменено 16 января, 2017 пользователем Fingercomp 7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 155 Опубликовано: 16 января, 2017 А где ссылка на пакет в репозитории? А вот же она! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
nailfor 50 Опубликовано: 9 мая, 2017 (изменено) Пример для гистограммы не рабочий. Запустилось вот в таком варианте: local charts = require("charts") local container = charts.Container { payload = charts.Histogram() payload.max = 80 payload.align = charts.sides.RIGHT payload.colorFunc = function(index, norm, value, self, container) return 0x20ff20 end } local payload = container.payload for i = 1, 400, 1 do table.insert(payload.values, math.random(0, 80)) container:draw() os.sleep(.05) end В библиотеке имеется функция getMinMax судя из названия и по коду, должна возвращать пару чисел, а возвращает только максимум. Не используется в библиотеке. Нет автоматического масштабирования, буду прикручивать... Изменено 9 мая, 2017 пользователем nailfor Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Fingercomp Автор темы 4 409 Опубликовано: 10 мая, 2017 И в самом деле, забыл в Container добавить проверку на nil перед использованием функции patch. Исправил эту багу и удалил ненужную функцию (я тогда думал, как бы получше реализовать гистограммы) в @1.3.1. Автоматическое масштабирование я делать не стал, так как я не знаю, как нужно оно энд-юзеру. Нужно ли ему, например, вытянуть часть графика за левелом, сделать единый масштаб или как-либо ещё. Так что просто нужно пробежаться по всем значениям и выставить нужные параметры. local min, max = 0, 0 for _, v in pairs(hist.values) do min, max = math.min(min, v), math.max(max, v) end max = max + (min == max and 1 or 0) hist.min = min hist.max = max Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
nailfor 50 Опубликовано: 10 мая, 2017 Автоматическое масштабирование я делать не стал, так как я не знаю, как нужно оно энд-юзеру. Нужно ли ему, например, вытянуть часть графика за левелом, сделать единый масштаб или как-либо ещё. Можно непосредственно в :draw() передать параметр и пусть программист сам решает. Пробежаться по параметрам конечно можно, но это уже далается в самом draw(), можно сделать это в один проход - отрисовать текущий вызов с тем что имеется в max, а по окончанию получить новое максимальное значение, которое будет использовано в следующем вызове. Это сэкономит время на прохождение таблицы. Еще странно, что таблица values отдана на откуп пользователю: нужно следить за ее объемом, хотя она предназначена только для чарта, значит он и должен следить за ее очищением и заполнением. Т.е. я думаю что правильнее было бы передать текущее значение в чарт, а библиотека, в соответствии с настройками, сама решит что с ним делать, запишет в таблицу и удалит когда нужно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах