Как разработать графический интерфейс для скриптов R

Хотите, чтобы ваши R-скрипты могли запускать пользователи без навыков программирования? Создайте понятное десктопное приложение.
Язык R предназначен преимущественно для Back End программирования, но на нем можно разработать довольно удобный графический интерфейс. В этой статье я расскажу, какие графические элементы вы можете построить с помощью пакета «gWidgets2», и поделюсь несколькими примерами интерфейса, разработанного в R.
Установка нужных пакетов
Основным пакетом, который мы рассмотрим будет «gWidgets2», который по сути является переписанным «gWidgets».
Но для построения интерфейсов вам понадобится установить несколько пакетов:
- Сначала установить одну из базовых графических библиотек: RGtk2, tcltk или Qt.
- Далее — пакет gWidgets2
- После чего необходимо установить один или несколько пакетов — это интерфейсы к базовым графическим пакетам: «gWidgets2RGtk2», «gWidgets2tcltk», «gWidgets2Qt».
Наиболее простым графическим интерфейсом является tcltk, поэтому мы установим его, и связанные с ним пакеты.
install.packages(\\\'tcltk\\\')
install.packages(\\\'gWidgets2\\\')
install.packages(\\\'gWidgets2tcltk\\\')
Какие элементы интерфейса доступны?
В пакете «gWidgets2» много графических элементов интерфейса — рассмотрим основные.
1. Диалоговое окно — «gwindow» и «gbasicdialog»
Основной и главный контейнер для всех графических элементов интерфейса.
Если вы планируете в дальнейшем запускать разработанный интерфейс с помощью BAT или EXE-файла, рекомендую в качестве главного контейнера использовать «gbasicdialog». При запуске из BAT-файла, элемент интерфейса «gwindow» строится и мгновенно закрывается, не дождавшись действий пользователя.
Все же существует способ, который позволит вам запускать интерфейс с помощью BAT-файла, даже если он построен через «gwindow». Сразу после завершения кода графического интерфейса воспользуетесь комaндой «Sys.sleep(300)», и окно не будет закрываться.
В «gbasicdialog» так же есть один небольшой баг, для закрытия обычного, или диалогового окна вам необходимо использовать функцию dispose(). Но из-за ошибки допущенной в пакете данная функция возвращает ошибку при попытке закрыть «gbasicdialog». Для закрытия диалогового окна вызывайте метод dispose_window() самого диалогового окна, вместо вызова функции dispose(), смотрите пример ниже:
# создаём окно
my_win <- gbasicdialog(\"My Window\",visible = T, do.buttons=FALSE)
# добавляем кнопку для закрытия окна
gbutton(\"Cancel\", container = my_win,handler = function(h,...) {
my_win()
})
Синтаксис:
gwindow(title = \"Window\", visible = TRUE, name=title, width = NULL,
height= NULL, parent=NULL, handler = NULL, action = NULL, ...,
toolkit = guiToolkit())
gbasicdialog(title = \"Dialog\", widget, parent=NULL,
do.buttons=TRUE,handler = NULL, action=NULL, ...,
toolkit=guiToolkit())Основные аргументы:
- title — заголовок диалогового окна;
- visible — видимость диалогового окна, принимает значение «FALSE» или «TRUE». Можно отключить видимость построения окна и всех его элементов и включить после того, как окно будет полностью сформировано с помощью функции visible.
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы данной функции — function(h,...).
2. Кнопка — «gbutton»
Функция «gbutton» создает кнопку в указанном контейнере.
Синтаксис:
gbutton(text = \"\", border=TRUE, handler = NULL, action = NULL,
container = NULL, ..., toolkit = guiToolkit())
Основные аргументы:
- text — текст кнопки;
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы данной функции — function(h,...) ;
- container — контейнер, в котором размещается кнопка.
Пример использования:
obj <- gbutton(\"Hello world\", container = gwindow())
3. Ярлык — «glabel»
Текстовый блок в диалоговом окне, который используется для описания различной информации.
Синтаксис:
glabel(text = \"\", markup = FALSE, editable = FALSE, handler =
NULL,action = NULL, container = NULL, ..., toolkit = guiToolkit())
Основные аргументы:
- text — текст ярлыка;
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы данной функции — function(h,...) ;
- container — контейнер, в который будет помещен ярлык.
Пример использования:
obj <- glabel(\"Hello world\", container = gwindow())
4. Текстовое поле — «gedit»
В диалоговом окне появится текстовое поле, в которое пользователь может ввести свои данные.
Синтаксис:
gedit(text = \"\", width = 25, coerce.with = NULL,
initial.msg=\"\",handler = NULL, action = NULL, container = NULL, ...,
toolkit = guiToolkit())
Основные аргументы:
- text — текст ярлыка.
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы данной функции — function(h,...).
- container — контейнер для текстового поля.
Пример использования:
obj <- gedit(\"Hello world\", container = gwindow())
5. Список с возможностью выбора одного элемента — «gradio»
Список, в котором можно отметить галочкой один элемент.
Синтаксис:
gradio(items, selected = 1, horizontal = FALSE, handler= NULL,action
= NULL, container = NULL, ..., toolkit = guiToolkit())
Основные аргументы:
- items — вектор значений, возможных для выбора;
- selected — числовое значение номера элемента, который будет выбран по умолчанию;
- horizontal — ориентация списка (TRUE — горизонтальная, FALSE — вертикальная) ;
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы данной функции — function(h,...) ;
- container — контейнер, в котором размещается список.
Пример использования:
obj <- gradio(c(\"hello\",\"world\"), container=gwindow())
6. Выпадающий список — «gcombobox»
Выпадающий список — более компактная альтернатива списку, с возможностью выбора одного элемента.
Синтаксис:
gcombobox(items, selected = 1, editable = FALSE, coerce.with=NULL,
handler = NULL, action = NULL, container = NULL, ..., toolkit =
guiToolkit())
Основные аргументы:
- items — вектор значений, возможных для выбора;
- selected — числовое значение номера элемента, который будет выбран по умолчанию;
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы данной функции — function(h,...) ;
- container — контейнер для размещения выпадающего списка.
Пример использования:
obj <- gcombobox(c(\"hello\",\"world\"), container=gwindow())
7. Список с возможностью выбора нескольких элементов — «gcheckboxgroup»
Пакет «gcheckboxgroup» дает возможность пользователю отметить галочками любое количество элементов из списка.
Синтаксис:
gcheckboxgroup(items, checked = FALSE, horizontal = FALSE,
use.table=FALSE, handler = NULL, action = NULL, container = NULL,
..., toolkit = guiToolkit())
Основные аргументы:
- items — вектор значений, возможных для выбора;
- horizontal — ориентация списка (TRUE — горизонтальная, FALSE — вертикальная) ;
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы функции — function(h,...) ;
- container — контейнер для размещения списка.
Пример использования:
obj <- gcheckboxgroup(c(\"hello\",\"world\"), container=gwindow()
8. Календарь — «gcalendar»
С помощью этого элемента удобно выбирать дату.
Синтаксис:
gcalendar(text = \"\", format = \"%Y-%m-%d\", handler=NULL,action=NULL,
container = NULL, ..., toolkit = guiToolkit())
Основные аргументы:
- text — дата по умолчанию;
- format — формат в котором будет задана дата;
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы данной функции — function(h,...) ;
- container — контейнер, в котором размещается календарь.
Пример использования:
obj <- gcalendar(text = as.character(Sys.Date()),container=gwindow())
9. Выбор папки или файла — «gfile»
Этот элемент выводит на экран диалоговое окно для открытия или сохранения файлов и папок.
Синтаксис:
gfile(text = \"\", type = c(\"open\", \"save\", \"selectdir\"),
initialfilename = NULL, filter = list(\"All files\" = list(patterns = c(\"*\")), \"R files\" = list(patterns =
c(\"*.R\",\"*.Rdata\")),
\"text files\" = list(mime.types = c(\"text/plain\")) ),
multi=FALSE, handler = NULL, action = NULL, ..., toolkit =
guiToolkit())
Основные аргументы:
- text — заголовок диалогового окна, открывающегося для выбора файла или папки;
- type — тип диалогового окна, принимает значение «open» (получить путь к файлу), «save» (сохранить объект в виде файла) и «selectdir» (получить путь к папке) ;
- handler — обработчик событий, в котором вы прописываете анонимную функцию, запускающуюся при активации элемента. Обязательные аргументы данной функции — function(h,...).
Пример использования:
obj <- gbutton(\"Select file\", container=gwindow(), handler =
function(h,...) {gfile(text = \"Select file\", type = \"selectdir\")})
Как разработать простой графический интерфейс?
Рассмотрим, как можно применять основные элементы пакета. Для примера создадим текстовое поле с возможностью ввести свое имя и кнопку, при нажатии на которую появится приветственное сообщение.
- В качестве основного контейнера выберем «gwindow».
main_window <- gwindow(title = \"My main windows\")
Функция «gwindow(title = \"My main windows\")» создаст главное диалоговое окно, которое вам предстоит наполнить графическими элементами.
- Сначала добавим текстовый ярлык, чтобы объяснить пользователям, какие данные нужно ввести в этом поле.
Для создания ярлыка используйте функцию «glable(\"Enter your name\", container = main_window)». Первый аргумент отвечает за текст ярлыка. Аргумент container указывает контейнер, в котором будет отображаться ярлык — мы указали «main_window », так как именно в этот объект сохранили созданное на первом шаге диалоговое окно.
- Последний элемент диалогового окна — кнопка «Hello!».
Кнопка создается с помощью функции «gbutton(\"Hello!\", container = main_window, handler = function(h,...)». Первый аргумент отвечает за текст кнопки, второй — указывает контейнер, в котором отобразится кнопка. Аргумент «handler» обpaбатывает событие, а значит в нем нужно описать функцию, которая выполнится при нажатии кнопки:
function(h,...){ gmessage(paste0(\"Hello \",svalue(username),\"!\"))}
Функция выводит на экран сообщение, созданное с помощью функции «gmessage». Чтобы в сообщении появилось имя, заданное пользователем в текстовом поле, я использую функцию «svalue» — она в качестве аргумента принимает объект, значение которого вы хотите получить.
- В результате у вас получится такой код:
#Создаем диалоговое окно
main_window <- gwindow(title = \"My main windows\")
#Добавляем подпись к текстовому полю
glable(\"Enter your name\", container = main_window)
#Добавляем текстовое поле
username <- gedit(\"User name\", container = main_window)
#Добавляем кнопку
gbutton(\"Hello!\", container = main_window, handler = function(h,...){
#Описываем действия которые будут выполнены при нажатие на кнопку
gmessage(paste0(\"Hello \", svalue(username),\"!\"))})
Запустите код в R-консоли или R Studio, и сформируется диалоговое окно.
В текстовом поле можно ввести свое имя и нажать кнопку «Hello!», после чего появится приветственное сообщение.
Пример сложного графического интерфейса, разработанного в R
Пользуясь пакетом «gWidgets2», можно создавать и достаточно сложные интерфейсы.
В этом пункте я поделюсь графическим интерфейсом для запуска скриптов. В диалоговых окнах можно ввести пользовательские параметры, необходимые для подключения к API, выбрать период статистики и конкретные скрипты. После нажатия кнопки «Start» начинается процесс сбора данных.
Скрипт для создания вышеприведенного интерфейса:
library(gWidgets)
library(gWidgetstcltk)
library(lubridate)
options(guiToolkit=\"tcltk\")
#переходим в рабочую директорию
setwd(\"C:/ppc_bi\")
#Период
currentDate <-Sys.Date()
eopm <- currentDate - days(day(currentDate))
sopm <- currentDate - days(day(currentDate))
sopm <- sopm - days(day(sopm) - 1)
#Строим диалоговое окно
win <- gbasicdialog(\"BI Data Uploader System v 1.0\",visible =
F,do.buttons=FALSE)
#Выбор рабочей папки
dirgroup <- gframe(\"Work directory\",container = win,horizontal = T)
workdirblock <- gedit(\"C:/ppc_bi\", container = dirgroup)
gbutton(\"Choice\", container = dirgroup,handler = function(h,...) {
workdir <<- gfile(\"Select directory\",type=\"selectdir\")
svalue(workdirblock) <- workdir
setwd(svalue(workdirblock))})
#Группируем учетные данные
cred_group <- ggroup(container = win)
#Учетные данные MySQL
mysqlgr <- gframe(\"MySQL credentials\",container = cred_group,horizontal = F)glabel(\"Host:\",container = mysqlgr)
host <- gedit(\"\", container = mysqlgr)
glabel(\"User:\",container = mysqlgr)
user <- gedit(\"\", container = mysqlgr)
glabel(\"Pass:\",container = mysqlgr)
pass <- gedit(\"\", container = mysqlgr)
#Учетные данные Google
gagroup <- gframe(\"Google credentials\",container = cred_group,horizontal = F)
glabel(\"Clientid:\",container = gagroup)
clientid <- gedit(\"\", container = gagroup)
glabel(\"Client secret:\",container = gagroup)
clientsecret <- gedit(\"\", container = gagroup)
glabel(\"Adwords API token:\",container = gagroup)
adwords_api_token <- gedit(\"\", container = gagroup)
#ID докса - справочника проектов
doxgroup <- gframe(\"Project dictionary document key\",container = win)
doxid <- gedit(\"\", container = doxgroup, width = 50)
#Установка отчетного периода
grperiod <- gframe(\"Period\",container = win,horizontal = F)
glabel(\"From: \",container = grperiod)
date_from <- gcalendar(text = as.character(sopm), format = \"%Y-%m-%d\", container = grperiod)
glabel(\"To: \",container = grperiod)
date_to <- gcalendar(text = as.character(eopm), format = \"%Y-%m-%d\", container = grperiod)
#Выбор скриптов которые необходимо запустить
grscripts <- gframe(\"Scripts\",container = win,horizontal = T)
scripts <- gcheckboxgroup(c(\"AdWords\",\"Facebook\",\"Direct\",\"QualityScore\",\"LostProfit\",\"Summary\"), container=grscripts)
#Кнопка Start
gbutton(\"Start\", container = win,handler = function(h,...) { dispose(win) for(scrnum in svalue(scripts)){ scriptName <- paste0(scrnum, \".R\") source(scriptName) }})
#Кнопка Cancel
gbutton(\"Cancel\", container = win,handler = function(h,...) { win()})
#Включаем окно
visible(win, set = T)
Выводы
С помощью пакета «gWidgets2» вы сможете организовывать R-скрипты в виде десктопных приложений с понятным интерфейсом.
Доступны такие графические элементы:
- Диалоговое окно, в котором будут содержаться все последующие элементы интерфейса.
- Кнопка с текстовой надписью и функцией, которая будет выполнятся при нажатии.
- Текстовый блок, с помощью которого вы сможете объяснить назначение определенных составляющих интерфейса.
- Текстовое поле для ввода данных.
- Списки с возможностью выбора одного или нескольких элементов.
- Выпадающий список, который позволяет более компактно разместить перечень доступных элементов.
- Календарь для удобного выбора дат и периодов.
- Диалоговое окно для выбора папки или файла.
Перечисленных элементов достаточно для создания интерфейсов, которые упростят работу со скриптами на языке R.
Если вы используете язык R в работе, или планируете его изучить подписывайтесь на мой Telegram и YouTube канал R4marketing, в котором собрано много полезных, русскоязычных материалов по изучению R.
Комментарии:
Лекции о ключевых этапах развития бизнеса в интернете: от создания сайта до подсчета ROMI (возврат маркетинговых инвестиций) рекламных каналов...
01 04 2026 17:36:32
Многие специалисты недооценивают эффективность отчетов Яндекс.Метрики. Очень зря. Вот чем они могут быть полезны....
31 03 2026 10:27:50
Делимся советами по оптимизации рассылок. Важны новые форматы писем, предварительное тестирование, смена тем письма, ярче CTA. Все это в сочетании с понятностью и искренностью не заставит ждать хороший CTR...
30 03 2026 12:45:46
Читать только интернет-маркетологам, SMM, PPC и SEO-специалистам....
29 03 2026 19:43:36
Портал-каталог организаций и его продвижение. В этом кейсе мы детальнее остановимся на выгодах для проекта от синергии усилий клиента и агентских специалистов по контекстной рекламе...
28 03 2026 11:34:12
Лучшие идеи круглого стола о SEO с участием Тараса Гущи, Сергея Карпенко, Алексея Чекушина, Дмитрия Шахова и других экспертов...
27 03 2026 13:39:15
Как пользоваться выбором высокочастотных фраз для метатегов, чисткой мусорных фраз и как расставлять приоритеты для навигационных запросов с указанием определенного направления...
26 03 2026 20:58:14
Ringostat и Binotel. Сравнение главных сервисов для коллтрекинга в Украине...
25 03 2026 12:58:28
Виктория Игнатьева опубликовала новый кейс по продвижению интернет-магазина детской одежды, обуви и товаров: ROMI (возврат маркетинговых инвестиций) 319%....
24 03 2026 12:59:44
Данные из контента страницы и основного заголовка h1 вместо метатега title. Что показало исследование Serpstat....
23 03 2026 20:25:32
Что такое посол бренда и чем он отличается от адвоката бренда?...
22 03 2026 4:25:48
Когда на сайт добавляют новый контент, он тут же трaнcлируется в RSS-ленту и отображается в специальных программах для чтения, либо в email подписчиков. Как это работает?...
21 03 2026 7:33:52
Что нужно знать о целевой аудитории, как грамотно воровать у других и что нужно сделать, чтобы настроить идеальную рекламную кампанию....
20 03 2026 23:20:36
Чтобы проставить 301 редиректы, вначале надо выгрузить весь список топовых страниц по обратным ссылкам...
19 03 2026 19:20:17
Базовые знания, которые нужны, чтобы ресурс понравился поисковикам и пользователям....
18 03 2026 4:34:22
Слорварь сленга, без которого к 25-летним не подходи...
17 03 2026 9:38:59
Продолжаем разговор о том, почему функция «Совмещение данных» в Google Data Studio может работать не так, как вы ожидаете....
16 03 2026 16:41:47
О новых функциях Universal App Campaigns — специально для тех, кто хочет эффективно вовлекать пользователей приложений...
15 03 2026 2:45:24
RFM — это аббревиатура слов Recency, Frequency, Money — новизна, частота, деньги. То есть считаем, как давно клиент купил товар в последний раз, сколько всего покупок он сделал и сколько денег принес нам за все время заказов....
14 03 2026 20:24:19
Экс-CEO, а теперь просто сотрудник и «волшебник страны Moz» Рэнд Фишкин поделился с читателями блога рассказом о своем видении будущего SEO, перспективах анонимизации сети и причудах американских клиентов....
13 03 2026 20:16:41
Как оптимизировать и выжать максимум пользы из сниппетов сайта в выдаче Google и Яндекс...
12 03 2026 16:13:15
20 сервисов для прокачки контента под SEO. Штуки, которые будут полезны новичкам и экспертам....
11 03 2026 7:42:59
Новости агентства Netpeak за предыдущий квартал. Появление отдела веб-аналитики. Открыли услугу «Создание и ведение блогов». Добавили мультивалютность. Глобально изменили скрипт Netpeak X-Reference. Запустили серию писем. Что еще?...
10 03 2026 5:15:12
Директ Коммaндер от Яндекса позволяет легко работать с большими кампаниями...
09 03 2026 7:45:43
Суть бренда на одном дыхании: о рекламе с любовью. Изначально под большой идеей мы пониманием ту пользу, которую несет бренд в окружающий его мир. Помимо этого, большая идея — это те «рельсы», по которым будут ехать все коммуникации бренда в течение нескольких лет...
08 03 2026 13:52:33
Инструкция для трудоголиков для тех, кто старается выполнить как можно больше заданий, а заметного прогресса при этом нет. Работать много и эффективно не всегда полезно. Если бы эффективная работа была залогом успеха, каждому хомяку воздвигли бы памятник...
07 03 2026 15:20:25
Пост по мотивам видео Мэтта Каттса из Google. Из первых рук, как говорится....
06 03 2026 9:48:58
Работа с умными рекламными кампаниями с оплатой за конверсии в контекстно-медийной сети. Особенности настройки и оптимизации в кейсе продвижения недвижимости. Узнать больше!...
05 03 2026 10:28:53
Значит так, делаем из лимонов лимонад — «выжимаем» максимум из ошибки 404...
04 03 2026 18:30:54
Когда email-маркетинг становится точкой роста. Кейс интернет-магазина книг Book24....
03 03 2026 22:37:47
Нейронные сети, нейросети онлайн, сверхточные нейронные сети. Я рассажу, как они устроены, как написать свою нейронную сеть с нуля, как правильно обучить нейронную сеть на имеющихся данных...
02 03 2026 19:56:57
С каждым годом китайские маркетплейсы увеличивают свое влияние, и покупатели всё активней заказывают товары из Поднебесной. Но не всё скидки да покупки — обладатели интернет-аудитории и маркетологи могут еще и хорошо заработать на этих площадках....
01 03 2026 18:36:45
Что делать, когда не получается заставить себя написать статью или кейс...
28 02 2026 7:44:32
У нас на руках оказались все карты для создания собственного мини-рейтинга популярных сервисов email-рассылок....
27 02 2026 17:57:12
Как увеличить охват целевой аудитории ресторана или магазина с помощью рекламы на мобильных и сверхточного геотаргетинга...
26 02 2026 10:41:45
Редполитика Netpeak Journal (ex блог Netpeak) — руководство по написанию понятных, полезных, продающих и удобочитаемых текстов. Документ для внутреннего использования в открытом доступе. Применяйте, адаптируйте. Читать!...
25 02 2026 18:17:56
Как правильно рассчитать окупаемость рекламных кампаний SaaS-продуктов, получить по ним четкую аналитику, и что делать дальше....
24 02 2026 20:31:26
«Случайный» посетитель потому, что может уйти (не сделав покупку) и не вернуться, не стать клиентом. Пуш-уведомления позволяют посетителю сразу стать подписчиком: ему предлагают подписаться на рассылку. Как это использовать? Читайте!...
23 02 2026 1:18:32
Как работать с новой функцией, чтобы набирать подписчиков и делать продажи. Подробное и актуальное руководство в 2021 году....
22 02 2026 2:23:43
Иногда удержать пользователя сложнее, чем мотивировать загрузить приложение. Семь инструментов для анализа Uninstall Rate....
21 02 2026 2:54:38
Опыт стартапа Paperform для стартаперов, которые боятся начать из-за ограниченного бюджета и/или отсутствия знаний в маркетинге. Надеемся, эта история вдохновит предпринимателей и поможет меньше сомневаться на счет запуска без бюджета....
19 02 2026 7:55:14
Знания основных принципов конверсионности сайта, этапов воронки продаж важны для того, чтобы наладить процессы, рост продаж в любом бизнесе. Узнать больше!...
18 02 2026 6:38:19
Относящиеся к низкочастотным long-tail запросы при правильном подходе могут стать эффективным инструментом для увеличения трафика. Рассказываем почему, а главное — как....
17 02 2026 13:51:19
Отслеживаем пропущенные, анализируем входящие и делаем выводы о том, как организовать работу менеджеров....
16 02 2026 9:18:27
Мы решили организовать серию вебинаров по SEO и предоставить их бесплатно. История о том, как с нуля при минимуме затрат создать успешный онлайн-курс...
15 02 2026 0:59:50
Исследование по 38,5 миллионам кликов в 22 тематиках в 391 городе страны....
14 02 2026 4:41:28
Как научиться продвигать мобильные приложения и заpaбатывать на этом....
13 02 2026 7:54:50
Оживший бар. О том, как один украинский бренд за полтора месяца получил более 4 000 фанов!...
12 02 2026 22:19:46
Иногда даже замена блока с промокодом или обновление хедера и футера способны освежить рассылки и принести продажи, заявки, повысить лояльность клиентов. Узнать больше!...
11 02 2026 5:30:29
Еще:
понять и запомнить -1 :: понять и запомнить -2 :: понять и запомнить -3 :: понять и запомнить -4 :: понять и запомнить -5 :: понять и запомнить -6 :: понять и запомнить -7 ::