<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="uk">
	<id>https:///index.php?action=history&amp;feed=atom&amp;title=%D0%A0%D0%B8%D1%81%D1%83%D0%B5%D0%BC_%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%BA%D0%B8</id>
	<title>Рисуем графики - Історія редагувань</title>
	<link rel="self" type="application/atom+xml" href="https:///index.php?action=history&amp;feed=atom&amp;title=%D0%A0%D0%B8%D1%81%D1%83%D0%B5%D0%BC_%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%BA%D0%B8"/>
	<link rel="alternate" type="text/html" href=""/>
	<updated>2026-05-05T12:28:19Z</updated>
	<subtitle>Історія редагувань цієї сторінки в вікі</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id></id>
		<title>Sv в 18:28, 23 квітня 2021</title>
		<link rel="alternate" type="text/html" href=""/>
		<updated>2021-04-23T18:28:59Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Нова сторінка&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Файл:Programming graphs.png|мини]]&lt;br /&gt;
Нарисовать график несложно. Это делается в 2 шага:&lt;br /&gt;
# Подготавливаем данные и сохраняем в базе данных&lt;br /&gt;
# Выводим график :)&lt;br /&gt;
&lt;br /&gt;
Поставим задачу: вывести график количества платежей на каждый день.&lt;br /&gt;
&lt;br /&gt;
Количество платежей по дням:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(time))) tm, COUNT(*) n&lt;br /&gt;
FROM pays GROUP BY tm ORDER BY tm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пояснение:&lt;br /&gt;
# Платежи хранятся в таблице pays&lt;br /&gt;
# COUNT(*) n - считает количество записей и записывает в &amp;quot;переменную&amp;quot; n (запись в n исключительно для удобства)&lt;br /&gt;
# UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(time))) tm - довольно сложная конструкция. Проанализируем по частям:&lt;br /&gt;
#* Поле time хранит и дату и время платежа. А нам нужна только дата. Т.е. нужно отбросить время&lt;br /&gt;
#* Время можно отбросить командой DATE()&lt;br /&gt;
#* Проблема в том, что NoDeny для уменьшения размера данных везде хранит время в виде называемом unixtimestamp. По сути это число (которое указывает на количество секунд прошедших с 01.01.1970). Команда DATE() принимает не unixtimestamp, а дату&lt;br /&gt;
#* FROM_UNIXTIME(time) преобразует unixtimestamp в дату&lt;br /&gt;
#* UNIX_TIMESTAMP() делает обратное преобразование даты в unixtimestamp&lt;br /&gt;
#* Таким образом, SELECT UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(time))) - преобразование в дату, отбрасывание времени, преобразование в unixtimestamp&lt;br /&gt;
# GROUP BY tm - группирует результат по дням (дни мы записали в &amp;quot;переменную&amp;quot; tm)&lt;br /&gt;
&lt;br /&gt;
Кроме sql нам нужно дать имя графику. Это просто уникальная последовательность символов. Назовем график pays_stat.&lt;br /&gt;
&lt;br /&gt;
Теперь напишем код. Создадим файл /usr/local/nodeny/web/demo.pl и дадим ему права на чтение вебсервером. Содержимое файла:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use strict;&lt;br /&gt;
use JSON;&lt;br /&gt;
&lt;br /&gt;
sub go&lt;br /&gt;
{&lt;br /&gt;
 my($url) = @_;&lt;br /&gt;
&lt;br /&gt;
 my $graph_name = 'pays_stat';&lt;br /&gt;
&lt;br /&gt;
 if( !ses::input('make') )&lt;br /&gt;
 {&lt;br /&gt;
    my $param = to_json({&lt;br /&gt;
        a       =&amp;gt; 'ajGraph',&lt;br /&gt;
        domid   =&amp;gt; 'main_block',&lt;br /&gt;
        group   =&amp;gt; $graph_name,&lt;br /&gt;
        y_title =&amp;gt; 'кол-во',&lt;br /&gt;
        type    =&amp;gt; 1&lt;br /&gt;
    });&lt;br /&gt;
    Doc-&amp;gt;template('base')-&amp;gt;{document_ready} .= &amp;quot;nody.ajax($param);&amp;quot;;&lt;br /&gt;
    return;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 my $points = [];&lt;br /&gt;
 my $db = Db-&amp;gt;sql(&lt;br /&gt;
    &amp;quot;SELECT UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(time))) tm, COUNT(*) n &amp;quot;.&lt;br /&gt;
    &amp;quot;FROM pays GROUP BY tm ORDER BY tm&amp;quot;&lt;br /&gt;
 );&lt;br /&gt;
 while( my %p = $db-&amp;gt;line ) { push @$points, [ 1000*$p{tm}, $p{n} ]; }&lt;br /&gt;
&lt;br /&gt;
 Save_webses_data(&lt;br /&gt;
    module=&amp;gt;'ajGraph', data=&amp;gt;{ points=&amp;gt;$points, group=&amp;gt;$graph_name, descr=&amp;gt;'Количество платежей' }&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
 $url-&amp;gt;redirect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Давайте проверим работу, а потом поясним как оно работает. В браузере открываем:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
https://xxx.xx/cgi-bin/stat.pl?a=demo&amp;amp;make=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
make=1 заставит сформировать график и записать его в базу. Если дальше просто открывать&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
https://xxx.xx/cgi-bin/stat.pl?a=demo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
- будет показываться уже сформированный график.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим код. Это, как вы поняли, имя графика мы записали в переменную graph_name:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
my $graph_name = 'pays_stat';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if( !ses::input('make') )&lt;br /&gt;
{&lt;br /&gt;
    XXX&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ses::input() - это функция получения GET и POST параметров. В данном случае из url-а получаем параметр make и если он не установлен (восклицательный знак - это проверка &amp;quot;не установлен&amp;quot;), то выполняется код XXX, а именно:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
my $param = to_json({&lt;br /&gt;
    a       =&amp;gt; 'ajGraph',&lt;br /&gt;
    domid   =&amp;gt; 'main_block',&lt;br /&gt;
    group   =&amp;gt; $graph_name,&lt;br /&gt;
    y_title =&amp;gt; 'кол-во',&lt;br /&gt;
    type    =&amp;gt; 1&lt;br /&gt;
});&lt;br /&gt;
Doc-&amp;gt;template('base')-&amp;gt;{document_ready} .= &amp;quot;nody.ajax($param);&amp;quot;;&lt;br /&gt;
return;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Здесь все, что вы можете поменять:&lt;br /&gt;
* group - имя графика&lt;br /&gt;
* y_title - подпись к оси Y на графике&lt;br /&gt;
&lt;br /&gt;
Этот код выведет на экран все графики (их может быть несколько) с именем $graph_name.&lt;br /&gt;
&lt;br /&gt;
Переходим к формированию графика. Вот такая конструкция выполняет sql:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
my $db = Db-&amp;gt;sql(...);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так мы проходимся по всем строкам результата и каждую строку записываем в переменную %p:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
while( my %p = $db-&amp;gt;line ) { ... }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Переменная $points - указатель на массив. Чтобы использовать ее как массив ставим спереди символ &amp;quot;@&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
push @$points, [ 1000*$p{tm}, $p{n} ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Структура данных для графика: [время в миллисекундах, значение по оси Y]. Умножаем на 1000 чтобы перевести секунды в миллисекунды&lt;br /&gt;
&lt;br /&gt;
Запись графика в базу данных:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Save_webses_data(&lt;br /&gt;
    module=&amp;gt;'ajGraph', data=&amp;gt;{ points=&amp;gt;$points, group=&amp;gt;$graph_name, descr=&amp;gt;'Количество платежей' }&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* module=&amp;gt;'ajGraph' - модуль, который будет рисовать график&lt;br /&gt;
* descr=&amp;gt;'Количество платежей' - заголовок графика&lt;br /&gt;
&lt;br /&gt;
Переход редиректом на текущую страницу, но без параметра make=1&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$url-&amp;gt;redirect();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sv</name></author>
	</entry>
</feed>