Начисление баллов и ответы на вопросы
Режимы оценивания (всё-или-ничего и частичный), формулы начисления баллов для вопросов с несколькими вариантами и на соответствие, и как корректно передавать ответы по каждому типу вопроса.
Режимы оценивания
У теста есть режим по умолчанию default_scoring_mode, а у каждого вопроса — необязательный scoring_mode, который его перекрывает. Если на вопросе режим не задан (null), применяется режим теста.
| Режим | Как считается | Где доступен |
|---|---|---|
all_or_nothing | Полный балл только за полностью верный ответ, иначе 0. | Все типы вопросов |
partial | Частичный балл — пропорционально верным элементам ответа. | Только multiple и matching |
default_scoring_mode) и переопределяется на вопросе (scoring_mode). Пустая строка "" в scoring_mode сбрасывает переопределение — вопрос снова наследует режим теста. Для single и free_text частичный режим запрещён (проверяется и на сервере, и в БД).Множественный выбор (multiple): частичный режим
В частичном режиме балл за вопрос с несколькими верными вариантами считается так:
балл = вес × max(0, (верных − неверных) / всего_верных)
верных — сколько выбрано верных вариантов
неверных — сколько выбрано неверных вариантов
всего_верных — сколько всего верных вариантов в вопросеКаждый неверный выбор гасит один верный — это штраф за угадывание. Результат не опускается ниже 0. Полный вес начисляется только при точном совпадении: выбраны все верные варианты и ни одного лишнего.
is_correct у ответа становится true только при точном совпадении (полный балл). Частично верный ответ приносит баллы, но is_correct остаётся false — поэтому в аналитике он не считается «решённым».Пример: вопрос на 10 баллов, 3 верных варианта (C1, C2, C3) и 2 неверных (W1, W2).
| Выбор студента | Режим partial | Режим all_or_nothing |
|---|---|---|
| C1 + C2 + C3 (все верные) | 10.00 — верно | 10.00 — верно |
| C1 + C2 (2 из 3 верных) | (2−0)/3 × 10 = 6.67 — неверно | 0.00 — неверно |
| C1 + W1 (1 верный, 1 неверный) | (1−1)/3 × 10 = 0.00 | 0.00 |
| C1 + C2 + W1 + W2 | (2−2)/3 × 10 = 0.00 | 0.00 |
| только W1 | (0−1)/3 → 0.00 (не ниже нуля) | 0.00 |
| ничего не выбрано | 0.00 | 0.00 |
Вопросы на соответствие (matching): частичный режим
Идентифицирующие вопросы (тип matching, «установление соответствия») сопоставляют пункты левого столбца с вариантами правого. В частичном режиме:
балл = вес × верных_пар / всего_пар
верных_пар — сколько пар сопоставлено правильно
всего_пар — число реальных пар (дистракторы не считаются)В отличие от множественного выбора, штрафа за неверную пару нет — балл просто пропорционален числу правильно сопоставленных пар. Строки-дистракторы (есть только правый вариант, без левого) в знаменатель не входят.
all_or_nothing полный балл начисляется, только если верны все реальные пары и ни одна не пропущена. Пример: 2 реальные пары, вес 4 балла, верно сопоставлена 1 → partial даёт 4 × 1/2 = 2.00, а all_or_nothing — 0.00.Как передавать ответы на идентифицирующие вопросы
Ответ на matching-вопрос передаётся в Сохранить ответы как массив пар pairs:
{
"answers": [
{
"question_id": "<id вопроса>",
"payload": {
"pairs": [
{ "left_id": "<id из match_lefts>", "right_id": "<токен из match_rights>" }
]
}
}
]
}Идентификаторы берутся из ответа GET /api/v1/t/quizzes/:id, полученного под ролью студента (студенческое представление вопроса):
left_id— этоidэлемента изmatch_lefts[](реальный идентификатор левого пункта).right_id— этоidэлемента изmatch_rights[]. Правый столбец перемешан, а егоid— это одноразовый токен, а не реальныйmatch.id. Сервер на отправке восстанавливает из токена настоящий идентификатор.
right_id — это токен из match_rights[].id студенческого представления, а НЕ сырой match.id из кураторского ответа (matches[].id в GET /quizzes/:id под куратором). Если прислать сырой id, токен не сопоставится, пара тихо засчитается неверной и студент получит 0 без какой-либо ошибки. Отправляйте пары только для тех left_id, что показаны в match_lefts — дистракторы присутствуют только в правом столбце.curl -X POST https://api.edumentor.kz/api/v1/t/attempts/<attempt_id>/answers \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme" \
-H "Content-Type: application/json" \
-d '{
"answers": [
{
"question_id": "a1b2c3d4-...",
"payload": {
"pairs": [
{ "left_id": "11111111-...", "right_id": "ffffffff-..." },
{ "left_id": "22222222-...", "right_id": "eeeeeeee-..." }
]
}
}
]
}'Для совместимости со старыми клиентами сервер также принимает синонимы ключей: конверт pairs либо matches; внутри пары — left_id/left и right_id/right. Канонична форма pairs + left_id/right_id.
Ответы на остальные типы вопросов
| Тип | payload | Принимаемые синонимы ключа |
|---|---|---|
single | { "selected_answer_id": "<id>" } | selected_option_id, answer_id, answer_ids (берётся первый) |
multiple | { "selected_answer_ids": ["<id>", …] } | selected_option_ids, answer_ids |
free_text | { "text": "..." } | — |
matching | { "pairs": [{ "left_id", "right_id" }] } | matches; left/right |
Идентификаторы вариантов (selected_answer_id, selected_answer_ids) — это id из answers[] студенческого представления вопроса. Сервер декодирует payload по типу вопроса; отправка ответов в уже завершённую попытку даёт 409 attempt_already_submitted.