Expression Manager
From LimeSurvey Manual
Короткий посібник для початку роботи
Огляд
Під час налаштування опитувань вам зазвичай потрібно мати можливість визначити таке:
- Навігація/розгалуження - дозволяє відповідям респондента змінювати порядок, у якому ставляться питання
- Адаптація/підстановка - як сформулювати питання (наприклад, з посиланням на попередні відповіді або з відмінюванням речень залежно від кількості чи статі респондентів), або як створювати власні звіти (наприклад, оцінки чи персоналізовані поради).
- Перевірка - гарантує, що відповіді відповідають певним критеріям, наприклад мінімальним і максимальним значенням або заданому шаблону введення
Expression Manager (EM) надає інтуїтивно зрозумілий спосіб визначення логіки для кожної з цих функцій. Майже все, що можна записати як стандартне математичне рівняння, є допустимим виразом, навіть якщо ви викликаєте функції. Наразі EM надає доступ до 80 функцій і може бути легко розширений для підтримки більшої кількості. Він також дозволяє звертатися до ваших змінних за зрозумілими людині іменами (а не за іменами SGQA).
У наведених нижче розділах показано основні місця, де використовується Expression Manager
Релевантність (керування навігацією/розгалуженням)
Деякі опитування використовують «логіку переходу» (Goto Logic): якщо ви відповідаєте на питання 1 варіантом C, то відбувається перехід до питання 5. Такий підхід дуже обмежений, оскільки його важко перевірити, а також він легко ламається під час зміни порядку питань. EM використовує булеве рівняння релевантності, щоб визначити всі умови, за яких питання може бути дійсним. Якщо питання релевантне, воно показується, інакше воно вважається нерелевантним (Not Applicable), а в базі даних зберігається значення NULL. Це схоже на те, що можна зробити за допомогою редактора умов, але EM дозволяє легко задавати набагато складніші та потужніші критерії (і використовувати ім'я змінної замість найменування SGQA).
Це зображення показує один зі способів перегляду логіки релевантності для опитування. Воно обчислює індекс маси тіла. Рівняння релевантності показано у квадратних дужках одразу після імені змінної (яке виділено зеленим). Отже, релевантність weight, weight_units, height і height_units дорівнює 1, що означає, що ці питання ставляться завжди. Однак релевантність для BMI - {!is_empty(height) and !is_empty(weight)}, що означає, що BMI буде обчислюватися, лише якщо респондент введе значення і для зросту, і для ваги (таким чином уникаючи ризику помилки ділення на нуль). Також питання Report показується, лише якщо респондент відповів на всі чотири основні питання (height, height_units, weight, weight_units).
Релевантність відображається та редагується в таких місцях:
Перегляд / редагування релевантності на рівні питання
Це рівняння обчислює індекс маси тіла (BMI). Питання ставиться, лише якщо людина спочатку вводить свій зріст і вагу.
Це екран редагування питання BMI.
Зверніть увагу, що під час введення рівняння релевантності фігурні дужки не використовуються.
Перегляд / редагування релевантності на рівні групи
Це зразок опитування для перепису населення. На першій сторінці запитується, скільки людей проживає разом з вами, і це значення зберігається у змінній «cohabs». Ця сторінка показується, лише якщо з вами проживає більше однієї особи (тобто вона показується для другої особи, що проживає з вами), а також лише якщо ви вказали, ким вам доводиться перша особа (p1_rel).
Як бачите, група також має критерії релевантності на рівні питань, тому кожне питання з'являється лише після того, як ви відповіли на попереднє (наприклад, {!is_empty(p1_sex)}). EM поєднує релевантність на рівні групи та питання за вас. Питання в групі ставляться, лише якщо група загалом релевантна. Після цього ставляться лише ті питання групи, які релевантні.
Ось екран редагування релевантності на рівні групи для цього питання:
Зверніть увагу, що під час введення рівняння релевантності фігурні дужки не використовуються.
Адаптація/підстановка (Tailoring/Piping)
EM дозволяє легко виконувати просту та складну умовну адаптацію ваших питань. Іноді потрібна проста підстановка, наприклад: «Ви сказали, що придбали [Product]. Що вам найбільше сподобалося в ньому?». Іноді потрібна умовна підстановка, наприклад: «[Mr./Mrs.] [LastName], чи погодилися б ви пройти наше опитування?». У такому разі потрібно використовувати «пан» або «пані» залежно від статі особи. В інших випадках потрібна ще складніша підстановка (наприклад, на основі математичного обчислення). EM підтримує кожен із цих типів адаптації/підстановки.
Умовні рівняння
Приклад з індексом маси тіла показує можливість обчислення BMI особи, навіть якщо вона вводить свій зріст і вагу в метричних або неметричних одиницях.
Тут weight_kg — це {if(weight_units == 'kg', weight, weight * .453592)}. Ця функція if() означає: якщо респондент ввів вагу в кілограмах, використовується це значення, інакше введене значення (у фунтах) множиться на .453592 для перетворення в кілограми. Змінна height_m використовує подібний підхід для обчислення зросту в метрах, навіть якщо зріст було введено в дюймах.
BMI обчислюється за формулою {weight_kg / (height_m * height_m)}.
Нарешті, звіт умовно адаптує повідомлення для респондента, повідомляючи, що саме він ввів. («Ви вказали, що ваш зріст 2 метри, а вага 70 кг.»)
Хоча це не дуже добре видно на зображенні вище, weight_status використовує вкладені оператори if() для віднесення людини до категорій від недостатньої ваги до тяжкого ожиріння. Рівняння цього виразу можна побачити в режимі «Показати логіку».
У вікні редагування цього питання можна побачити дві речі:
- Під час адаптації вирази необхідно брати у фігурні дужки
- Вирази можуть займати кілька рядків, якщо, як у цьому випадку, потрібно полегшити читання вкладеної умовної логіки.
Адаптовані питання, відповіді та звіти
У цьому прикладі показано звіт BMI.
Ось вікно редагування того самого питання.
Як видно, усе, що знаходиться у фігурних дужках, розглядається як вираз, тому на попередньому зображенні підсвічується синтаксисом (кольором). Якщо ви зробили помилки (наприклад, неправильно написали або використали невизначені імена змінних чи функцій), EM покаже помилку, як у цьому прикладі: height_unit — невизначена змінна (насправді вона називається height_units), а rnd() — невизначена функція (правильна назва функції — round()). В обох випадках помилки обведені червоною рамкою, щоб їх було легше помітити та виправити.
Також видно, що можна швидко створювати складні звіти, наприклад таблицю введених значень або адаптовані поради.
Пам’ятайте, що під час адаптації всі вирази потрібно брати у фігурні дужки, щоб LimeSurvey знав, які частини питання є вільним текстом, а які слід обробляти через Expression Manager.
Перевірка
EM керує роботою більшості розширених параметрів питання. Вони визначають такі аспекти, як мінімальна/максимальна кількість відповідей; мінімальні/максимальні окремі значення; мінімальна/максимальна сума значень; а також перевірку відповідності введених значень заданим шаблонам рядків. Ви, як і раніше, вводите ці розширені параметри питання звичайним способом. Однак тепер будь-яке значення в цих полях вважається виразом, тому можна задавати критерії мінімуму/максимуму зі складними умовними залежностями від інших питань.
В усіх цих випадках, оскільки розширений параметр питання завжди вважається виразом, фігурні дужки під час його задання не використовуються.
На сторінці Приклади опитувань наведено багато робочих прикладів використання виразів для перевірки.
Вступ
LimeSurvey використовує новий модуль Expression Manager (EM), який дозволить LimeSurvey підтримувати складніше розгалуження, оцінювання, перевірку та адаптацію. Він замінить спосіб, у який LimeSurvey керує замінами, умовами та оцінюванням на внутрішньому рівні. Він також значно прискорить обробку, оскільки усуває більшість читань із бази даних під час виконання. EM розробив д-р Томас Вайт (TMSWhite).
Ця вікі-сторінка є основним довідником із синтаксису та функціональності Expression Manager.
Основні визначення
- Вираз: усе, що взято у фігурні дужки
- За умови, що одразу після відкривної дужки або перед закривною фігурною дужкою немає пробілів
- Вміст виразів обчислюється EM, тому він може містити математичні формули, функції та складну обробку рядків і дат.
- Адаптація: інколи її називають «piping», це процес умовної зміни тексту
- Ви маєте доступ до всіх «полів заміни», дані учасника та дані відповідей.
- Ви також отримуєте простіший доступ до питань, відповідей та їхніх властивостей.
- Рівняння релевантності: новий атрибут питання, що керує видимістю питання
- Якщо є рівняння релевантності, питання показується лише тоді, коли воно набуває значення «істина».
- Внутрішньо всі команди array_filter і array_filter_exclude перетворюються на релевантність на рівні підпитання
- Рівняння (тип питання): новий тип питання, що зберігає обчислення або звіти в базі даних
- Він схожий на питання Boilerplate, але його вміст зберігається в базі даних, навіть якщо ввімкнено «Завжди ховати це запитання»
- Код запитання: це бажане ім’я змінної для EM
- Це може бути описова назва, що вказує на призначення питання, що полегшує читання складної логіки
- Допустимі коди питань НЕ повинні починатися з цифри, тому для нумерації питань за допомогою коду питання просто використовуйте «q1», «q1a» або «g1q2».
- Саме це наразі стає іменем змінної під час експорту даних до SPSS або R, тож якщо ви виконуєте статистичний аналіз, ви, імовірно, уже зробили його унікальним.
Чи обов’язково мені використовувати EM?
Коротка відповідь: ні (але й так).
EM повністю зворотно сумісний з наявними опитуваннями. Тож якщо вас влаштовує використання умов та оцінювання в стилі, який LimeSurvey використовував у версіях <= 1.91+, ви можете й надалі так робити.
Проте EM повністю замінює спосіб, у який LimeSurvey внутрішньо працює з умовами. Хоча ви все ще можете використовувати редактор умов для створення та керування умовами, LimeSurvey 1.92 перетворить їх на еквівалентні рівняння релевантності. Під час оновлення LimeSurvey 1.92 автоматично перетворить усі наявні умови на рівняння релевантності.
Це дає змогу отримати найкраще з обох підходів: ви можете й надалі користуватися LimeSurvey так, як звикли, але бачитимете еквівалентне рівняння релевантності, тож зможете поступово переходити безпосередньо до рівнянь релевантності, коли вважатимете за потрібне.
Чи можна поєднувати Умови та Релевантність?
Так. Ви можете використовувати редактор умов для одних питань, а редактор релевантності — для інших. Умови автоматично перетворюються на релевантність під час збереження питання.
Зверніть увагу: ми виходимо з того, що якщо ви використовуєте редактор умов, то хочете, щоб ці умови перезаписали будь-яке рівняння релевантності, введене вручну. Тому, якщо у вас є наявні умови і ви хочете вручну змінити релевантність, спочатку видаліть умови для цього питання. А саме: скопіюйте згенероване рівняння релевантності до текстового редактора, за допомогою меню умов видаліть усі умови для цього питання (це також видалить релевантність), потім відредагуйте питання та вставте згенероване рівняння релевантності з текстового редактора назад у поле релевантності цього питання (і збережіть питання). Якщо буде достатній попит на видалення умов без видалення згенерованого рівняння релевантності, ми зможемо додати процес масового перетворення.
Як вибрати між Умовами та Релевантністю?
Ось перелік переваг і недоліків кожного підходу:
| Підхід | Переваги | Недоліки |
|---|---|---|
| Умови | 1. Зручний графічний інтерфейс для створення простих умов 2. Графічний інтерфейс добре задокументований і зрозумілий команді підтримки |
1. Підтримуються лише прості порівняння, погано працює з умовами AND/OR 2. Каскадні умови працюють нестабільно 3. Повільно: інтенсивне використання бази даних може уповільнювати довгі опитування 4. Повідомлялося про проблеми з повторним завантаженням умов 5. Графічний інтерфейс погано масштабується, коли є десятки, сотні чи тисячі питань 6. Перенесення паперових опитувань може бути повільним, оскільки потрібно використовувати назви SGQA 7. Для складного розгалуження часто потрібен програміст, який напише спеціальну логіку |
| Релевантність | 1. Підтримує дуже складну логіку, зокрема 80+ функцій та математичні/рядкові оператори 2. Чудова підтримка каскадної логіки 3. Швидко: немає додаткових звернень до бази даних, тому підтримуються опитування з 1000+ питань 4. Немає проблем із повторним завантаженням логіки, оскільки коди SGQA не потрібні 5. Підсвічування синтаксису масштабується до опитувань з 1000+ питань 6. Легко і швидко використовувати групам, які хочуть комп'ютеризувати наявні паперові опитування. 7. Легко підтримує напівструктуровані інтерв'ю та епідеміологічні опитування без залучення програмістів |
1. Немає графічного інтерфейсу для простих умов: натомість використовуйте підсвічування синтаксису 2. Це нове, тому команди підтримки ще не опанували EM. |
Підсумок такий: якщо вас влаштовує те, як працює LimeSurvey 1.91+, немає причин змінювати свій підхід.
Які ще переваги дає використання EM?
Ось інші причини, з яких вам може знадобитися EM.
- Обчислення — ви можете створити будь-яке обчислення, яке тільки можете уявити:
- Вам доступні всі поширені математичні оператори та функції
- Вам доступні понад 70 математичних функцій, функцій обробки дат і рядків
- Розробникам досить легко додавати нові функції, якщо вони потрібні користувачам
- Збереження обчислень у базі даних
- Тепер ви можете виконувати прості й складні обчислення та/або обчислювати бали за шкалою І зберігати їх у базі даних без використання JavaScript.
- Для цього використовується тип питання «Рівняння».
- Оцінювання
- Тепер ви можете створювати оцінювання або бали за шкалою з будь-якого типу питання, а не лише з того обмеженого набору, який підтримувався раніше
- Ви можете використовувати тейлоринг, щоб показувати поточні або загальні бали оцінювання в будь-якому потрібному місці — навіть на тій самій сторінці
- Ви маєте більше контролю над звітами, що генеруються на основі цих балів оцінювання
- Ви можете зберігати бали оцінювання в базі даних без використання JavaScript
- Ви можете приховувати бали оцінювання без використання JavaScript чи CSS
- Поля підстановки
- Використовуйте код питання, щоб вставляти значення з відповідей на попередні питання — так легше читати та перевіряти.
- Тейлоринг — ви можете умовно показувати текст залежно від інших значень
- Використовуйте відповідне звертання до респондента, наприклад (напр. «Вітаємо, [пане/пані] Смит»)
- Формуйте граматично правильні речення, коли важливі однина/множина: (напр. «У вас 1 дитина» і «У вас 2 дітей»)
- Правильно відмінюйте дієслова та іменники залежно від статі й числа респондента.
- Нові атрибути змінних — для тейлорингу вам доступні такі:
- (без суфікса) — псевдонім для qcode.code
- .code — вибраний код відповіді на питання, якщо воно релевантне (інакше порожньо), або текстове значення, якщо це питання без кодів
- .NAOK — те саме, що .code, але може бути частиною обчислень або списків, навіть якщо питання нерелевантне
- .value — значення оцінки для питання, якщо воно релевантне (інакше порожньо), або текстове значення, якщо це питання без кодів — доступне, якщо для опитування ввімкнено оцінювання, інакше завжди дорівнює нулю
- .valueNAOK — те саме, що .value, але може бути частиною обчислень або списків, навіть якщо питання нерелевантне
- .shown — відповідь у тому вигляді, в якому її бачить користувач
- .qid — ідентифікатор питання
- .gid — ідентифікатор групи
- .sgqa — значення SGQA для питання
- .jsName — правильна назва змінної JavaScript для питання, незалежно від того, визначено її на цій чи на іншій сторінці
- .qseq — порядковий номер питання (починаючи з 0)
- .gseq — порядковий номер групи (починаючи з 0)
- .mandatory — чи є питання обов'язковим (Y/N)
- .question — текст питання
- .relevance — рівняння релевантності для питання
- .grelevance — рівняння релевантності для групи
- .relevanceStatus — чи є питання наразі релевантним (булеве значення (може відрізнятися в PHP і JS))
- .type — тип питання (однолітерний код)
- Динамічні зміни на сторінці
- Уся релевантність, обчислення та тейлоринг працюють динамічно на сторінці — тож зміни значень миттєво оновлюють сторінку
- Отже, питання динамічно з'являються/зникають залежно від того, чи вони релевантні
- Питання також динамічно адаптуються на основі відповідей на сторінці, тому ви можете бачити поточні підсумки, адаптовані речення та індивідуальні звіти.
- Новий екран введення даних
- Окрім поточної системи введення даних, ви можете просто використовувати режим «Опитування все в одному».
- Він підтримує релевантність і тейлоринг на сторінці, тож оператори введення даних можуть швидко переходити між полями і вводитимуть лише релевантні відповіді
- Це може бути критично, якщо вашій особі, що вводить дані, потрібно бачити тейлоринг, який також є динамічним.
- Усуває потребу в більшості власного коду JavaScript
- EM легко підтримує складні обчислення, підрахунок балів, тейлоринг та умовну логіку.
- Для деяких речей усе ще знадобиться JavaScript (наприклад, власні макети та умовне приховування піделементів питання), але ваш JavaScript може використовувати функції EM, щоб ви могли отримувати доступ до питань за їхнім Qcode замість SGQA, а також до будь-яких властивостей питання, перелічених вище.
Які ще корисні нові можливості надає EM?
Незалежно від того, чи ви продовжуєте користуватися редактором умов, чи складаєте рівняння релевантності вручну, ви отримуєте такі додаткові переваги:
- Ви можете створювати складніші критерії перевірки
- Усі розширені атрибути питання (наприклад, max_answers, min_num_value_n, max_num_value) можуть використовувати вирази. Тому критерії мінімуму/максимуму можна легко змінювати залежно від попередніх відповідей, навіть якщо вони розміщені на тій самій сторінці.
- EM також обробляє всю перевірку на основі регулярних виразів, тому ви можете надійно поєднувати атрибути питання на основі preg і рівнянь.
- Легка зміна порядку (або видалення) питань і груп
- До версії 1.92 не можна було змінювати порядок питань чи груп, якщо LimeSurvey вважав, що така зміна може порушити умови, в яких вони використовувалися. Так само не можна було видалити питання, від яких залежали інші питання.
- Завдяки підсвічуванню синтаксису в EM легко побачити й перевірити, чи не використовуєте ви питання до того, як їх оголошено. Тому тепер ви можете змінювати порядок або видаляти питання і групи будь-коли. EM оновить усе підсвічування синтаксису, щоб показати потенційні помилки.
- Вигляд зміни порядку питань було вдосконалено для такої перевірки. Тепер він показує рівняння релевантності питання та персоналізацію, тож ви одразу бачите, чи не стали якісь змінні рожевими (це означає, що їх використано до оголошення).
- Покажчик навігації за питаннями/групами завжди доступний і точний
- До версії 1.92 ці покажчики були недоступні за наявності складних умов
- З EM ми можемо гарантувати їхню точність.
- Респонденти можуть навіть повернутися до попереднього питання, змінити відповідь, а потім перейти вперед (або надіслати анкету)
- Під час переходу вперед EM повторно перевірить усі проміжні питання/групи.
- Якщо якісь питання стають нерелевантними, у базі даних для них буде записано NULL, щоб ваші дані були внутрішньо узгодженими
- Якщо якісь питання стають релевантними або вперше не проходять правила обов'язковості чи перевірки, EM зупиниться на цій сторінці й змусить користувача відповісти на ці питання, перш ніж перейти до кінцевого пункту призначення.
- Автоматичне перетворення умов на релевантність
- Під час оновлення бази даних для всіх наявних опитувань з умовами буде створено рівняння релевантності
- Щоразу, коли ви імпортуєте опитування, за потреби створюватимуться рівняння релевантності
- Щоразу, коли ви додаєте, видаляєте або змінюєте умови, EM створюватиме відповідне рівняння релевантності.
- Зручне підсвічування синтаксису
- Коли EM показує рівняння релевантності, він показує Qcode, навіть якщо ви ввели код SGQA, оскільки ми вважаємо, що так легше читати.
- Усі змінні виділено кольором, щоб показати, чи їх оголошено до чи після поточного питання (або до чи після поточної групи). Це дає змогу швидко виявити й виправити випадки, коли ви намагаєтеся використати змінні в релевантності (зокрема array_filter), персоналізації або рівняннях перевірки до їх оголошення.
- Крім того, якщо навести вказівник миші на змінну, виділену кольором, ви побачите найважливіші метадані про це питання. Це зокрема № послідовності групи, № послідовності питання, Qcode, текст питання та всі доступні варіанти відповідей (якщо це тип питання з переліченими варіантами відповідей).
- Список варіантів відповідей використовує такий синтаксис: 'answers':{key:val, ... }.
- key має синтаксис 'scale~code', де scale — це шкала відповіді (наприклад, для подвійної шкали), а code — код відповіді.
- val має синтаксис 'value~shown', де value — це значення оцінки (якщо використовується оцінювання, інакше code) (наприклад, Qcode.value), а shown — це значення, яке бачить респондент (наприклад, Qcode.shown)
- Це означає, що багато опитувань можуть використовувати обчислення без режиму оцінювання. Якщо ваші перелічені варіанти відповідей унікальні, не десяткові й невід'ємні, ви можете просто виконувати обчислення зі значеннями Qcode.code.
- Легкий перегляд усієї логіки та вмісту опитування
- З'явилася нова функція «Показати логіку опитування», яка дозволяє побачити все про опитування (або групу чи питання) на одній сторінці
- Вона показує деталі на рівні групи, питання, підпитання та відповіді для вибраної області (опитування, група чи питання)
- Вона також показує релевантність, релевантність на рівні підпитань (для array_filter і array_filter_exclude), згенероване рівняння перевірки (для preg та будь-яких правил перевірки, як-от мінімум/максимум суми/кількості значень) і всі непорожні атрибути питання.
- Усе підсвічено за синтаксисом, щоб ви могли бачити потенційні синтаксичні помилки (наприклад, незбалансовані дужки або використання змінних до їх оголошення)
- Підсвічування синтаксису забезпечує швидку навігацію та редагування опитування.
- Якщо клацнути назву змінної, відкриється вікно (або вкладка) браузера, яке показує це питання та дозволяє його редагувати.
- Якщо клацнути назву групи, відкриється вікно (або вкладка) браузера з виглядом зміни порядку груп, щоб ви могли легко переміщувати питання.
- Усі атрибути питання також підсвічуються за синтаксисом. Це дає змогу задавати й бачити вирази в розширених параметрах питання (наприклад, базувати мінімум/максимум кількості/суми значень на виразі)
- Автор EM використовував подібний вигляд (трохи чистіший), щоб його співпрацюючі епідеміологи та інституційна комісія з етики могли перевіряти й затверджувати опитування з тисячами питань у сильно розгалужених і персоналізованих структурованих інтерв'ю
Початок роботи
Найкращий спосіб почати роботу з EM:
- Встановіть останню стабільну версію з http://www.limesurvey.org/en/download
- Імпортуйте та вивчіть зразки опитувань.
- Ознайомтеся з прикладами використання та інструкціями і покроковими прикладами.
- Вивчіть документацію EM (ця сторінка)
- Перегляньте вбудований набір тестів EM
- У будь-якому опитуванні в розділі «Інструменти» виберіть параметр EM
- Розділ «Доступні функції» містить перелік понад 70 функцій і їхній синтаксис
- Модульні тести окремих виразів
- показують приклади використання всіх функцій і операторів EM, а також результати в PHP і JavaScript
- зверніть увагу, що є кілька функцій, які дають різні результати у версіях PHP і JavaScript, тож ця сторінка допоможе вам спланувати логіку EM відповідно.
Яку функціональність розширює/замінює Expression Manager? (LimeSurvey <= 1.91+)
Умови => Релевантність
Умови керували тим, які питання видимі. Загальний синтаксис був SGQA оператор Значення, наприклад 111X2X3 == "Y". Умови можна було поєднувати через AND або OR, але змішування AND і OR було складним. Самі умови зберігалися в окремій таблиці, і значна частина коду LimeSurvey була присвячена керуванню умовами. Через інтенсивний доступ до бази даних обробка великої кількості умов могла спричиняти помітні проблеми з продуктивністю. Крім того, коли до питань або груп було призначено умови, часто не дозволялося змінювати їхній порядок або видаляти їх.
Оцінювання => Рівняння та мікроперсоналізація
Оцінювання дозволяло користувачам створювати шкальні бали із сукупності питань. Однак вони не могли динамічно змінюватися на поточній сторінці, а їхні значення не зберігалися в базі даних.
Підстановки => Мікроперсоналізація
Користувачі могли персоналізувати деякі повідомлення та питання на основі попередніх відповідей. Наприклад, питання могло бути таким: {TOKEN:FIRSTNAME}, ви сказали, що {SPORT.shown} — ваш улюблений вид спорту. Однак без складного JavaScript було неможливо виконувати умовну персоналізацію (наприклад, казати «пан» або «пані» залежно від статі особи), а також відмінювати іменники чи змінювати дієслова за формами. Автори могли створювати опитування, що здавалися персоналізованими, але це вимагало окремих питань для кожної комбінації та складних умов для вибору питань, які слід показувати.
Перевірка
Питання можна було перевіряти за допомогою регулярних виразів або мінімальних/максимальних значень, або дозволити відповіді слугувати мінімальним чи максимальним значенням. Однак без складного JavaScript перевірки не могли базуватися на обчисленнях інших змінних.
Рівняння
Рівняння не підтримувалися без складного JavaScript.
Тип питання «Рівняння»
Рівняння (наприклад, остаточний бал оцінювання) не можна було зберегти в базі даних без складного JavaScript.
Як Expression Manager замінить/розширить цю функціональність?
Expression Manager — це новий основний модуль LimeSurvey, який значно полегшує підтримку складної функціональності, що раніше вимагала власного JavaScript. Він також замінює спосіб, у який LimeSurvey наразі керує умовами та оцінюванням.
Нова термінологія щодо Expression Manager (EM)
EM «мислить» свою функціональність такими термінами:
- Розгалуження на основі релевантності — якщо питання релевантне, то його ставлять, інакше ні (тобто роблять невидимим і позначають як NULL у базі даних). З'явилося нове поле «Релевантність» для всіх типів питань, а також для кожної групи (тож ви можете застосувати набір умов до цілої групи, не копіюючи ту саму умову до кожного питання, та/або поєднувати умовну логіку на рівні груп і питань).
- Персоналізація — коли ви знаєте, які питання слід ставити, персоналізація (іноді її називають piping) визначає, як саме ставити питання. Це дає змогу підтримувати не лише просту підстановку (як-от {TOKEN:FIRSTNAME}), а й змінювати дієслова та відмінювати іменники залежно від статі чи кількості ваших респондентів. Вона також дозволяє змінювати повідомлення, яке ви показуєте респонденту, залежно від того, чи відповів він (або як відповів) на інші питання.
- Рівняння — EM додає новий тип питання під назвою «Рівняння», який зберігає результат виразу. Результати цих рівнянь обчислюються та записуються в базу даних, навіть якщо ви приховуєте їх на сторінці. Тому вони корисні для прихованих обчислень балів, навігації на основі складних рівнянь, оцінювання та звітів, які мають створюватися й бути легко доступними в базі даних.
Релевантність і каскадна релевантність
Кожен тип питання тепер має параметр «Релевантність», який керує тим, чи показується питання. EM обробляє кожне рівняння релевантності в тому порядку, у якому вони мають з'являтися в опитуванні. Якщо вираз істинний (або відсутній — для підтримки старих опитувань), питання буде показано. Якщо воно не релевантне, питання буде приховано, а значення в базі даних стане NULL. Якщо в групі немає релевантних питань, усю групу буде пропущено.
Крім того, якщо будь-яка зі змінних у виразі нерелевантна, вираз завжди дає значення «хибність». Це забезпечує каскадну релевантність, тож вам не потрібно писати дуже довгі рівняння релевантності для кожного питання.
Припустімо, у вас є 5 питань Q1–Q5, і ви хочете показувати Q2 лише якщо була дана відповідь на Q1, Q3 — якщо була дана відповідь на Q2 тощо. Рівняння релевантності можуть бути такими:
| Код запитання | Релевантність | Питання |
|---|---|---|
| Q1 | 1 | Як вас звати? |
| Q2 | Q1 | {Q1}, скільки вам років? |
| Q3 | Q2 | Отже, вам {Q2} років. Ви одружені? |
| Q4 | Q3 == "Y" | {Q1}, як довго ви одружені? |
| Q5 | Q4 | Скільки у вас дітей, {Q1}? |
Обчислення релевантності також працюють у JavaScript — тож ви можете розмістити всі наведені вище питання на одній сторінці, і все працюватиме як очікується. Фактично EM повністю замінює спосіб, у який EM обробляє формати опитування «усе на одній сторінці», «по групах» і «по одному питанню». Тепер усі вони використовують той самий механізм навігації, тому працюють однаково незалежно від стилю опитування.
Поки ви перебуваєте на тій самій сторінці, усі введені вами дані залишатимуться на місці, просто прихованими. Тож якщо ви введете якусь інформацію, потім виберете варіант, що робить її нерелевантною, а потім знову зробите її релевантною, ваші відповіді залишаться доступними. Однак щойно ви перейдете на іншу сторінку, усі нерелевантні відповіді буде втрачено задля цілісності набору даних.
Релевантність на рівні групи
Expression Manager також підтримує релевантність на рівні групи. Це спрощує реалізацію циклів. Припустімо, ви хочете зібрати інформацію щодо до 10 об'єктів (наприклад, продуктів або членів домогосподарства), при цьому спочатку визначаєте, для скількох об'єктів потрібні додаткові питання (наприклад, запитавши, скільки людей мешкає в домогосподарстві, або попросивши респондентів відзначити в довгому списку продукти, які їм подобаються). Дізнавшись, для скількох об'єктів потрібні додаткові питання, ви можете використати релевантність на рівні групи, наприклад {count >= 1}, {count >=2}, ... {count >= 10} для кожної з 10 груп додаткових питань. Усередині кожної групи можна застосувати умовну логіку на рівні питання (наприклад, додаткові питання залежно від статі чи віку кожної особи). Рівняння релевантності на рівні питання та групи поєднуються через логічне І, щоб визначити, що саме слід показувати.
Адаптація тексту / Piping
Усе, що знаходиться у фігурних дужках, тепер розглядається як вираз (за одним винятком, описаним нижче). Вирази мають доступ до всіх LimeReplacementFields, до всіх змінних (через кілька псевдонімів), до всіх типових операторів рівнянь (математичних, логічних і порівняння) та до десятків функцій (які навіть працюють динамічно на стороні клієнта).
За допомогою цих рівнянь ви можете, наприклад:
- Умовно показувати респондентам адаптовані повідомлення на основі попередніх відповідей
- Створювати оцінювання та показувати його результати (або умовно переходити чи показувати повідомлення на основі цих результатів) без використання самого модуля оцінювання
- Відмінювати іменники та змінювати дієслова за формами у питаннях, відповідях і звітах.
- Показувати підсумки відповідей перед сторінкою «Показати ваші відповіді» наприкінці опитування
Рівняння
Існує новий тип питання під назвою «Рівняння». Він схожий на питання Boilerplate, але зберігає в базі даних значення того, що відображається. Тому, якщо текст питання типу «Рівняння» містить обчислення оцінювання, це значення буде збережено в базі даних у змінній, яку можна відображати в публічній або приватній статистиці.
Це вирішує поширений запит щодо збереження балів оцінювання в базі даних.
Синтаксис
Усе, що міститься у фігурних дужках, тепер вважається виразом (за одним винятком: на початку й наприкінці не повинно бути пробілів — це потрібно для того, щоб Expression Manager не намагався обробляти вбудований JavaScript).
Зверніть увагу: вирази можуть займати кілька рядків, якщо після відкривної фігурної дужки та перед закривною немає пробілів. Це особливо зручно для вкладених операторів if(), як у цьому прикладі:
{if(is_empty(PFTotals),
'',
if(PFTotals >= -5 && PFTotals <= -4,
'Very Soft',
if(PFTotals >= -3 && PFTotals <= -2,
'Soft',
if(PFTotals == -1,
'Somewhat Soft',
if(PFTotals == 0,
'Moderate',
if(PFTotals == 1,
'Somewhat Hard',
if(PFTotals >= 2 && PFTotals <= 3,
'Hard',
if(PFTotals >= 4 && PFTotals <= 5,
'Very Hard',
''
)
)
)
)
)
)
)
)}
- Усі стандартні математичні оператори (наприклад, +,-,*,/,!)
- Усі стандартні оператори порівняння (наприклад, <,<=,==,!=,>,>=, а також еквіваленти: lt,le,eq,ne,gt,ge)
- Круглі дужки (для групування підвиразів)
- Умовні оператори (наприклад, &&,| | та їхні еквіваленти: and,or)
- Рядки в одинарних і подвійних лапках (у кожному з яких можна вкладати рядки з лапками іншого типу)
- Оператор «кома» (дозволяє мати список виразів і повертати лише останній результат)
- Оператор присвоєння (=)
- Попередньо визначені змінні (для посилання на питання, атрибути питань і відповіді) — наприклад, усі коди SGQA
- Попередньо визначені функції (їх уже понад 70, і додавати нові легко)
Оператори
Синтаксис EM дотримується звичайного пріоритету операторів:
| Рівень | Оператор(и) | Опис |
|---|---|---|
| 1 | () | круглі дужки для групування або виклику функцій |
| 2 | ! - + | унарні оператори: заперечення, зміна знака, унарний плюс |
| 3 | * / | множення, ділення |
| 4 | + - | додавання, віднімання |
| 5 | < <= > >= lt le gt ge | порівняння за величиною |
| 6 | == != eq ne | порівняння на рівність |
| 7 | and | логічне І |
| 8 | or | логічне АБО |
| 9 | = | оператор присвоєння |
| 10 | , | оператор «кома» |
Попередження щодо оператора плюс (+)
Для узгодженості між JavaScript і PHP оператор плюс (+) виконує додавання, якщо обидва операнди числові, і конкатенацію, якщо обидві частини є нечисловими рядками. Проте ми рекомендуємо використовувати функцію join() для конкатенації та функцію sum() для додавання, оскільки так ваш намір буде зрозумілішим, а також це дозволяє уникнути несподіваних результатів, якщо ви очікували рядки, а отримали числа (або навпаки).
Попередження щодо невідповідності числа й рядка та алфавітного порівняння
Коли ви порівнюєте значення за величиною або на рівність, зверніть увагу на невідповідність типів. Значення, введене користувачем, або вибраний код відповіді можна використовувати як число, якщо це явно число.
Якщо взяти одне зі значень у ", порівняння буде виконано як текстове (алфавітне). Якщо ви хочете порівнювати числа, ніколи не беріть число в лапки ".
Наприклад, Q0.NAOK > "50" має значення «істина», якщо Q0.NAOK — числове питання зі значенням 9. Це відбувається тому, що оператор > вважатиме порівняння алфавітним, а не числовим.
Щоб гарантовано порівнювати цілі значення, можна використати intval(Q0.NAOK) > 50, але пам'ятайте: якщо Q0.NAOK не є числом (порожнє значення або рядок), то intval(Q0.NAOK) == 0. Щоб порівнювати рядкові значення ("A" < "B"), використовуйте безпосередньо strcmp: strcmp(Q0.NAOK,"B") або strcmp(Q0.NAOK,"A5").
Застереження щодо використання оператора присвоєння (=)
Зверніть увагу: слід уникати операторів присвоєння, якщо в цьому немає крайньої потреби, оскільки вони можуть спричинити несподівані побічні ефекти. Наприклад, якщо ви змінюєте значення попередньої відповіді, каскадна логіка релевантності та перевірки між цим питанням і поточним питанням не перераховується, тож ви можете отримати внутрішньо суперечливі дані (наприклад, питання, що залишилися з відповіддю, хоча мали б мати значення NULL, або питання, які пропущено, хоча на них слід було відповісти). Загалом, якщо потрібно присвоїти значення змінній, слід створити питання типу «Рівняння» і за допомогою виразу встановити його значення. Проте іноді цей оператор справді потрібен, тому ми зробили його доступним.
Щоб застерегти вас щодо цього оператора, у рівняннях із синтаксисом він показується червоним шрифтом (щоб ви не плутали його з «==»).
Використання оператора присвоєння
Основні причини, з яких може знадобитися присвоєння:
- Потрібно встановити значення за умовчанням для питання, яке не приймає значення за умовчанням через рівняння (наприклад, список із перемикачами, де інтерфейс дозволяє вибрати один із варіантів відповідей, але не дає змоги ввести рівняння). Однак будьте обережні: LimeSurvey не зможе перевірити, що ваше рівняння видає одну з допустимих відповідей для цього питання.
- Потрібно примусово змінити відповідь на попереднє питання на основі пізнішої відповіді
- Потрібна складна квота: використання одного прихованого питання з одиничним вибором для квоти та встановлення його значення через присвоєння
- тощо
Для цього можна використовувати всю систему Expression Manager.
Кілька прикладів:
- Встановити відповідь на питання з коротким текстом у нижньому регістрі:
{QCODE=strtolower(QCODE.NAOK)} - Встановити відповідь за умовчанням для питання типу «масив» на початку опитування:
{Q1_SQ1=((is_empty(Q1_SQ1.NAOK),"A99",Q1_SQ1.NAOK)} - Встановити відповідь за умовчанням для питання типу «масив текстів» на початку опитування:
{Q1_SQY1_SQX1 = ((is_empty(Q1_SQY1_SQX1.NAOK),"Inserted answer", Q1_SQY1_SQX1.NAOK)} - Встановити відповідь за умовою:
{QCODE=if(YesNo="Y","A1","")}
Безпека XSS
Якщо ввімкнено захист від XSS, деякі можливості Expression Manager використовувати не можна:
- початок HTML-тегу в одному виразі та його закінчення в іншому виразі;
- використання складного виразу в URL.
Приклад і обхідний шлях
{if( 1 ,"<strong>","")}information{if( 1 ,"</strong>","")}не працює із захистом від XSS, тут можна використати{if(1,"<strong>information</strong>","information")}<a href="/script.php?value={if(QCODE == "Y","yes","no")}">next</a>, тут можна використати питання типу «Рівняння», оскільки використання повного коду питання допустиме:<a href="/script.php?value={EQUATION.NAOK}">next</a>
Доступ до змінних
Expression Manager надає доступ лише для читання до будь-яких змінних, які можуть знадобитися. Для зворотної сумісності він надає доступ до такого:
- TOKEN:xxx - значення TOKEN (наприклад, TOKEN:FIRSTNAME, TOKEN:ATTRIBUTE_5) (лише для НЕанонімних опитувань).
- QCODE.shown - відображуване значення відповіді (наприклад, «Так») за допомогою Expression Manager.
- Усі значення {XXX}, що використовуються шаблонами.
- У тексті питання можна використовувати {QID}, яке замінюється на ідентифікатор питання, та {SGQ}, яке замінюється на SGQA питання.
Крім того, Expression Manager дає змогу посилатися на змінні за кодом питання (стовпець 'title' у таблиці питань у базі даних). Це також мітка змінної, яка використовується під час експорту даних до SPSS, R або SAS. Наприклад, якщо у вас є питання про ім’я, вік і стать, ви можете назвати ці змінні name, age і gender замість 12345X13X22, 12345X13X23 і 12345X13X24. Це полегшує всім читання рівнянь і перевірку логіки, а також дає змогу переставляти питання, не відстежуючи номери груп або питань.
Важливо: безпечно посилатися лише на змінні, що містяться на попередніх сторінках або в попередніх питаннях.
Крім того, Expression Manager дає змогу отримати доступ до багатьох властивостей питання:
| Синтаксис | Значення | Приклад | Результат прикладу |
|---|---|---|---|
| Qcode | псевдонім для Qcode.code | {implode(',',name,gender)} | 'Tom','M' |
| Qcode.code | вибраний код відповіді на питання, якщо воно релевантне (інакше порожньо), або текстове значення, якщо питання не має кодів відповідей | {implode(',',name.code,gender.code)} | 'Tom','M' |
| Qcode.NAOK | те саме, що Qcode - див. обговорення NAOK | {gender.NAOK} | 'M' |
| Qcode.value | значення оцінки для питання, якщо воно релевантне (інакше порожньо), або текстове значення, якщо питання не має кодів відповідей | {gender.value} | '1' |
| Qcode.valueNAOK | те саме, що Qcode.value - див. обговорення NAOK | {gender.valueNAOK} | '1' |
| Qcode.shown | відображуване значення для питання | {implode(',',name.shown,gender.shown)} | 'Tom','Male' |
| Qcode.question | текст питання | {gender.question} | 'Яка ваша стать?' |
| Qcode.mandatory | чи є питання обов'язковим (Y/N) | {gender.mandatory} | 'N' |
| Qcode.qid | внутрішній номер питання (не порядковий номер) | {gender.qid} | 337 |
| Qcode.type | тип питання | {gender.type} | 'G' |
| Qcode.jsName | правильне ім'я JavaScript для питання, незалежно від того, оголошене воно на цій сторінці чи ні | {gender.jsName} | 'java1827X3X337' |
| Qcode.gid | внутрішній номер групи (не порядковий номер) | {gender.gid} | 3 |
| Qcode.qseq | порядковий номер питання, починаючи з 0 | {gender.qseq} | 5 |
| Qcode.gseq | порядковий номер групи, починаючи з 0 | {gender.gseq} | 1 |
| Qcode.relevanceStatus | чи є питання наразі релевантним (0 або 1) | {gender.relevanceStatus} | 1 |
| Qcode.relevance | рівняння релевантності на рівні питання | {gender.relevance} | '!is_empty(name)' |
| Qcode.grelevance | рівняння релевантності на рівні групи | {gender.grelevance} | 'num_children >= 5' |
| Qcode.sgqa | значення SGQA для цього питання | {gender.sgqa} | '1827X3X337' |
Проблема з HTML редактором
Якщо ви використовуєте HTML редактор, деякі символи замінюються на HTML-сутності.
- & на &
- < на <
- > на >
Якщо ви використовуєте HTML редактор, потрібно використовувати:
- and замість &
- lt замість <
- le замість <=
- gt замість >
- ge замість >=
Іменування змінних Qcode
Нижче наведено подробиці того, як побудувати Qcode (та отримати доступ до деяких властивостей) залежно від типу питання. Загалом Qcode будуються так:
QuestionCode . '_' . SubQuestionCode . '_' . ScaleId
Код підпитання та ідентифікатор шкали потрібно використовувати чи ні залежно від типу питання - див. таблицю нижче. Для comment і other коди питань - QuestionCode_comment та QuestionCode_other
| Тип | Опис | Код | Підпитання | Варіанти відповідей | Шкали | Код відповіді | Показана відповідь | Релевантність |
|---|---|---|---|---|---|---|---|---|
| 5 | Вибір із 5 варіантів, радіокнопки | Q1 | 1-5 | {Q1} | {Q1.shown} | {Q1==3} | ||
| B | Масив (вибір із 10 пунктів), радіокнопки | Q2 | L1-L6 | 1-10 | {Q2_L2} | {Q2_L2.shown} | {Q2_L2==7} | |
| A | Масив (вибір із 5 пунктів), радіокнопки | Q3 | 1-5 | 1-5 | {Q3_1} | {Q3_1.shown} | {Q3_1>=3} | |
| 1 | Масив (гнучкі мітки), подвійна шкала | Q4 | sq1-sq5 | 0:a1-a3 | 1:b1-b3 | {Q4_sq1_0} | {Q4_sq1_1.shown} | {Q4_sq1_1=='b2'} |
| H | Масив (гнучкий) - формат стовпців | Q5 | 1-5 | s,m,t | {Q5_1} | {Q5_1.shown} | {Q5_1=='s'} | |
| F | Масив (гнучкий) - формат рядків | Q6 | F1-F5 | 1-5 | {Q6_F3} | {Q6_F3.shown} | {Q6_F3==4} | |
| E | Табличне запитання (Підвищення/Той самий рівень/Зниження), радіокнопки | Q7 | 1-7 | I,S,D | {Q7_4} | {Q7_4.shown} | {Q7_4=='D'} | |
| : | Масив (мультигнучкий) від 1 до 10 | Q8 | ls1,todo,ls2 | min,max,avg | {Q8_ls1_max} | {Q8_ls2_avg.shown} | {Q8_ls2_min==7} | |
| ; | Масив (мультигнучкий) текст | Q9 | hp,st,sw | 1st,2nd,3rd | {Q9_hp_3rd} | {Q9_hp_3rd.shown} | {Q9_hp_3rd=='Peter'} | |
| C | Масив (Так/Невизначено/Ні), радіокнопки | Q10 | 1-5 | Y,N,U | {Q10_1} | {Q10_1.shown} | {Q10_3=='Y'} | |
| X | Текстове питання (Boilerplate) | Q11 | {Q11.shown} | |||||
| D | Дата | Q12 | {Q12} | {Q12.shown} | ||||
| * | Рівняння | Q13 | {Q13} | {Q13.shown} | {Q13>5} | |||
| ~124~ | Завантаження файлу (записує кількість завантажених файлів) | Q14 | {Q14} | {Q14>0} | ||||
| G | Список «Стать», що розкривається | Q15 | M,F | {Q15} | {Q15.shown} | {Q15=='M'} | ||
| U | Величезний довільний текст | Q16 | {Q16} | {Q16.shown} | {strlen(Q16)>100} | |||
| I | Питання «Мова» | Q17 | {Q17} | {Q17.shown} | {Q17=='en'} | |||
| ! | Список (що розкривається) | Q18 | 1-5 | {Q18} | {Q18.shown} | {Q18==3} | ||
| L | Список, що розкривається/радіокнопки | Q19 | A-Z | {Q19} | {Q19.shown} | {Q19=='X'} | ||
| O | Список з коментарями, що розкривається/радіокнопки + текстове поле | Q20 | A-F | {Q20},{Q20comment} | {Q20.shown} | {Q20=='B'} | ||
| T | Довгий довільний текст | Q21 | {Q21} | {Q21.shown} | {strstr(Q21,'hello')>0} | |||
| M | Множинний вибір, прапорці | Q22 | A-F, other | {Q22_E}, {Q22_other} | {Q22_E.shown}, {Q22_other.shown} | {Q22_E=='Y'} | ||
| P | Множинний вибір з коментарями, прапорці + текст | Q23 | A-F | {Q23_D}, {Q23_Dcomment} | {Q23_D.shown} | {!is_empty(Q23)} | ||
| K | Множинне числове питання | Q24 | self,mom,dad | {Q24_self} | {Q24_self.shown} | {Q24_self>30} | ||
| Q | Кілька коротких текстів | Q25 | A-F | {Q25_B} | {Q25_B.shown} | {substr(Q25_B,1,1)=='Q'} | ||
| N | Числове питання | Q26 | {Q26} | {Q26.shown} | {Q26 > 30} | |||
| R | Рейтинг | Q27 | 1-4 | {Q27_1} | {Q27_1.shown} | {Q27_1==3} | ||
| S | Короткий довільний текст | Q28 | {Q28} | {Q28.shown} | {Q28=='mine'} | |||
| Y | Так/Ні, радіокнопки | Q29 | {Q29} | {Q29.shown} | {Q29=='Y'} |
Зарезервовані змінні 'this', 'self' та 'that'
Досить часто потрібно оцінити всі частини питання, наприклад, підрахувати, на скільки підпитань надано відповідь, або підсумувати бали. Іноді потрібно обробити лише певні рядки чи стовпці питання (наприклад, отримати суми за рядками чи стовпцями та зберегти їх у базі даних). Ці зарезервовані змінні роблять цей процес відносно простим.
Змінна 'this' використовується виключно в додаткових параметрах питання «Рівняння перевірки всього питання» та «Рівняння перевірки підпитання». Вона розгортається в імена змінних кожної з комірок у цих питаннях. Отже, якщо ви хочете переконатися, що кожне значення більше за три, задайте для «Рівняння перевірки підпитання» значення (this > 3).
Змінні 'self' і 'that' потужніші та працюють як макроси, що розгортаються перед обробкою рівнянь. Доступні варіанти синтаксису:
- self
- self.suffix
- self.sub-selector
- self.sub-selector.suffix
suffix - це будь-який зі звичайних суфіксів qcode (наприклад, NAOK, value, shown)
sub-selector - це одне з такого:
- comments - лише підпитання, що є коментарями (наприклад, із типів «Множинний вибір з коментарями» та «Список з коментарями»)
- nocomments - лише підпитання, що не є коментарями
- sq_X - де X - ідентифікатор рядка або стовпця. Вибираються лише підпитання, що відповідають шаблону X. Зверніть увагу: пошук виконується за повним кодовим ідентифікатором, після чого sq_X збігається з підпитаннями nX, X, Xn і включає їх (наприклад, якщо ви використовуєте sq_1, будуть включені підпитання a1, 1a, 1, 11 або 001). Зверніть увагу на тип питання з подвійною шкалою, де коди підпитань мають вигляд QCODE_SQCODE_1 і QCODE_SQCODE_1, та на тип питання «Рейтинг», де коди підпитань мають вигляд QCODE_1, QCODE_2 ....
- nosq_X - де X - ідентифікатор рядка або стовпця. Вибираються лише підпитання, що не відповідають шаблону X. Зверніть увагу: пошук виконується за повним кодовим ідентифікатором, після чого nosq_X збігається з підпитаннями, але не включає підпитання nX, X, Xn
Приклади:
- Чи надано відповідь на будь-яку частину питання? {count(self.NAOK)>0}
- Яка оцінка за це питання? {sum(self.value)}
Ви також можете використовувати їх для отримання підсумків за рядками та стовпцями. Припустімо, у вас є масив чисел із рядками A-E і стовпцями 1-5.
- Який загальний підсумок? {sum(self.NAOK)}
- Яка сума рядка B? {sum(self.sq_B.NAOK)}
- Яка сума стовпця 3? {sum(self.sq_3.NAOK)}
Змінна 'that' схожа на змінну 'self', але дає змогу посилатися на інші питання. Її синтаксис:
- that.qname
- that.qname.suffix
- that.qname.sub-selector
- that.qname.sub-selector.suffix
qname - це назва питання без жодних розширень підпитань. Наприклад, якщо ви створили питання 'q1', то це і є його qname
Приклади:
- Чи надано відповідь на будь-яку частину питання q1? {count(that.q1.NAOK)>0}
- Яка оцінка за питання q2? {sum(that.q2.NAOK)}
- Який загальний підсумок питання q3? {sum(that.q3.NAOK)}
- Яка сума рядка C у q4? {sum(that.q4.sq_C.NAOK)}
- Яка сума стовпця 2 у q4? {sum(that.q4.sq_2.NAOK)}
Змінні 'self' і 'that' можна використовувати в будь-якій релевантності, перевірці або адаптації тексту.
Єдине застереження: коли ви використовуєте функцію Показати файл логіки, вона показуватиме розгорнуте значення 'self' і 'that'. Це дає змогу побачити реальне рівняння, яке буде згенеровано, щоб ви (та Expression Manager) могли перевірити існування змінних. Це може збивати з пантелику, оскільки ви можете побачити досить довгі рівняння. Однак, якщо ви відредагуєте питання, то побачите початкове рівняння з використанням 'self' та/або 'that'
Також зауважте, що не слід використовувати ці змінні, якщо (а) ви хочете явно вказати кожну змінну, що використовується в рівнянні, або (б) використовуєте змінні без підпитань (наприклад, питання з однією відповіддю). У таких випадках додавати до змінної префікс 'that' зайве, і ви ризикуєте отримати неочікувані результати.
Використання NAOK
NAOK --> "Not Applicable" (NA) is alright (OK) — «Неактуально» (NA) — це нормально (OK)
Використання NAOK означає, що всі або деякі змінні є нерелевантними (тобто «Неактуально» (NA) — це нормально (OK)).
Якщо ви використовуєте в будь-якому рівнянні змінну з питання, а це питання (або підпитання) приховане за умовою, це робить недійсним усе рівняння.
Наприклад, count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) завжди повертає порожній рядок, якщо одне з підпитань Q1 відфільтровано. Щоб підрахувати кількість позначених підпитань у такому питанні, можна використати count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK). Якщо підпитання приховане, Expression Manager повертає порожній рядок.
Без NAOK: якщо одне питання або одне підпитання приховане, Expression Manager завжди повертає порожній рядок, що рівнозначно значенню false.
Суфікс .shown завжди використовує систему NAOK (порожній рядок, якщо питання приховане), але якщо вам потрібен код відповіді, завжди краще додавати .NAOK після коду запитання. Окрім випадків, коли він вам потрібен саме так і ви розумієте, що робите.
Інший приклад та додаткову інформацію наведено в розділі Перевизначення каскадних умов
Доступ до функцій
Expression Manager надає доступ до математичних, рядкових і користувацьких функцій, як показано нижче. Для цих функцій існують еквіваленти в PHP та JavaScript, тому вони працюють однаково на стороні сервера (PHP) і на стороні клієнта (JavaScript). Нові функції додати легко.
Реалізовані функції
Наразі доступні такі функції:
| Функція | Значення | Синтаксис |
|---|---|---|
| abs | Абсолютна величина | number abs(number) |
| acos | Арккосинус | number acos(number) |
| addslashes | Екранувати рядок за допомогою зворотних похилих рисок | string addslashes(string) |
| asin | Арксинус | number asin(number) |
| atan | Арктангенс | number atan(number) |
| atan2 | Арктангенс двох змінних | number atan2(number, number) |
| ceil | Округлити дроби (up) | number ceil(number) |
| checkdate | Повертає істину (1), якщо це дійсна дата за григоріанським календарем | bool checkdate(month,day,year) |
| convert_value | Перетворити числове значення за допомогою вхідної та вихідної таблиць числових значень | number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList) |
| cos | Косинус | number cos(number) |
| count | Підрахувати кількість запитань у списку, на які надано відповідь (непорожніх) | number count(arg1, arg12, ..., argN) |
| countif | Підрахувати кількість запитань у списку, на які надано відповідь, що дорівнює першому аргументу | number countif(matches, arg1, arg2, ... argN) |
| countifop | Підрахувати кількість запитань у списку, що відповідають критерію (arg op value) | number countifop(op, value, arg1, arg2, ... argN) |
| date | Форматувати місцеву дату / час | string date(format [, timestamp=time()]) |
| exp | Розрахувати експоненту e | number exp(number) |
| fixnum | Відображати числа з комою як роздільником дробової частини, за потреби | string fixnum(number) |
| floor | Округлити дроби (down) | number floor(number) |
| gmdate | Форматувати дату / час GMT | string gmdate(format [, timestamp=time()]) |
| html_entity_decode | Перетворити всі HTML-сутності на відповідні символи (завжди використовує ENT_QUOTES та UTF-8) | string html_entity_decode(string) |
| htmlentities | Перетворити всі відповідні символи на HTML-сутності (завжди використовує ENT_QUOTES та UTF-8) | string htmlentities(string) |
| expr_mgr_htmlspecialchars | Перетворити спеціальні символи на HTML-сутності (завжди використовує ENT_QUOTES та UTF-8) | string htmlspecialchars(string) |
| expr_mgr_htmlspecialchars_decode | Перетворити спеціальні HTML-сутності назад на символи (завжди використовує ENT_QUOTES та UTF-8) | string htmlspecialchars_decode(string) |
| idate | Форматувати місцевий час / дату як ціле число | string idate(string [, timestamp=time()]) |
| if (Updated in 3.0.2 ) | if(test,result_if_true[,result_if_false = ""]) у стилі Excel | if(test,result_if_true[,result_if_false = ""]) |
| implode | З'єднати елементи масиву в рядок | string implode(glue,arg1,arg2,...,argN) |
| intval | Отримати значення ціллого числа змінної | int intval(number [, base=10]) |
| is_empty | Визначити, чи вважається змінна порожньою | bool is_empty(var) |
| is_float | Дізнатися, чи є тип змінної числом з плаваючою комою | bool is_float(var) |
| is_int | Дізнатися, чи є тип змінної цілим числом | bool is_int(var) |
| is_nan | Дізнатися чи значення не є числом | bool is_nan(var) |
| is_null | Дізнатися чи змінна є порожньою (нульовою) | bool is_null(var) |
| is_numeric | Дізнатися, чи є змінна числом або числовим рядком | bool is_numeric(var) |
| is_string | Дізнатися, чи є тип змінної рядком | bool is_string(var) |
| join (New in 2.0 build 130129) | З'єднати елементи в новий рядок | join(arg1, arg2, ... argN) |
| list | Повернути список непорожніх значень, розділених комами | string list(arg1, arg2, ... argN) |
| listifop (New in 3.16.1 ) | Повернути список зазначеної властивості запитання (retProp), розділений «glue», із запитань у списку, що відповідають критерію (cmpProp op value) | string listifop(cmpProp, op, value, retProp, glue, sgqa1, sgqa2, ... sgqaN) |
| log | Логарифм числа за заданою основою або натуральний логарифм. | number log(number,base=e) |
| ltrim | Видалити пробіли (або інші символи) на початку рядка | string ltrim(string [, charlist]) |
| max | Знайти найбільше значення | number max(arg1, arg2, ... argN) |
| min | Знайти найменше значення | number min(arg1, arg2, ... argN) |
| mktime | Отримати штамп дати/часу UNIX для дати (кожен із 6 аргументів необов'язковий) | number mktime([hour [, minute [, second [, month [, day [, year ]]]]]]) |
| modulo-function | Функція остачі від ділення поки не підтримується. Натомість можна використати функцію floor() | floor(x/y)==(x/y) |
| nl2br | Вставляє HTML-розриви рядків перед усіма символами нового рядка в рядку | string nl2br(string) |
| number_format | Форматувати число до тисячних | string number_format(number) |
| pi | Отримати значення числа Пі | number pi() |
| pow | Експоненціальний вираз | number pow(base, exp) |
| quoted_printable_decode | Перетворити рядок quoted-printable на 8-бітний рядок | string quoted_printable_decode(string) |
| quoted_printable_encode | Перетворити 8-бітний рядок на рядок quoted-printable | string quoted_printable_encode(string) |
| quotemeta | Поставити лапки для метасимволів | string quotemeta(string) |
| rand | Згенерувати випадкове ціле число, див. цей приклад | int rand() OR int rand(min, max) |
| regexMatch | Порівняти рядок із регулярним виразом | bool regexMatch(pattern,input) |
| round | Округлення числа до додаткової точності | number round(val [, precision]) |
| rtrim | Видалити пробіли (або інші символи) наприкінці рядка | string rtrim(string [, charlist]) |
| sin | Синус | number sin(arg) |
| sprintf | Повернути відформатований рядок | string sprintf(format, arg1, arg2, ... argN) |
| sqrt | Квадратний корінь | number sqrt(arg) |
| stddev | Обчислити вибіркове стандартне відхилення для списку чисел | number stddev(arg1, arg2, ... argN) |
| str_pad | Доповнити рядок іншим рядком до певної довжини | string str_pad(input, pad_length [, pad_string]) |
| str_repeat | Повторити рядок | string str_repeat(input, multiplier) |
| str_replace | Замінити всі входження пошукового рядка рядком заміни | string str_replace(search, replace, subject) |
| strcasecmp | Бінарне безпечне порівняння рядків без урахування регістру | int strcasecmp(str1, str2) |
| strcmp | Бінарне безпечне порівняння рядків | int strcmp(str1, str2) |
| strip_tags | Зняти HTML та PHP теги з рядка | string strip_tags(str, allowable_tags) |
| stripos | Знайти позицію першого входження рядка Unicode без урахування регістру (починаючи з 0, повертає false, якщо не знайдено) | int stripos(haystack, needle [, offset=0]) |
| stripslashes | Зняти лапки рядка з лапками | string stripslashes(string) |
| stristr | Без урахування регістру strstr (Case-insensitive strstr) | string stristr(haystack, needle [, before_needle=false]) |
| strlen | Отримати довжину рядка | int strlen(string) |
| strpos | Знайти позицію першого входження рядка Unicode (починаючи з 0, повертає false, якщо не знайдено) | int strpos(haystack, needle [ offset=0]) |
| strrev | Перевернути рядок | string strrev(string) |
| strstr | Знайти перший випадок рядка | string strstr(haystack, needle[, before_needle=false]) |
| strtolower | Перетворити рядок на нижній регістр | string strtolower(string) |
| strtotime | Перетворити майже будь-який англійський текстовий опис дати й часу на штамп часу UNIX | int strtotime(string) |
| strtoupper | Перетворити рядок на верхній регістр | string strtoupper(string) |
| substr | Повернути частину рядка Unicode | string substr(string, start [, length]) |
| sum | Обчислити суму значень масиву | number sum(arg1, arg2, ... argN) |
| sumifop | Підсумувати значення запитань у списку, на які надано відповідь і які відповідають критерію (arg op value) | number sumifop(op, value, arg1, arg2, ... argN) |
| tan | Тангенс | number tan(arg) |
| time | Повертати поточний штамп дати/часу UNIX | number time() |
| trim | Видалити пробіли (або інші символи) на початку та в кінці рядка | string trim(string [, charlist]) |
| ucwords | Перетворити перший символ кожного слова в рядку на верхній регістр | string ucwords(string) |
| unique | Повертати істину, якщо усі непорожні відповіді є унікальними | boolean unique(arg1, ..., argN) |
Функції, які заплановані або розглядаються
Інші функції, які заплановані (або розглядаються), але ще не реалізовані, наведено нижче. Деякі з них потрібні для зворотної сумісності з іншим інструментом для опитувань.
| Синтаксис | Значення | Коментарі |
|---|---|---|
| e() | повертає значення e | |
| formatDate(X,PAT) | повертає рядкове значення дати X, відформатованої за шаблоном формату дати Java PAT | |
| formatNumber(X,PAT) | повертає рядкове значення числа X, відформатованого за шаблоном формату чисел Java PAT | |
| getAnsOption(X) | Основний плагін ExpressionAnswerOptions | |
| getAnsOption(X,Y) | Основний плагін ExpressionAnswerOptions | |
| getRelevance(X) | повертає рівняння релевантності для питання X | |
| getStartTime() | повертає дату, що відповідає системному часу початку опитування респондента | |
| getType(X) | повертає рядкову назву типу даних, напр. *NA*, якщо isNA() | |
| gotoFirst() | переходить до першого набору релевантних питань — це порушує звичайний хід роботи системи | |
| gotoNext() | переходить до наступного набору релевантних питань — це порушує звичайний хід роботи системи | |
| gotoPrevious() | переходить до попереднього набору релевантних питань — це порушує звичайний хід роботи системи | |
| isAsked(X) | повертає true, якщо відповідь не є ні *NA*, ні *INVALID*, ні *UNASKED* | |
| isInvalid(X) | повертає true, якщо відповідь має тип *INVALID* | |
| isNA(X) | повертає true, якщо відповідь має тип *NA* | |
| isNotUnderstood(X) | повертає true, якщо відповідь має тип *HUH* | |
| isRefused(X) | повертає true, якщо відповідь має тип *REFUSED* | |
| isSpecial(X) | повертає true, якщо відповідь має тип *UNASKED*, *NA*, *REFUSED*, *INVALID*, *UNKNOWN* або *HUH* | |
| isUnknown(X) | повертає true, якщо відповідь має тип *UNKNOWN* | |
| jumpTo(X) | переходить до групи, що містить питання із зазначеною назвою — це порушує звичайний хід роботи системи | |
| jumpToFirstUnasked() | переходить до першого непоставленого питання |
|
| lastIndexOf(X,Y) | повертає останній індекс (з нуля) рядка Y у рядку X. Повертає -1, якщо Y не міститься в X | |
| list(X,...) | рядок, що містить список додатних значень, розділених комами, де останні два розділено словом «і» | |
| mean(X,...) | повертає середнє значення списку значень | |
| numAnsOptions(X) | повертає кількість варіантів відповідей питання X | |
| orlist(X,...) | рядок, що містить список додатних значень, розділених комами, де останні два розділено словом «або» | |
| parseDate(X,PAT) | повертає значення дати з рядка X, розібраного за шаблоном формату дати Java PAT | |
| parseNumber(X,PAT) | повертає числове значення з рядка X, розібраного за шаблоном формату чисел Java PAT | |
| showAllResponsesExcept( questionList,attributeList,attributeTitleList) | »; attributeList = список атрибутів, розділений символом «|» (як-от question#, title, text, type — щоб ви могли вирішити, що показувати); attributeTitleList = список заголовків таблиці, розділений символом «|», щоб можна було локалізувати звіт. | |
| showTheseResponses( questionList,attributeList,attributeTitleList) | »; attributeList = список атрибутів, розділений символом «|» (як-от question#, title, text, type — щоб ви могли вирішити, що показувати); attributeTitleList = список заголовків таблиці, розділений символом «|», щоб можна було локалізувати звіт. |
Expression Manager знає, які змінні є локальними
Щоб правильно побудувати JavaScript для сторінки, Expression Manager має знати, які змінні встановлюються на сторінці та який у них JavaScript ID (наприклад, для document.getElementById(x)). Він також має знати, які змінні встановлюються на інших сторінках (щоб гарантувати наявність і заповненість потрібних полів <input type='hidden' value='x'>).
Каскадні умови
Якщо будь-яка зі змінних нерелевантна, усе рівняння стає нерелевантним (false). Наприклад, у таблиці нижче N/A означає, що одна зі змінних не була релевантною
| Оператор | Приклад | a | b | Результат |
|---|---|---|---|---|
| + (unary) | +a | N/A | false | |
| ! | !a | N/A | false | |
| == (or eq) | a == b | N/A | 5 | false |
| == (or eq) | a == b | N/A | 0 | false |
| == (or eq) | a == b | N/A | N/A | false |
| != (or ne) | a != b | N/A | 5 | false |
| != (or ne) | a != b | N/A | N/A | false |
| != (or ne) | a != b | N/A | 0 | false |
| > (or gt) | a > b | N/A | 5 | false |
| >= (or ge) | a >= b | N/A | 5 | false |
| < (or lt) | a < b | N/A | 5 | false |
| <= (or le) | a <= b | N/A | 5 | false |
| and | a and b | N/A | 5 | false |
| and | a and b | N/A | N/A | false |
| or | a or b | N/A | N/A | false |
| or | a or b | N/A | 5 | false |
| + | a + b | N/A | 5 | false |
| * | a * b | N/A | 5 | false |
| / | a / b | 5 | N/A | false |
| () | (a) | N/A | false | |
| (exp) | (a && b) | N/A | 5 | false |
| (exp) op (exp) | (b + b) > (a && b) | N/A | 5 | false |
| function | sum(a,b,b) | N/A | 5 | false |
| function | max(a,b) | N/A | 5 | false |
| function | min(a,b) | N/A | 5 | false |
| function | implode(', ',a,b,a,b) | N/A | 5 | false |
| function | if(a,a,b) | N/A | 5 | false |
| function | is_empty(a) | N/A | false | |
| function | is_empty(a) | 0 (or blank) | true | |
| function | !is_empty(a) | N/A | false |
Перевизначення каскадних умов
Припустімо, ви хочете показати поточну суму всіх релевантних відповідей. Ви можете спробувати використати рівняння {sum(q1,q2,q3,...,qN)}. Однак внутрішньо воно перетворюється на LEMif(LEManyNA('q1','q2','q3',...,'qN'),,sum(LEMval('q1'),LEMval('q2'),LEMval('q3'),...,LEMval('qN'))). Тому, якщо будь-яке зі значень q1-qN нерелевантне, рівняння завжди повертатиме false. У цьому разі sum() показуватиме 0, доки не буде дано відповіді на всі питання.
Щоб обійти це, до кожної змінної можна додати суфікс «.NAOK» (означає, що Not Applicable — це нормально). У такому разі спрацьовує така поведінка. Припустімо, у вас є змінна q1.NAOK
- q1 не додається до виразу LEManyNA()
- LEMval('q1') і надалі перевірятиме, чи відповідь релевантна, і повертатиме '', якщо ні (тобто окремі нерелевантні відповіді ігноруватимуться, але не зроблять недійсним увесь вираз).
Отже, розв'язання проблеми поточної суми — використати рівняння sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).
Використання суфікса .NAOK також дає змогу авторам створювати опитування з кількома можливими шляхами, які пізніше сходяться на спільних шляхах. Наприклад, припустімо, що респонденти відповідають на опитування так, що це виходить за межі звичайного діапазону відповідей. Автор може попередити респондентів, що вони можуть не отримати достовірних результатів, і запитати, чи справді вони хочуть продовжити опитування. Якщо вони відповідають «Так», решта питань буде показана. Умова для «решти питань» перевірятиме, чи початкові відповіді були в межах звичайного діапазону, АБО чи респондент відповів «Так» на питання, яке релевантне лише тоді, коли відповіді виходили за межі діапазону.
Як Expression Manager підтримує умовне мікроадаптування (micro-tailoring)?
Ось приклад мікроадаптування (де Question Type=='expr' означає рівняння):
| Код питання | Релевантність | Тип питання | Питання |
|---|---|---|---|
| name | 1 | text | What is your name? |
| age | 1 | text | How old are you? |
| badage | !is_empty(age) | expr | {(age<16) or (age>80)} |
| agestop | badage | message | Sorry, {name}, you are too {if( (age<16),'young',if( (age>80),'old','middle-aged') ) } for this test. |
| kids | !badage | yesno | Do you have children? |
| parents | 1 | expr | {!badage && kids=='Y'} |
| numKids | parents | text | How many children do you have? |
| kid1 | parents && numKids >= 1 | text | How old is your first child? |
| kid2 | parents && numKids >= 2 | text | How old is your second child? |
| kid3 | parents && numKids >= 3 | text | How old is your third child? |
| kid4 | parents && numKids >= 4 | text | How old is your fourth child? |
| kid5 | parents && numKids >= 5 | text | How old is your fifth child? |
| sumage | 1 | expr | {sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)} |
| report | parents | yesno | {name}, you said you are {age} and that you have {numKids}. The sum of ages of your first {min(numKids,5)} kids is {sumage} |
Усі ці питання можуть бути на одній сторінці (наприклад, в одній групі), і відображатимуться лише релевантні питання. Більше того, коли ви вводите вік дітей, вираз sum() в останньому питанні динамічно оновлюватиметься на сторінці.
Expression Manager забезпечує цю функціональність, обгортаючи кожен вираз в іменований елемент <span>. Щоразу, коли значення змінюється, він перераховує вираз, який має відображатися в цьому елементі <span>, і заново формує відображення. На одній сторінці може бути десятки або навіть сотні таких адаптованих виразів, і сторінка оновить їх усі за одне перемалювання екрана.
Відповідність функціональності LimeSurvey 1.91+ та Expression Manager
| Стара функція | Нова функція | Коментарі |
|---|---|---|
| Умови | Релевантність | Ви можете використовувати дуже складні умовні рівняння та мати доступ до ширшого діапазону змінних |
| Оцінювання | Рівняння | Будь-які бали оцінювання можна переструктурувати в рівняння. Це гарантує запис балу в базу даних і дає змогу бачити динамічні зміни значення балу на поточній сторінці |
| Заміни | Expression Manager | Основний рушій приймає вхідний рядок і розглядає все в фігурних дужках як вираз, тому він обробляє всі історичні типи замін. Щоб не зіпсувати вбудований JavaScript, Expression Manager обробляє вміст між фігурними дужками лише за умови, що (a) у фігурних дужках немає пробілів на початку чи в кінці — наприклад, {expr} є виразом, але { expr}, {expr } і { expr } не є виразами. Крім того, Expression Manager не обробляє вміст усередині власних рядків (наприклад, {list('hi','there {braces}')} генерує «hi there {braces}»). Він також ігнорує екрановані фігурні дужки (наприклад, \{this is not an expression\}) |
| Перевірка | Expression Manager | План полягає в тому, щоб взяти поточні атрибути питання min/max і обробляти їх за допомогою Expression Manager. Так самі значення min/max можуть бути виразами |
Підсвічування синтаксису
Щоб допомогти у введенні та перевірці виразів, EM пропонує підсвічування синтаксису з такими можливостями:
Типи та значення підсвічування синтаксису
| Колір | Приклад | Значення | Підказка | Коментарі |
|---|---|---|---|---|
| жовтувато-коричневий фон | Sample | усе рівняння | немає | Усе, що розміщено у фігурних дужках і розпізнається як рівняння (тобто немає пробілів на початку чи в кінці), позначається жовтувато-коричневим фоном, щоб відрізнити його від навколишнього тексту |
| жирний червоний текст | Sample | Помилка | Пояснення помилки | Може бути невідома змінна або помилка у функції тощо. Опитування може повністю не працювати, але це не показується публічним користувачам. |
| синій текст | Sample | назва функції | значення та допустимий синтаксис | назви функцій, або те, що має бути функціями, оскільки далі йде відкрита дужка, відображаються жирним синім текстом. Підказки показують значення та допустимий синтаксис функції. |
| сірий текст | Sample | рядок | немає | рядки в одинарних і подвійних лапках відображаються сірим текстом |
| блакитний текст | Sample | змінна, задана на цій самій сторінці, | [ім'я або код SGQA]: питання; значення; список відповідей із кодами для кожного значення | Будь-яка змінна, задана на тій самій сторінці, що й поточне питання, відображається блакитним текстом, що означає, що її можна оновлювати в JavaScript. Підказка показує її ім'я, саме питання та поточне значення (або порожньо, якщо не задано). Якщо тип питання передбачає відповіді з переліку значень, показується відповідність кодів значенням, що відображаються. |
| зелений текст | Sample | змінна, задана на попередній сторінці | [ім'я або код SGQA]: питання; значення; список відповідей із кодами для кожного значення | Будь-яка змінна, задана на попередній сторінці, відображається жирним зеленим текстом. Підказка показує її ім'я, саме питання та поточне значення (або порожньо, якщо не задано). Якщо тип питання передбачає відповіді з переліку значень, показується відповідність кодів значенням, що відображаються. |
| жирний рожевий текст | Sample | змінна, задана на наступній сторінці як правило: порожня на початку опитування, але може бути заповнена через індекс або перехід назад | [ім'я або код SGQA]: питання; значення; список відповідей із кодами для кожного значення | Будь-яка змінна, задана на наступній сторінці, відображається жирним рожевим текстом. Підказка показує її ім'я, саме питання та поточне значення (або порожньо, якщо не задано). Якщо тип питання передбачає відповіді з переліку значень, показується відповідність кодів значенням, що відображаються. |
| жирний коричневий текст | Sample | значення заміни LimeSurvey | значення | Рядки заміни Lime (як-от {TOKEN:xxx}, {PRIVACY_MESSAGE}) відображаються жирним коричневим текстом. |
| червоний текст | Sample | оператор присвоєння (=) | попередження | Якщо ви використовуєте оператор присвоєння (=), він відображається червоним текстом. Це допомагає запобігти випадковому перепризначенню значень, коли ви насправді хотіли перевірити, чи a == b, а не встановити значення a = b. |
| звичайний чорний текст | Sample | розділові знаки | немає | Усі інші розділові знаки у виразі відображаються звичайним чорним текстом. |
| текст у червоній рамці | жирна червона лінія оточує помилку | синтаксична помилка | опис помилки | Будь-які виявлені синтаксичні помилки позначаються червоною рамкою навколо помилки. Підказка показує саму помилку. Приклади: незакриті дужки, використання невизначених функцій, передавання неправильної кількості аргументів у функції, погано структуровані вирази (наприклад, пропущені оператори між змінними), спроба присвоїти нове значення змінній лише для читання, спроба присвоїти значення не змінним або використання синтаксису, що не підтримується. Зауважте, що система виявлення синтаксичних помилок може повідомити лише про одну помилку у виразі, навіть якщо їх кілька; проте, якщо помилки виявлено, буде показано щонайменше одну. |
Додаткові матеріали
Зразки опитувань Expression Manager
Сценарії використання та інструкції
Покрокові приклади
Статистичні функції Expression Manager
Довідник для розробників










