Перейти к основному содержимому

Задать вопросы для каждого ответа другого вопроса

· 11 мин. чтения

Когда в анкете нужно задавать блок одних и тех же вопросов для выбранных или невыбранных ответов, можно, конечно, просто добавить все эти вопросы вручную, прописав в них соответствующие условия показа. Однако система позволяет автоматизировать этот процесс.

note

Перед прочтением рекомендуем ознакомиться с этой статьёй.

Рассмотрим пример:

Q1. Какими сервисами Вы пользуетесь в настоящее время?

1. Сервис 1
2. Сервис 2
3. Сервис 3
97. Никакими

Q2. Как давно Вы начали пользоваться сервисом [вставить название из Q1]?

1. Один месяц назад и менее
2. От одного до трех месяцев назад
3. От трех до шести назад
4. От шести месяцев до года назад
5. Более года назад
99. Не помню

Q3. Вы пользуетесь сервисом [вставить название из Q1]

1. По платной подписке
2. Бесплатно
99. Затрудняюсь ответить

Для каждого выбранного в Q1 ответа необходимо задать уточняющие Q2 и Q3. Конечно, в случае выбора ответа 97 ничего спрашивать не нужно.

Как бы мы делали это вручную?

После Q1 для каждого ответа, кроме 97, добавляем вопросы:

Q21. Как давно Вы начали пользоваться сервисом Сервис 1?
[Условие показа: Q1 = 1]
Q31. Вы пользуетесь сервисом Сервис 1
[Условие показа: Q1 = 1]

Q22. Как давно Вы начали пользоваться сервисом Сервис 2?
[Условие показа: Q1 = 2]
Q32. Вы пользуетесь сервисом Сервис 2
[Условие показа: Q1 = 2]

Q23. Как давно Вы начали пользоваться сервисом Сервис 3?
[Условие показа: Q1 = 3]
Q33. Вы пользуетесь сервисом Сервис 3
[Условие показа: Q1 = 3]

Хорошо, когда нужно задать 2 вопроса для 3-х ответов. В груди начинает щемить, если вопросов 20, а ответов 200.

Создаём цикл

note

В программировании циклом называют многократно исполняемую последовательность инструкций.

Добавляем в скрипт Подготовка строку:

questions.repeat(2, 3, 1);
Подробнее

По-русски прочитать эту строчку можно так: повторить блок вопросов с Q2 по Q3 включительно для каждого ответа Q1.

О синтаксисе метода repeat() почитать можно здесь.

В текстах Q2 и Q3 вместо [вставить название из Q1] пишем: {answerText}. И осталось ответу 97 в Q1 поставить флаг Запрещено использовать в циклах.

В общем-то, всё. Теперь при каждом запуске анкеты на месте Q2 и Q3 будут создаваться вопросы Q21,Q31…Q23,Q33 с необходимыми условиями показа.

tip

Вывести на экран номера всех вопросов анкеты с их условиями показа можно с помощью этого скрипта.

Вы уже можете создавать простые циклы по вопросу. Чтобы расширить знания и разобраться в деталях, читайте далее.

Важно понять

Во время запуска анкеты с циклом добавленные в редакторе вопросы удаляются, а на их месте создаются новые (копии исходных) для каждого варианта ответа. Номера этих вопросов формируются автоматически в зависимости от кодов ответов.

В примере выше вопросы создавались для ответов 1, 2 и 3 — номера новых вопросов получились Q21, Q22, Q23… То есть к номеру исходного вопроса — Q2 — просто добавились коды вариантов ответа.

Если бы максимальным кодом ответа было бы двузначное число, например, 1, 2 и 10, то к исходному номеру вопроса добавлялись бы двузначные коды: Q201, Q202, Q210. Если максимальный код трёхзначный: 1, 2, 523 — Q2001, Q2002, Q2523. И так далее.

caution

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

Немного математики

По такому номеру вопроса можно легко определить номер исходного вопроса и код варианта ответа, для которого он задаётся.

Если мы знаем, что максимальный код ответа — одна цифра, то номер вопроса нужно разделить на 10: 21 / 10 = 2,1. То есть целая часть числа (2) — номер исходного вопроса, дробная часть (1) — код ответа.

Если максимальный код — двузначное число, то делить нужно на 100: 202 / 100 = 2,02. Если трёхзначный — делим на 1000: 2003 / 1000 = 2,003. Ну, вы поняли.

Это потребуется для прописывания логики по вопросам, находящимся внутри цикла.

Логика внутри цикла

Усложним предыдущий пример:

Q1. Какими сервисами Вы пользуетесь в настоящее время?

1. Сервис 1
2. Сервис 2
3. Сервис 3
98. Другой (запишите)
97. Никакими

НЕ ЗАДАВАТЬ ДЛЯ СЕРВИСА 3
Q2. Как давно Вы начали пользоваться сервисом [вставить название из Q1]?

1. Один месяц назад и менее
2. От одного до трех месяцев назад
3. От трех до шести назад
4. От шести месяцев до года назад
5. Более года назад
99. Не помню

ЗАДАТЬ, ЕСЛИ Q2 = 1
Q3. Вы пользуетесь сервисом [вставить название из Q1]

1. По платной подписке
2. Бесплатно
99. Затрудняюсь ответить

Как создать цикл вы уже знаете, здесь ничего нового. Но дальше сложности:

  1. В Q1 у ответа 98 есть текстовое поле. Значит в тексты вопросов Q2 и Q3 надо подставлять то, что туда впишут.
  2. Условия показа в Q2 и Q3, но в анкете нет таких вопросов после её запуска.

Чтобы это сделать, потребуются глобальные скрипты анкеты.

caution

Скрипты перед показом и после ответа в вопросах, находящихся внутри цикла, не выполняются.

Выводить текст из «другого» вместо {answerText}

Макрос {answerText} заменяется на текст варианта ответа, а нам нужно значение текстового поля. Добавьте глобальный скрипт перед показом:

/* 
Делим номер текущего вопроса на 100 и берём целую часть.
Если она равна 2 или 3 (номера первого и последнего вопросов
в цикле), то…
*/
if ((Q.number / 100 | 0) == 2 || (Q.number / 100 | 0) == 3) {
// делим номер текущего вопроса на 100 и берём остаток (код ответа)
let code = Q.number % 100;
// из Q1 получаем вариант ответа с этим кодом
let A = Q1[code];
// в глобальную переменную «Сервис» помещаем или значение поля, или текст ответа
V['Сервис'] = A.flags & AnswerFlags.OpenValueTxt ? A.openValueTxt : A.text;
}

Теперь в текстах вопросов вместо {answerText} нужно использовать подстановку {Сервис}.

Не задавать Q2 для ответа 3

Если просто написать в условии показа Q2 not Q1 = 3, то вопросы Q201, Q202, Q203 и Q298 не будут выводиться на экран, если в Q1 выбран ответ 3. Поэтому добавьте в глобальный скрипт перед показом:

if ((Q.number / 100 | 0) == 2) {
// если текущий код 3 — пропускаем вопрос
if (Q.number % 100 == 3) return skip;
}

Задать Q3, если в Q2 выбран ответ 1

Если просто написать в условии показа Q3 Q2 = 1, то он никогда не выведется на экран, потому что условие не выполнится. Поэтому добавьте в глобальный скрипт перед показом:

if ((Q.number / 100 | 0) == 3) {
// получаем Q2 для текущего кода ответа
let Q2x = questions[200 + Q.number % 100];
// если в нём не выбран ответ 1, то пропускаем вопрос
if (!Q2x.isChecked(1)) return skip;
}

Если скрипт не работает

Чаще всего встречаются две проблемы:

  1. Скрипт ничего не делает.
  2. Делает (или приводит к ошибке), но в вопросе, который не находится в цикле.

В первом случае следует начать с проверки, срабатывает ли блок if для этого вопроса. Возможно, некорректно прописана проверка номера вопроса, например текущий номер делится на 10, а нужно делить на 100. Для этого можно воспользоваться функцией informationText(), например пишем сразу после if:

if ((Q.number / 100 | 0) == 3) {
informationText('СРАБОТАЛО! Q{0}', Q.number);
// … дальше ваш скрипт
}

Далее запустите анкету и дойдите до вопросов Q3x. Если в левом нижнем углу вы не видите СРАБОТАЛО! — ищите причину этого. Нужно исправить ошибку, чтобы проверочный текст начал выводиться, и сразу начнёт выполняться ваш скрипт.

Во втором случае, когда происходит что-то не то в вопросе за пределами цикла, проверяйте нумерацию. Пример: где-то в анкете есть вопрос Q30, а в Подготовке создаётся цикл с вопросами Q31, Q32…, соответственно, блок с условием if ((Q.number / 10 | 0) == 3)… будет выполнен и для вопроса Q30 тоже. Проблему решит смена номера этого вопроса или того, что внутри цикла.

Логика по вопросам цикла за его пределами

Возьмём такой пример:

Q1. Какими сервисами Вы пользуетесь в настоящее время?

1. Сервис 1
2. Сервис 2
3. Сервис 3
97. Никакими

ЗАДАТЬ ДЛЯ ВЫБРАННЫХ В Q1 СЕРВИСОВ
Q2. Как давно Вы начали пользоваться сервисом [вставить название из Q1]?

1. Один месяц назад и менее
2. От одного до трех месяцев назад
3. От трех до шести назад
4. От шести месяцев до года назад
5. Более года назад
99. Не помню

ЗАДАТЬ, ЕСЛИ В Q2 ЛЮБОГО СЕРВИСА ВЫБРАН ОТВЕТ 5
Q56. Вы сказали, что…

Здесь нас интересует только Q56. Он расположен после цикла, и тут можно обойтись обычным условием показа:

Q21 = 5 or Q22 = 5 or Q23 = 5

То есть просто проверяем все вопросы Q2 на наличие ответа с кодом 5.

Что делать, если в Q1 ответов очень много? Прописывать 100 проверок может быть утомительно и сложно читаемо. На помощь, как всегда, приходят скрипты.

Можно добавить в Q56 такой скрипт перед показом:

// проходим по выбранным ответам Q1
for (let code of Q1.getCheckedCodes()) {
// формируем номер вопроса Q2 для такого ответа
let qn = 20 + code;
// если вдруг вопроса с таким номером в анкете нет — пропускаем его
if (!(qn in questions)) continue;

// если в текущем Q2 выбран ответ 5, то останавливаем for и задаём Q56
if (questions[qn].isChecked(5)) return ok;
}

// если дошли сюда, значит ни в одном Q2 ответ 5 не выбран — пропускаем Q56
return skip;

Цикл по невыбранным ответам

Иногда бывает нужно задавать уточняющие вопросы для невыбранных ответов. Для этого есть метод repeatIfNot().

Просто пишем в Подготовке:

questions.repeatIfNot(2, 3, 1);

И вопросы Q2 и Q3 будут выводиться на экран для кодов Q1, которые не были выбраны.

Этот вид цикла также удобно использовать, когда требуется выводить по одному на экране какие-либо высказывания для их оценки.

Пример:

Q1. Как Вы думаете, каким из этих марок подходит высказывание [вставить высказывание]?

1. Марка 1
2. Марка 2
3. Марка 3
99. Ни одной

Список высказываний:
1. Предлагает то, чего нет у других марок
2. Марка, которую Вы любите
3. Марка, которая задает тон на рынке

Вместе с Q1, в анкету нужно добавить «служебный» вопрос со списком высказываний (списком ответов), пусть это будет Q8001, единственный или множественный выбор — без разницы. В условии показа пишем false, чтобы он никогда не задавался. Также на вкладке Дополнительно можно поставить флаг Исключить вопрос при выгрузке, ведь пользы от этого вопроса в массиве никакой.

И теперь добавляем в Подготовку:

questions.repeatIfNot(1, 1, 8001);

В тексте Q1 не забываем использовать подстановку {answerText}.

Цикл по табличному вопросу

Сразу скажем, это невозможно. Создавать цикл можно только по вопросу с выбором ответа. Как же быть?

Есть такая задача.

Q1. Пользуетесь ли Вы следующими сервисами?

Список строк:
1. Сервис 1
2. Сервис 2
3. Сервис 3

Список ответов:
1. Да
2. Нет

ЗАДАТЬ ДЛЯ КАЖДОГО СЕРВИСА С ОТВЕТОМ 1
Q2. Как давно Вы начали пользоваться сервисом [вставить название из Q1]?

1. Один месяц назад и менее
2. От одного до трех месяцев назад
3. От трех до шести назад
4. От шести месяцев до года назад
5. Более года назад
99. Не помню

Общий принцип простой: переносим необходимые ответы из табличного вопроса в обычный и создаём цикл по нему.