All documentation

Adaptive Difficulty Tests

Tests that calibrate themselves to the student — harder questions for students doing well, easier ones for students struggling.

Students · Tutors5 min read
Why adaptive
Fixed-difficulty tests waste questions on either end. A weaker student fails the hard ones; a stronger student breezes through the easy ones. Adaptive tests stay near the student's actual ability — every question carries information.

Overview

An adaptive test runs the same underlying questions but pulls them in an order driven by the student's performance. Implementation is deliberately simple — a 3-up/1-down heuristic that mirrors real Item Response Theory (IRT) but doesn't require difficulty calibration data.

The 3-up / 1-down rule

The current difficulty starts at MEDIUM. After each answer:

  • 3 correct in a row → step up one difficulty level (MEDIUM → HARD; HARD stays HARD).
  • 1 wrong → step down one level (MEDIUM → EASY; EASY stays EASY).
  • Otherwise → stay at the current difficulty.

Difficulty levels are exactly three: EASY, MEDIUM, HARD. Questions are tagged with either a bloomLevel or a difficulty field; the picker matches whichever is set.

Enabling adaptive mode

  1. Open Tutor dashboard → Tests → Edit on any test.
  2. Toggle Adaptive mode on.
  3. Save. The test stays the same to students until they start an attempt; from then on, the next-question endpoint picks adaptively.
Diagnostics are always adaptive
The platform's diagnostic test uses the same engine but at a richer scale. See Diagnostic Test for that flow.

Question pool requirements

For adaptive routing to work the test should have:

  • At least 6-8 questions per difficulty level (EASY / MEDIUM / HARD).
  • Each question tagged with either a bloomLevel (REMEMBER, UNDERSTAND, APPLY, ANALYZE, EVALUATE, CREATE) or a difficulty (EASY / MEDIUM / HARD). Most picker logic treats EASY ≈ REMEMBER/UNDERSTAND, MEDIUM ≈ APPLY/ANALYZE, HARD ≈ EVALUATE/CREATE.

If the pool runs out of questions at the target difficulty, the runner falls back to any unanswered question.

Adaptive state tracking

The runner keeps an adaptiveState JSON on the test attempt:

{
  "currentDifficulty": "MEDIUM",
  "streakCorrect": 0,
  "streakWrong": 0
}

The streaks reset to 0 whenever the difficulty changes. The state is persisted with each answer so refreshes don't lose place.

How a test ends

An adaptive test attempt ends when:

  • All questions in the test have been answered (the pool is exhausted), OR
  • The student clicks Submit, OR
  • The test's timer expires.

Unlike the diagnostic engine, regular adaptive tests don't stop early — they're full-length tests that just sequence questions intelligently.

When to use it

  • Diagnostic-style placement tests — quick read on where a new student is.
  • Topic mastery checks — students who already know the basics skip past easy items.
  • Practice tests with high heterogeneity — a single batch with very mixed ability levels.

Don't use adaptive mode for high-stakes exams where every student must answer the same questions for fairness — keep those as fixed tests.


Header Logo