Перейти к публикации
Форум - ComputerCraft
Fingercomp

Библиотека для создания гистограмм и прогрессбаров

Рекомендованные сообщения

 

 

C0nTFmj.png


XFQ0Lnt.png


SCnOt85.png

 

 

 

Вот такая красота теперь возможна благодаря моей новой либе 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. Так что теперь вам, слава коду, не придётся больше никогда писать опять свои ловисипеды для этого. Либу, однако, я продолжу допиливать. У меня есть ещё несколько идей насчёт очень крутых фич, которые я как-нибудь потом реализую.

 

Установка

  1. Установите hpm: http://computercraft.ru/topic/1855-repozitorii-programm-hel/?do=findComment&comment=27287
  2. Поставьте пакет с помощью данной команды: hpm install charts.
Изменено пользователем Fingercomp
  • Like 7

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Пример для гистограммы не рабочий.

Запустилось вот в таком варианте:

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 судя из названия и по коду, должна возвращать пару чисел, а возвращает только максимум.

Не используется в библиотеке.

 

Нет автоматического масштабирования, буду прикручивать...

Изменено пользователем nailfor

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

И в самом деле, забыл в 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Автоматическое масштабирование я делать не стал, так как я не знаю, как нужно оно энд-юзеру. Нужно ли ему, например, вытянуть часть графика за левелом, сделать единый масштаб или как-либо ещё.

 

Можно непосредственно в :draw() передать параметр и пусть программист сам решает.

Пробежаться по параметрам конечно можно, но это уже далается в самом draw(), можно сделать это в один проход - отрисовать текущий вызов с тем что имеется в max, а по окончанию получить новое максимальное значение, которое будет использовано в следующем вызове. Это сэкономит время на прохождение таблицы.

Еще странно, что таблица values отдана на откуп пользователю: нужно следить за ее объемом, хотя она предназначена только для чарта, значит он и должен следить за ее очищением и заполнением. Т.е. я думаю что правильнее было бы передать текущее значение в чарт, а библиотека, в соответствии с настройками, сама решит что с ним делать, запишет в таблицу и удалит когда нужно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

×