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

LMS quiz storage

Сборка skin: cd wp2lms-turbo-blocks-mos && npm run build (не wp2lms-turbo-pulse / не корневой build:core).

Pulse банк и проверочные вопросы пишут в те же ключи, что Elementor-виджеты wp2lms-pro:

Store widgetId Когда
quiz wp2Id банка init / ответ / finish / reset
questions wp2Id вопроса submit любого типа вопроса

Типы вопросов: choice, open, sort, match, classify.

Хранение через нативные globals wp2lms-pro:

  • getCourseControllerData(dataId, pageId) → getData / setData
  • addQuizScore / updateQuizScore
  • pageId из wp2lmsProConfig.pageId (fallback elearningConfig.pageId)

В курсе (isCourse()) данные уходят в parent.courseController.data; вне курса — в localStorage['quiz'|'questions'] в форме { [pageId]: { [widgetId]: state } }.

События: quiz:passed (finish), quiz:reset (retry / «Начать сначала»). Pulse-события question-bank:continue|close без изменений (consumers — pro / course UI).

Общий каркас (Elementor-совместимый):

{
isQuestionCompleted: true,
attemptsLeft: 0,
attemptStatus: 0,
nextButtonClicked: false, // true после клика «Далее» в банке
answers: [], // choice: 1-based индексы; иначе []
points: 0 | 1,
showCorrectAnswersButton: false,
}

Расширения (не ломают Elementor readers):

Тип Поля
open answer, answerType (text | number)
sort order: string[] (id элементов в ответе пользователя)
match matchAnswers: { [promptId]: answerId }
classify placement: { [itemId]: categoryId | null }

Scene / page.progress банк не трогает (намеренно).

scorePercent считается через Math.ceil (как Elementor / buildQuizState), и в UI банка, и в LMS store.

Состояние LMS showStart После hydrate
finished любой экран results
mid (receivedAnswersCounter > 0) on start («В процессе», «Продолжить» + «Начать сначала»); continue без wipe, restart = wipe + новый порядок + сразу quiz
mid off сразу quiz
пусто on/off start или quiz по showStart

Retry на results → wipe LMS + новая попытка. Start при уже finished no-op (restart только через Retry). На старте mid-quiz «Начать сначала» сбрасывает прогресс без подтверждения и открывает первый вопрос.

Persist только для стабильных wp2Id (isStableLmsId). Ephemeral fallback q-{index} — только UI, в LMS не пишется.

selectedOptionWp2Ids остаётся в Alpine resultPayload / событиях банка; в questions store не сериализуется (чтобы не ломать Elementor readers).

Wp2lmsProFrontendAssets всегда подключает wp2lmsProConfig + pro functions.min.js на static (до skin Alpine). Tripetto переиспользует тот же resolver.

  • Core headless: wp2lms-turbo/assets/src/assessment/ (lms-quiz.js, compare-*, registry)
  • Blocks adapters: assets/src/frontend/question-bank.js — hydrate / score / events; слушает choice|open|sort|match|classify-question:answered|next
  • question-choice.js / question-open.js / question-sort.js / question-match.js / question-classify.js — persist вопроса

Ассеты:

  • Blocks assets/build/turbo.js — подключается Core только при requiresAlpine на странице
  • Core wp2lms-turbo/assets/build/sortable.js — только если компоненты декларируют frontendScripts: ["sortable"] (Sort/Classify)

Open / sort / match / classify допускаются внутри банка (editor + transformer).

Новый тип вопроса + банк: AI_ASSESSMENT_BLOCKS.md.

  • Legacy prompt-блоки (choice-question-prompt / open-question-prompt) — migrate shims, inserter: false.
  • inQuestionBankFlag — Gutenberg providesContext plumbing.
  • bankQuestionNumber — только editor (List View / заголовок).
Окно терминала
# unit (mock LMS)
npm test --prefix wp2lms-turbo-pulse
# e2e (нужен предварительный build:core + build skin + browsers)
npm run build:core
npm run build --prefix wp2lms-turbo-blocks
npx playwright install chromium --with-deps # один раз
npm run test:e2e --prefix wp2lms-turbo-pulse

E2E поднимает fixture tests/e2e/fixtures/quiz-lms.html (генератор копирует Core sortable.js + Blocks turbo.js) и проверяет:

  • localStorage → reload hydrate → reset (retry)
  • mid-quiz «Начать сначала» со стартового экрана
  • persist расширений sort (order) / match (matchAnswers) / classify (placement)
  • nextButtonClicked после «Далее»