tel8618217223380 / oasychev-moodle-plugins

Automatically exported from code.google.com/p/oasychev-moodle-plugins
0 stars 0 forks source link

Поддержка шаблонов в инструментах авторинга #312

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Нужно реализовать следующую 
функциональность:
Храним (в БД, а пока можно захардкодить) 
наборы соответствий типа 
number  - \d*\.\d* . 
Соответственно некоторая запись в регексе 
с использованием комментариев (или другой 
вариант - например flex использовал фигурные 
скобки, но тогда их эскейпить надо) будет 
преобразовываться в содержимое шаблона - 
например (?#$$word$$)

Шаблоны могут содержать нумерованные 
плейсхолдеры - место, в котором может 
стоять любое корректное регулярное 
выражение. Например в словаре шаблонов 
может быть описано типа 
parens - ((?#$$1$$)|\((?R)\)) 
будет использовать плейсхолдер с номером 1.
В регулярном выражении при задании такого 
шаблона необходимо указать значение 
плейсхолдера. Значение должно быть вне 
комментария, т.к. коммент закрывается любой 
скобкой. Здесь вопрос как лучше. Вариант (но 
длинновато)
(?#$$parens$$)(?#$$1)abc(?#1$$)

Ваши предложения? Кто короче предложит 
вариант записи шаблона с плейсхолдером в 
регексе?

Нам необходима будет новая опция в режиме 
парсинга - учитывать ли шаблоны. И 
возможность сгенерировать текст регекса 
при подстановке шаблона, а также 
возможность показать их как узлы в 
инструментах авторинга - т.е. будут два 
новых типа preg-узла - preg_template_leaf и 
preg_template_operator (они используются 
инструментами авторинга для отображения 
шаблонов, матчер же их заменяет на реальные 
значения).

Решать надо срочно, т.к. желательно к релизу 
сделать хотя бы для захардкоденных 
шаблонов (включая плейсхолдеры!) 
возможность вводить их и получать 
результирующий регекс.

Original issue reported on code.google.com by oasyc...@gmail.com on 3 Dec 2014 at 9:51

GoogleCodeExporter commented 9 years ago
У меня пока что вопрос - что если нам надо 
подряд несколько шаблонов parens? Они же будет 
иметь разные подстановки для плейсхолдера. 
Я так понимаю, что плейсхолдер $$1$$ надо тоже 
уметь задавать во время редактирования.

Original comment by vostreltsov@gmail.com on 6 Dec 2014 at 10:17

GoogleCodeExporter commented 9 years ago
И чуть более короткий вариант для задания 
значения плейсхолдера - (?#$$1abc). То есть если 
видим запись (?#$$n то всё что до конца 
коммента - это регекс.

Original comment by vostreltsov@gmail.com on 6 Dec 2014 at 10:19

GoogleCodeExporter commented 9 years ago
Смысл плейсхолдера - это та часть шаблона, 
которая задается не в описании шаблона, а в 
конкретном регексе. Параметризованный 
шаблон.

Укорачивать и уточнять синтаксис 
плейсхолдеров нужно. Возможно по принципу 
функций в Си - круглая скобка вместе с 
названием, потом разделители-комменты (а не 
имена плейсхолдеров), потом закрывающая 
скобка. Причем именно скобки и разделители 
(запятые) должны быть комментами, значения 
плейсхолдеров между ними должны быть 
обычными регексами.

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

Original comment by oasyc...@gmail.com on 7 Dec 2014 at 10:51

GoogleCodeExporter commented 9 years ago
оба синтаксиса какието очень нечитаемые.
Есть 2 предложения:
1) 
Простые шаблоны:
(?#<pattern_name>)

Шаблоны с плейсхолдерами:
(?#<pattern_name>inner_regex)

Описание плейсхолдера при определении 
шаблона
(?#<placeholder>)
2) json
Простые шаблоны:
(?#{name: "patternname"})

Шаблоны с плейсхолдерами:
(?#{name: "patternname", placeholder1: "blablabla"})

Описание плейсхолдера при определении 
шаблона
(?#{placeholder: "placeholder1"})

Original comment by TOPT.iiiii on 9 Dec 2014 at 2:45

GoogleCodeExporter commented 9 years ago
Я уже писал почему нельзя размещать 
значение плейсхолдера (по сути - параметра 
функции) внутри коммента - оно нарушит 
синтаксис.

Пока я вижу самое простое - использовать 
синтаксис функции - нумеровать 
плейсхолдеры и в скобках писать:
(?#$$templatename()placeholder1_value(?#$$,)placehodler2_value(?#$$)
* примечание - закрывающая круглая скобка я 
так понимаю не может быть частью коммента 
регекса, поэтому в последнем просто $$. 
Доллары нужны чтобы отличить специальные 
комменты шаблонов от обычных комментов.
Плейсхолдер - это по сути параметр шаблона, 
т.е. при определении шаблона задается его 
номер (название) в нужных местах шаблона; а 
при вставке шаблона в регекс задается 
значение плейсхолдера в виде 
произвольного регулярного выражения.

Original comment by oasyc...@gmail.com on 9 Dec 2014 at 2:59

GoogleCodeExporter commented 9 years ago
Да, можно еще квадратные или фигурные 
скобки вместо круглых, тогда закрывающая 
тоже поместиться. Круглые скобки и запятые 
я взял по аналогиями с функциями С++, это 
универсальный синтаксис позволяющий 
внутри значения плейсхолдера вставлять 
новые шаблоны со своими плейсхолдерами.

Original comment by oasyc...@gmail.com on 9 Dec 2014 at 3:01

GoogleCodeExporter commented 9 years ago
есть еще предложение - использовать 
квадратные скобки.
То есть, в режиме использования шаблоном, 
мы говорим, что если первый символ 
символьного класса, например, # - то это уже 
не символьный класс а шаблон.

Например

[#patternname]

[#patternname#placeholder1#placeholder2] или
[#patternname[placeholder1][placeholder2]]

это позволит избавиться от странностей 
вроде той, что в конце комментария может не 
быть круглой скобки. И это уменьшит размер 
шаблонов...
  ***
Еще предложение в варианте
(?#$$templatename()placeholder1_value(?#$$,)placehodler2_value(?#$$)
не использовать доллары:
(?##templatename()placeholder1_value(?##,)placehodler2_value(?##)

(мне не нравятся доллары, кажется, они 
усложняют читаемость в миллиард раз)

Original comment by TOPT.iiiii on 10 Dec 2014 at 4:11

GoogleCodeExporter commented 9 years ago
Манером с квадратными скобками вы 
нарушаете обратную совместимость - то, что 
раньше было корректными символьными 
классами становится чем-то непонятным; к 
тому же совершенно неясно какие правила 
эскейпинга применять к значениям 
плейсхолдеров - как внутри симв. класса 
(потому что внутри) или как обычно (потому 
что это обычный регекс, а вовсе не часть 
симв. класса). Очень проблемный подход.

Использовать вместо доллара дублирование 
решетки можно, может быть три раза ее 
повторить. Общий смысл долларов или лишних 
решеток - сделать крайне маловероятным 
совпадение обычного коммента с шаблоном. 

Original comment by oasyc...@gmail.com on 10 Dec 2014 at 9:00

GoogleCodeExporter commented 9 years ago
Новые узлы шаблонов для авторинга 
создаются, просьба всем оперативно 
написать их отображение в инструментах 
авторинга.

Сначала каждый пишет здесь свои 
предложения по внешнему виду (граф/дерево) 
и необходимым строкам (описание, а также 
надписи в графе и тултипы в дереве); потом 
реализуем.

Поскольку для релиза то надо сделать 
быстро - в течении недели...

Original comment by oasyc...@gmail.com on 4 Jan 2015 at 7:23

GoogleCodeExporter commented 9 years ago
Появился новый класс шаблона, который 
позволяет хранить их захардкоденными.
Пахомову после общего обсуждения строк 
добавить туда поля для хранения строк с 
описаниями в естественном падеже. 
Посмотрите есть ли в Moodle filter/multilang или 
что-то подобное, там может быть способ 
записи строки с текстами на нескольких 
языках. Не использовать get_string здесь 
логично, ибо в будущем эти строки будет 
вводить пользователь. Только сначала 
согласовать строки, чтобы не повторяться а 
по максимум использовать те же для графа, 
тултипа дерева и описания.

Original comment by oasyc...@gmail.com on 5 Jan 2015 at 12:17

GoogleCodeExporter commented 9 years ago
Еще пара моментов, которые надо уточнить.

1) Шаблонам нужны свои личные опции, потому 
что можно писать хоть в обычной, хоть в extended 
нотации, и так далее. Предлагаю строковое 
поле $options рядом с $regex.

2) Нужно ли уметь использовать шаблоны 
внутри описания шаблона? Именно описания, а 
не вложенных вызовов. Там тогда получается 
нужно кучу дополнительных проверок 
городить, и пока не совсем понятно как это 
вообще парсить.

Original comment by vostreltsov@gmail.com on 6 Jan 2015 at 11:30

GoogleCodeExporter commented 9 years ago
1) реализовано, 2) в первом приближении тоже

Вот такой вопрос нумерации подвыражений. 
Допустим, есть:

'parens_req' => new qtype_preg\template('parens_req', '(   \(    (?:$$1|(?-1))  
 \)  )', 'x', 1),
'parens_opt' => new qtype_preg\template('parens_opt', 
'$$1|(?###parens_req<)$$1(?###>)', '', 1),

И простое использование:

(?###parens_opt<)(a)(?###>)

Правильно ли, номер 1 идет на левый операнд 
альтернативы, 2 - это обертка parens_req, 3 - это 
исходный (a) уже в качестве операнда вместо 
$$1?
Просто получается, что записанное в строке 
в одном месте выражение размножается на 
несколько поддеревьев в разными номерами. 
Можно, конечно, решить этот конкретный 
случай вызовом подвыражения но как-то 
странно это всё равно.

Original comment by vostreltsov@gmail.com on 8 Jan 2015 at 12:32

GoogleCodeExporter commented 9 years ago
Ну по логике вещей правильно. Другое дело 
что лучше в операндах таких шаблонов не 
использовать подвыражения без надобности. 
А использовать двойную нумерацию 
подвыражений тут невозможно? Если нет, то 
для именованных подвыражений можно точно 
добиться чтобы совпадение было с 
одинаковым ключом.

Original comment by oasyc...@gmail.com on 9 Jan 2015 at 6:17

GoogleCodeExporter commented 9 years ago
добавил описания к шаблонам, и получение 
описания для текущего языка.

Описания задаются в виде:
array('код языка' => 'описание $$1', 'код языка' => 
'описание $$1')

$$1 выбрано для единообразия с синтаксисом 
шаблонов.

Между $$ и цифрой можно указывать форму.

Пример:
new qtype_preg\template(
    'parens_req', 
    '(   \(    (?:$$1|(?-1))   \)  )', 
    'x', 
    array('en' => '$$1 in parens', 'ru' => '$$1 в скобках'), 
    1
)

Original comment by TOPT.iiiii on 11 Jan 2015 at 9:42

GoogleCodeExporter commented 9 years ago
Допустим, шаблон (x)(y)$$1|($$1)

(?###template<)(a)(?###>)

Допустим, мы проходим подряд по всем 
токенам, которые встречаем, и если это 
шаблон - сразу парсим его.
Тогда у шаблона есть подвыражения 1,2,3. 
Операнд (a) получает номер 4 во время 
парсинга. Затем мы доходим до правила 
свёртки, и нужно подставить (a) вместо $$1. Вот 
этот момент мне и не ясен до конца. (x)(y) 
нужно оставить как есть, потом $$1 сделать 
номер 3, потом увеличить номер подвыражения 
из правой альтернативы, и снова увеличить 
номер правого $$1. И после всего этого 
лексеру нужно тоже увеличить счетчик для 
последующих скобок.

Я пока не вижу четкого алгоритма, как оно 
должно работать. Может попробуем текстовый 
препроцессор сделать?

Original comment by vostreltsov@gmail.com on 12 Jan 2015 at 6:17

GoogleCodeExporter commented 9 years ago
Вот, предлагаю гораздо более простое 
решение с препроцессингом. Это будет 
одна-единственная функция, принимающая все 
токены из регекса и возвращающая строку, 
теперь уже без шаблонов.

У нее есть стек открытых шаблонов - как при 
проверке открытых-закрытых скобок. 
Проходим по всем токенам, если встретили 
не-шаблон, дописываем к результату userinscription 
токена. Если шаблон, то добавляем его на 
стек. И так далее. Синтаксические ошибки 
обнаруживаются здесь же.

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

Original comment by vostreltsov@gmail.com on 12 Jan 2015 at 9:52

GoogleCodeExporter commented 9 years ago
Еще забыл уточнить, что учет опций шаблона 
делается через (?x: ... ) в случае расширенной 
нотации, и т. п. Так что объект парсера будет 
создаваться всего один, только для 
финального парсинга. А лексера будет два - 
для первоначального и финального лексинга.

Original comment by vostreltsov@gmail.com on 12 Jan 2015 at 9:58

GoogleCodeExporter commented 9 years ago
Честно говоря если подставлять прямо при 
лексинге основного регекса шаблоны, не 
понимаю какие могли бы быть проблемы - 
просто прибавлять количество подвыражений 
внутри шаблона и все, оно же слева направо 
работает.

Но можно и препроцессором, надо только 
чтобы он режим preserveallnodes не испортил.

Original comment by oasyc...@gmail.com on 15 Jan 2015 at 6:46

GoogleCodeExporter commented 9 years ago
Пахомову вопрос - там слоформы описаний 
аргументов как-то поддерживаются? Или 
только именительный падеж везде?

Original comment by oasyc...@gmail.com on 15 Jan 2015 at 7:16

GoogleCodeExporter commented 9 years ago
сейчас всё что есть - в именительном падеже. 
В описании шаблонов можно вместо $$1 
использовать $$form1 для указания требуемой 
формы. 

Original comment by TOPT.iiiii on 15 Jan 2015 at 8:33

GoogleCodeExporter commented 9 years ago
предлагаю в дереве отображать следующим 
образом - т.к. все стили форм уже были 
использованы ( http://www.graphviz.org/doc/info/attrs.html ), то 
выделить края новых узлов зеленым цветом. 
Для параметризованного шаблона так:
1) http://prntscr.com/5tp9lk
2) тултип на русском: шаблон с параметрами
3) тултип на английском: template with parameters
Для шаблона без параметров так:
1) http://prntscr.com/5tozca
2) тултип на русском: шаблон без параметров
3) тултип на английском: template without parameters

Original comment by grvl...@gmail.com on 17 Jan 2015 at 8:22

GoogleCodeExporter commented 9 years ago
Во-первых, если выделять цветом, то тогда 
уже форму делать для шаблона без 
параметров идентичную с листом-символом, 
прямоугольную. А с параметрами - как у 
операций. Как простые и сложные ассерты (мы, 
кстати и dashed и dotted ухитрились использовать?)

Во-вторых, зеленый цвет вроде используется 
для выделения, может синий или оранжевый?

В третьих, я уже писал выше - в качестве 
тултипа должно быть описание смысла 
шаблона на русском/английском языке, 
которое вводится в класс шаблона. Что этот 
конкретный шаблон означает, т.е. условно 
(над фразой надо подумать) "любое 
количество правильно открытых и закрытых 
скобок" а не просто "шаблон с параметрами". 
Использовать строки от описания Пахомова 
может получиться для шаблонов с 
параметрами если правильно продумать 
слова, которые в общем смысле 
характеризуют параметры.

Original comment by oasyc...@gmail.com on 18 Jan 2015 at 3:02

GoogleCodeExporter commented 9 years ago
1) Формы для шаблонов без параметров/с 
параметрами соответствуют формам 
операндов/операторов (прямоугольные/овалы)
2) синий цвет:
http://prntscr.com/5ujazb
оранжевый цвет:
http://prntscr.com/5ujai8
Я за синий, он на вид заметнее. Прошу 
высказать остальных своё мнение.

Original comment by grvl...@gmail.com on 19 Jan 2015 at 9:19

GoogleCodeExporter commented 9 years ago
Синий неплох, только у нас некоторые 
надписи внутри синим/голубым делались в 
других узлах, мешать не будет? В шаблонах 
вроде таких надписей быть не должно. И таки 
может их как-нибудь dotted/dashed - не могли же мы 
оба эти стиля использовать на ассерты? Тоже 
прошу всех высказаться...

Original comment by oasyc...@gmail.com on 19 Jan 2015 at 9:46

GoogleCodeExporter commented 9 years ago
Я за синий. Кстати, если мне не изменяет 
память - в графе, дереве и описании 
выделения разными цветами были сделаны? 
Может стоит унифицировать?

Original comment by vostreltsov@gmail.com on 19 Jan 2015 at 9:49

GoogleCodeExporter commented 9 years ago
В графе и дереве вроде одинаково - зеленым. 
В описании это фон (а не прямоугольник), так 
что унифицировать едва ли разумно.

Original comment by oasyc...@gmail.com on 19 Jan 2015 at 9:50

GoogleCodeExporter commented 9 years ago
Значит оставляем синий.

3) тултипы:
для word: 
 "любое слово"
 "any word"
для integer:
 "любое число, включая + или -"
 "any number including + or -"
для parens_req:
 "подвыражение в скобках"
 "subexpression in parentheses"
для parens_opt:
 "подвыражение в скобках или без"
 "subexpression in parentheses or without"
для brackets_req:
 "подвыражение в квадратных скобках"
 "subexpression in square brackets"
для brackets_opt:
 "подвыражение в квадратных скобках или без"
 "subexpression in square brackets or without"

Что касается тултипов для 
пользовательских шаблонов: их должен 
описывать сам пользователь при создании 
шаблона так, как он хочет и на нужном ему 
языке или нужно генерировать краткое 
описание, подобно описаю самого 
регулярного выражения?

Original comment by grvl...@gmail.com on 20 Jan 2015 at 9:45

GoogleCodeExporter commented 9 years ago
Я вот думаю, может быть к тултипам 
добавлять на первой строке слово "шаблон" а 
на второй уже описание? Мы так делали с 
символьными классами вроде.

По скобкам - не надо пугать людей словом 
"подвыражение" - может "строка в скобках" или 
"текст в скобках"? Для круглых скобок - 
писать явно "в круглых скобках". Я бы еще и 
фигурные сделал.
Может быть даже, для унификации с 
описанием, типа "в любом количестве круглых 
скобок" - а что именно будет в описании 
добавлено.

Пользователь будет сам вводить для своих 
шаблонов описания, но это уже следующая 
версия.

Original comment by oasyc...@gmail.com on 23 Jan 2015 at 1:39

GoogleCodeExporter commented 9 years ago
Добавил поддержку шаблонов в графе 
(репозиторий zlumyo-preg-28). Приму предложения по 
внешнему виду. На данный момент внешний вид 
такой:
 - простой шаблон выглядит как обычный узел в форме гексагона;
 - сложный как подмаска с подписью, что это собственного говоря шаблон типа "такого-то".

Original comment by ZluMYO@gmail.com on 25 Jan 2015 at 11:28

GoogleCodeExporter commented 9 years ago
3) тултипы:
для word: 
 "любое слово"
 "any word"
для integer:
 "любое число, включая + или -"
 "any number including + or -"
для parens_req:
 "текст в круглых скобках"
 "text in round parentheses"
для parens_opt:
 "текст в круглых скобках или без"
 "text in round parentheses or without"
для brackets_req:
 "текст в квадратных скобках"
 "text in square brackets"
для brackets_opt:
 "тект в квадратных скобках или без"
 "text in square brackets or without"

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

Original comment by grvl...@gmail.com on 25 Jan 2015 at 6:33

GoogleCodeExporter commented 9 years ago
а) в графе сложный шаблон желательно 
отделить от подмасок/квантификаторов 
цветом или видом линии еще
б) в lang файле можно, но с пользовательским 
это не пройдет.
Есть еще такая штука для этих целей - в 
отличие от get_string работает и на 
пользовательских данных тоже
 https://github.com/moodle/moodle/tree/master/filter/multilang

Вопрос только что ее надо проверять, если 
выключена - выдавать текст на одном 
каком-то языке, чтобы ужасов юзеру не 
показывать.

Original comment by oasyc...@gmail.com on 25 Jan 2015 at 9:43

GoogleCodeExporter commented 9 years ago
Внешний вид сложного шаблона в графе 
довольно проблематично отделить от 
подмасок/квантификатором.
Вот такие есть варианты отрисовки границ 
кластера: http://prntscr.com/5xcuam
Если думать о цветовом выделении, то 
наиболее очевидные (и ярко выраженные) 
цвета уже используются в других местах 
графа. Или можно повториться?

Original comment by ZluMYO@gmail.com on 26 Jan 2015 at 6:03

GoogleCodeExporter commented 9 years ago
Для дерева вроде все сделал по шаблонам, 
прошу проверить

Original comment by grvl...@gmail.com on 26 Jan 2015 at 9:38

GoogleCodeExporter commented 9 years ago
Считаю, что и для дерева, и для описания, 
строки нужно делать прямо полями в самом 
классе шаблона. Юзер их будет вводить на 
своем родном языке сам, а сейчас пока 
захардкодим на английском. Не будет же он 
менять lang/en/qtype_preg.php!

Original comment by vostreltsov@gmail.com on 29 Jan 2015 at 11:59

GoogleCodeExporter commented 9 years ago
они сейчас (у меня по крайней мере) берут 
описания не из lang-файла а как параметр 
конструктора

new qtype_preg\template(
    'parens_req', 
    '(   \(    (?:$$1|(?-1))   \)  )', 
    'x', 
>>> array('en' => '$$1 in parens', 'ru' => '$$1 в скобках'), 
<<<<<<<<<<<<<<<<<<<<<<
    1
)

расчет был на то, что в будущем появится 
форма вида:
http://prntscr.com/5yhior
и вся эта радость будет храниться в бд

Original comment by TOPT.iiiii on 29 Jan 2015 at 12:13

GoogleCodeExporter commented 9 years ago
Зачем мне вводить описание на английском, 
если я его всё равно не буду использовать?

Original comment by vostreltsov@gmail.com on 29 Jan 2015 at 12:24

GoogleCodeExporter commented 9 years ago
По языкам и описаниям еще раз (см 31-й 
коммент) - "Есть еще такая штука для этих 
целей - в отличие от get_string работает и на 
пользовательских данных тоже
 https://github.com/moodle/moodle/tree/master/filter/multilang "

Предлагаю проверять, включен ли - если 
проверять то вываливать описания на всех 
языках в соотв. тегах, если нет - на 
английском.
Вообще по идее функция, возвращающая 
текущий язык интерфейса тоже есть.

Валерий - про описание на английском не 
понял, хардкодить его точно надо.

Original comment by oasyc...@gmail.com on 8 Feb 2015 at 10:07

GoogleCodeExporter commented 9 years ago
>> по идее функция, возвращающая текущий 
язык интерфейса тоже есть.
Есть. Она используется уже

Original comment by TOPT.iiiii on 9 Feb 2015 at 12:52

GoogleCodeExporter commented 9 years ago

Original comment by oasyc...@gmail.com on 3 Jul 2015 at 8:16