Движки e-repa.ru. Часть 2. qb: конструктор вопросов

В первой части я показал, как js-движок dub помогает ученику преодолеть трудность восприятия английской речи на слух: js-движок переводит структуру синтагмы из слухового канала в визуальный. Другая трудность, с которой сталкивается русскоязычный ученик, — английская грамматика, в частности построение вопросительного предложения. Помимо особенностей самого английского вопроса — инверсии, наличия вспомогательного глагола, недопустимости разрыва определения и определяемого слова — ученику трудно различать типы вопросов: вопрос к подлежащему, специальный, общий, разделительный и т. д. Поэтому вопросительное предложение складывается для ученика в сложный для усвоения комплекс. Чтобы помочь ученику видеть структуры, входящие в построение вопросительного предложения, я разработал js-движок qb.

Структуры, из которых строится английский вопрос, — вопросительное слово, вспомогательный глагол, подлежащее, предлог, смысловой глагол и остальные слова вопроса, — ученик видит на экране как отдельные зоны карточек: Wh-words, Auxiliaries, Pronouns & Nouns, Prepositions и Words. Собирая вопрос, он всякий раз решает, из какой зоны брать карточку и нужна ли ему эта зона вообще. Для специального вопроса он берёт вопросительное слово, затем вспомогательный глагол и подлежащее: Where do you live? Для общего вопроса карточек из зоны Wh-words он не берёт и начинает со вспомогательного глагола: Do you live here? Вопрос к подлежащему строится без вспомогательного глагола do, и после вопросительного слова сразу идёт смысловой глагол: Who lives here? А если вопросительное слово относится к существительному, разорвать их нельзя, и ученик ставит существительное из зоны Words сразу за вопросительным словом, до вспомогательного глагола: What tiles is she buying? Так типы вопросов, которые в учебнике даны списком правил, ученик различает по тому, какие зоны участвуют в сборке и в каком порядке.

Что даёт такое зонирование? Когда в задании сказано «постройте вопрос» и опоры нет, ученик должен опираться на правила построения вопроса и на инвентарь, то есть на то, какие бывают вопросительные слова, вспомогательные глаголы, местоимения и предлоги. Всё это есть у него только в голове, в абстрактно-понятийной форме: это заученные формулировки и парадигмы, которые нельзя увидеть и взять. Зонирование переводит правила и инвентарь в наглядно-действенную форму. Состав зон — это инвентарь, выложенный на экран, а то, какие зоны участвуют в сборке и в каком порядке, — это правила построения вопроса. Это такая же внешняя опора, как визуальная структура синтагмы в js-движке dub, и со временем ученик научается обходиться без неё.

Как зонирование помогает усвоить сложный грамматический комплекс? Комплекс, который в учебнике дан списком правил, а в задании «постройте вопрос» не дан вовсе, ученик должен удержать в голове целиком, и целое при этом рассыпается. Зонирование раскладывает его на функциональные структурные части и показывает их: ученик видит, из каких структур состоит вопрос и из какой парадигмы берётся каждый элемент. Но он не только видит, он ещё и действует руками: берёт карточку из зоны, ставит её в линию на её функциональное место, переставляет, убирает. В результате правило построения вопроса проходит через моторику: собирая вопросы одного типа, ученик раз за разом повторяет одно и то же движение — в специальном вопросе от зоны вопросительных слов к зоне вспомогательных глаголов и дальше к подлежащему, в общем вопросе сразу от вспомогательного глагола к подлежащему. Зрительный образ структуры и моторный образ действия складываются вместе, и комплекс усваивается как действие, а не как знание о действии.

Как зоны и сборка вопроса устроены в коде js-движка qb

Всё, что ученик видит на экране и делает руками, реализовано в js-движке qb. Как и в js-движке dub, упражнение состоит из трёх частей: HTML-страницы, XML-файла с заданиями и самого js-движка, то есть JS-файла qb-script.js, написанного с использованием jQuery, и CSS-файла qb-styles.css. Разница в том, что в dub одна страница — это одно упражнение с одной записью, а в qb на одной странице собрано много наборов заданий. Все они хранятся в папке qb_data/, и когда ученик открывает страницу Question Drill — Конструктор, js-движок читает реестр qb_data/index.json и строит по нему список наборов, из которого ученик выбирает один.

Почему инвентарь вопроса задан в js-движке, а не в XML набора

Наборы различаются заданиями, а инвентарь вопросительного предложения — вопросительные слова, вспомогательные глаголы, местоимения и предлоги — во всех заданиях и во всех наборах один и тот же. Поэтому задан он не в XML отдельного набора, а в самом js-движке, в виде постоянных массивов:

var ZONE1 = [['who','whom','what','which','whose'],['when','where','why','how'],['many','much','long','kind']];var ZONE2 = [{words: ['do','does','did']},{words: ['am','is','are','was','were']},{words: ['be','being','been']},{words: ['have','has','had']},{words: ['can','will','shall','may','must','need']},{words: ['could','would','should','might']},{words: ['not']}];

Точно так же заданы местоимения (ZONE3_PERMANENT) и предлоги (ZONE5). У этого решения два следствия. Во-первых, составитель набора не может случайно убрать из зоны нужную форму или забыть её, потому что зоны от набора не зависят. Во-вторых, ученик всегда видит в зоне Auxiliaries все формы вспомогательных и модальных глаголов, а не только ту, которая входит в ответ, и поэтому вспомогательный глагол ему приходится выбирать по времени и лицу, а не брать единственную карточку. Зону предлогов js-движок достраивает на странице сам, функцией buildPrepositionZone(), поэтому зона, добавленная позже остальных, сразу появилась во всех наборах без правки их XML.

Что составитель набора пишет в XML и как js-движок строит зону Words

Раз инвентарь задан в js-движке, составителю набора остаётся написать в XML только само задание: русскую опору, варианты английского ответа и обманку.

01. Кто преподавал химию и физику в школе для мальчиков и девочек?Who taught chemistry and physics at a school for boys and girls|Who taught chemistry and physics in a school for boys and girlsteaching

В через | перечислены все верные варианты ответа: здесь ученик вправе собрать и at a school, и in a school, и js-движок примет оба варианта. В стоит обманка, то есть форма того же глагола, которая в этой позиции неверна: teaching рядом с taught. Зону Words составитель набора не размечает, её js-движок строит сам, функцией buildScrambleWords():

q.answer.split('|').forEach(function(variant) {variant.trim().split(/s+/).forEach(function(w) {if (w && !hardcoded[norm(w)]) add(w);});});q.vx.forEach(add);

Функция берёт слова всех вариантов ответа, отбрасывает те, что уже есть в постоянных зонах, добавляет обманку, убирает повторы и перемешивает оставшееся по Фишеру — Йетсу. В результате в зоне Words остаются только слова конкретного вопроса и обманка, а служебные слова — вопросительное слово, вспомогательный глагол, местоимение, предлог — ученик берёт из постоянных зон, где должен их выбрать.

Почему карточка остаётся в зоне после переноса на линию

Выбирать ученику приходится и в зоне Words. Если бы карточка при переносе на линию исчезала из зоны, ученик мог бы не выбирать, а раскладывать: по числу оставшихся карточек он видел бы, сколько слов ещё нужно, и последнюю карточку ставил бы на последнее место, не думая. Поэтому карточка остаётся в зоне, а на линию js-движок ставит её копию:

card.addEventListener('click', function() {if (!answered) addCardToEnd(word, zone);});

Одна карточка the годится для любого числа вхождений, и вычислить длину ответа по карточкам нельзя. Кроме клика, карточку можно перетащить в нужное место линии, и тогда js-движок показывает, куда она встанет: соседние карточки раздвигаются, и ученик видит позицию вставки ещё до того, как отпустит карточку. Сборочная линия переносится на несколько строк, поэтому функция findSlotIndex() сначала выбирает строку по вертикали, а затем место в строке по горизонтали.

Как js-движок проверяет собранный вопрос

Каждое изменение сборки js-движок проверяет сам, кнопки «Проверить» в упражнении нет: через 400 мс после последнего изменения функция doAutoCheck() сравнивает сборку слово за словом с каждым вариантом ответа:

var variants = q.answer.split('|');var matched = false;for (var vi = 0; vi < variants.length; vi++) {var eNorm = variants[vi].trim().split(/s+/).map(norm);if (sNorm.length !== eNorm.length) continue;var ok = true;for (var i = 0; i < sNorm.length; i++) {if (sNorm[i] !== eNorm[i]) { ok = false; break; }}if (ok) { matched = true; break; }}

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

Как кнопка с лампочкой закрывает угадывание артиклей, предлогов и притяжательных местоимений

Проверка засчитывает только полное совпадение с вариантом ответа, а артикль, притяжательное местоимение или предлог часто нельзя вывести из русской опоры: «мальчик по имени Дик» по-английски может быть и a boy, и the boy, и по русскому тексту не понять, какой вариант стоит в ключе. Если из-за этого задание не засчитывается, оно превращается в угадывание, а угадывание и есть тот обходной путь, который упражнение должно закрыть. Поэтому рядом со Skip стоит кнопка с лампочкой, и загорается она ровно тогда, когда всё, что составляет цель дрилла, — вопросительное слово, вспомогательный глагол, порядок слов, форма глагола — в сборке уже верно, а расходятся только «мелкие» слова: артикли, притяжательные местоимения и предлоги. Функция stripSoft() убирает эти слова из сборки и из каждого варианта ответа, а findNearMatch() ищет вариант, у которого остаток совпал со сборкой:

var sCore = stripSoft(sNorm).join(' ');q.answer.split('|').forEach(function(variant) {var words = variant.trim().split(/s+/);var vNorm = words.map(norm);if (stripSoft(vNorm).join(' ') !== sCore) return;var mk = lcsMarks(sNorm, vNorm);var dist = sNorm.length + vNorm.length - 2 * mk.len;if (!best || dist < best.dist) best = {words: words, marks: mk, dist: dist};});

Функция lcsMarks() строит наибольшую общую подпоследовательность так же, как побуквенная проверка в js-движке dub, только по словам, а не по буквам. По ней js-движок обводит красным карточки ученика, которые лишние или стоят не на своём месте, и выделяет жирным в ключе слова, которых в сборке не хватает. Ученик, нажав лампочку, видит ближайший вариант ключа, и дальше возможны два исхода. Если он исправил сборку и она совпала с ключом, задание засчитано. Если посмотрел и не исправил, задание не засчитано, и дальше он нажимает Skip. Для наборов, где цель дрилла — сами артикли, предлоги или притяжательные местоимения, у ставится атрибут strict: он исключает названный класс из «мелких» слов, и лампочка на ошибках в них уже не загорается.

Как устроены Skip, повторные циклы и сохранение прогресса

Skip, которым ученик откладывает несданное задание, и циклы устроены так же, как в js-движке dub: функция nextCur() после каждого задания ищет следующее несданное, а дойдя до конца списка, начинает с начала, поэтому отложенное задание возвращается к ученику в следующем цикле, пока он не соберёт его верно. Прогресс хранится в localStorage, но ключ здесь не путь страницы, как в dub, а составной: pathname + '::' + имя набора. Поэтому прогресс каждого набора хранится отдельно, и, начав второй набор, ученик не теряет работу над первым.

Общий принцип, на котором построены js-движки e-repa.ru

Зоны в js-движке qb и визуальная структура синтагмы в js-движке dub выводятся из одного принципа, общего для всех js-движков e-repa.ru. Js-движок переводит правила и инвентарь из абстрактно-понятийной формы в наглядно-действенную, и это позволяет ученику совершать конкретные действия: назначать каждому элементу инвентаря функцию, его структурную роль. В qb ученик берёт карточку из зоны, ставит её в линию на функциональное место, переставляет, убирает; в dub он вписывает каждое расслышанное слово в своё поле в строке синтагмы.

В абстрактно-понятийной форме такое действие невозможно, потому что в ней нет ни предмета, ни места. Правило и парадигма в голове — это знание о структуре: заученная формулировка и список форм. Элемент в нём не отделён от других, а грамматика существует целиком и расплывчато. Чтобы назначить элементу функцию, нужны отдельный элемент, который можно взять, и место в структуре, куда его можно поставить. Ученик, у которого правило есть только в голове, может его вспомнить, но совершить с ним действие не может. Наглядно-действенная форма позволяет абстрактно-понятийной форме:

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

  2. Превратиться в решение. Поставить карточку «куда-нибудь» нельзя: место определяется тем, что слово делает в вопросе, и, чтобы поставить карточку, ученик каждый раз определяет функцию слова. Знание о структуре («в вопросе есть вспомогательный глагол») становится действием («этот глагол стоит здесь, потому что…»).

  3. Стать видимой самому ученику. Пока рассуждение было в голове, проверить его было нельзя. Теперь оно лежит перед глазами в виде расположения карточек: ошибка перестаёт быть смутным «что-то не так» и становится конкретной неверной позицией, которую можно найти и исправить, переставив карточку.

  4. Повторяться до автоматизма. Действие с карточками ученик выполняет много раз и закрепляет последовательность решений: кто спрашивает, какой это тип вопроса, где вспомогательный глагол. Из внешнего действия вырастает внутреннее, и опора становится ненужной.

Источник: habr.com

0 0 голоса
Рейтинг новости
1
0
Подписаться
Уведомить о
0 комментариев