Skip to documentation

Video Units and Adaptive Logic

Last Updated: 2026-10-09 | For: Teachers, researchers, and developers | Level: Basic playback through advanced adaptive authoring

Overview

For fixed video questions, start with Stimulus Files and Trial Types Reference. Before adding prequiz-dependent video questions, also read Assessment Sessions.

MoFaCTS supports embedding YouTube videos (or local video files) as video units, with the ability to pause the video at specific timestamps and ask questions. The adaptive logic system allows you to dynamically insert or modify video units based on student performance on previous assessments.

Boolean literals in adaptive conditions are case-insensitive: TRUE, True, and true are equivalent, as are the corresponding forms of false. These are rule literals, not TDF settings.

Control conditions must place their videos in tutor.unit in playback order. Merely listing videos in setspec.unitTemplate does not run them; templates require an adaptive directive. Adaptive template insertion still creates the video when no question rules match, so that video plays without questions. If adaptive rewind is enabled, its anchor list must still be valid; see Checkpoint Modes and Rewind Anchors.

Generated adaptive units and selected questions are saved with progress and restored on resume. Missing saved sequence state is reported as a concrete failure rather than skipping to Final; existing attempts are not reset. See Resume and Persistence Behavior.

This page covers:

  • Basic video units (videosession)
  • All video-session fields, defaults, playback restrictions, and known implementation gaps
  • Adaptive unit templates (unitTemplate)
  • Dynamic unit insertion with adaptive logic
  • Template vs. modification modes (t vs f)

Table of Contents

  1. Basic Video Units
  2. Video Session Settings
  3. Shared Unit and Delivery Settings
  4. Unit Templates
  5. Adaptive Logic System
  6. Template Mode (t) vs Modify Mode (f)
  7. Adaptive Logic Syntax
  8. Complete Examples
  9. Owner Updates and Adaptive Continuation
  10. Resume and Persistence Behavior
  11. Operational Validation
  12. Advanced Topics

Worksheet checkpoints

Set videosession.checkpointBehavior to "worksheet" and provide videosession.worksheet.pageIds, one TutorScript page ID per entry in questiontimes. Timestamps must be nonnegative and strictly increasing. Each page owns display.worksheet with workDurationSeconds, reviewDurationSeconds and randomizeQuestions; do not duplicate these fields on the video. The ordinary questions list is not used in this mode.

The video pauses for editable work, then read-only feedback. Each answer/change writes normal model-eligible history without updating the live adaptive model. Work submission/deadline opens feedback after pending writes; review Continue/deadline resumes playback. At a final-timestamp checkpoint, review completes before the normal video-end state, without restarting the video. Participant pause/seek restrictions remain applicable, while worksheet pauses are system actions. No wrong-answer rewind is requested by worksheet completion.

Worksheet phase, absolute deadlines, realized order and answer history resume within learner/lesson/unit/page/checkpoint/course-assignment scope. Completion events, rather than the number of changed answers, determine completed checkpoints. Each actual feedback appearance logs a non-answer exposure. See Timed worksheets for blanks, feedback and history rules. Local schema and pure-controller verification is distinct from HTML5/YouTube browser and persisted-history verification.

Basic Video Units

A video unit plays a video and may include checkpoint questions. A simple video unit with fixed checkpoint questions pauses at predetermined times, so all students see the same questions.

Video units may also include unitinstructions; these display before video playback. If the unit should only show text and continue without video playback, use an instruction-only unit instead of videosession.

Example: Static Video Unit

{
  "unitname": "Carbon Cycle Video",
  "unitinstructions": "Watch the video and answer the questions that appear.",
  "videosession": {
    "videosource": "https://www.youtube.com/watch?v=TitrRpMUt0I",
    "questions": [25, 26, 27, 28],
    "questiontimes": [66, 92, 387, 458]
  },
  "deliverySettings": {
    "drill": 2000000,
    "correctprompt": 2000,
    "reviewstudy": 12000
  }
}

How it works:

  • Video plays from YouTube
  • At 66 seconds (1:06): Video pauses, shows question from cluster 25
  • At 92 seconds (1:32): Shows question from cluster 26
  • At 387 seconds (6:27): Shows question from cluster 27
  • At 458 seconds (7:38): Shows question from cluster 28
  • After the last question, video playback continues. When the video ends, the learner presses Continue to complete the unit, unless a configured elapsed-unit timer advances it earlier.

Video Source Options

YouTube URL:

"videosource": "https://www.youtube.com/watch?v=TitrRpMUt0I"

Local video file:

"videosource": "my-video.mp4"

(File must be uploaded with the TDF package)

Use canonical asset references for local media and validate runtime resolution before assignment.

Empty Questions (Continuous Playback)

To show a video without checkpoint questions:

"videosession": {
  "videosource": "https://www.youtube.com/watch?v=TitrRpMUt0I",
  "questions": [],
  "questiontimes": []
}

questions: [] and questiontimes: [] mean continuous playback with no checkpoint questions. The videosource is still required.

Video Session Settings

These fields belong inside tutor.unit[].videosession or a reusable tutor.setspec.unitTemplate[].videosession. This reference covers all 14 fields declared in the current video-session registry. Boolean playback/replay fields default to false when omitted; use true/false or the existing string forms "true"/"false".

The descriptions below reflect the current application source. They do not establish which revision is deployed or the values saved in a particular lesson.

Source and Question Schedule

Field Default or requirement Current behavior
videosource Required; no playable default YouTube URL or supported HTML5 video URL/file. Local files must be included in the content package and resolve through its media assets.
questions Required; [] is valid Zero-based cluster indices to ask during playback, supplied as an array or a range string. Each scheduled video question currently uses stimulus index 0 of its cluster.
questiontimes Required; [] is valid Video timestamps in seconds, paired by position with questions. The lists must have the same length. Author them in playback order; the player advances through the list in that order. The authoring schema uses integer timestamps.
checkpointBehavior Runtime default none when omitted Selects how rewind anchors are built. Authored modes are pause, adaptive, and none; it does not independently determine whether scheduled questions pause playback.
checkpoints No default list Explicit objects such as { "time": 30 }, measured in seconds. Used as rewind anchors for checkpointBehavior: "adaptive"; matching adaptive rules may append anchors.

For questions: [2, 5] and questiontimes: [30, 60], the player pauses at 30 seconds for cluster 2 and at 60 seconds for cluster 5. Scheduled questions pause playback in every checkpoint mode, including none. Empty lists disable checkpoint questions; checkpointBehavior: "none" does not.

Checkpoint Modes and Rewind Anchors

A question timestamp tells the player when to ask a question. A rewind anchor tells it where to return after an incorrect answer. They need not be the same list.

Authored mode Rewind anchors when rewindOnIncorrect is enabled
pause All scheduled question times. A wrong answer returns to the preceding question timestamp, or the beginning for the first question.
adaptive The explicit checkpoints[].time list. A nonempty valid list is required when automatic rewind is enabled. This name describes anchor selection; prequiz-dependent question insertion is configured separately through top-level adaptive rules.
none No authored anchors. With automatic rewind enabled, a wrong answer returns to the beginning. Scheduled questions still appear and pause playback.

The runtime also accepts all and some, but the current authoring schema permits only the three modes above. all builds the same anchors as pause; some selects question times through a runtime-only checkpointQuestions list (one-based question positions) or stimulus checkpoint flags. checkpointQuestions is not in the video-session authoring registry. These paths are implementation/schema discrepancies, not supported authoring choices.

Participant Playback Restrictions

Set these optional fields inside videosession. Omitted fields default to false; use the existing video Boolean convention (true/false or "true"/"false").

Field Participant behavior System behavior retained
preventPause Removes pause controls, click-to-pause, and pause shortcuts. Initial Play remains available. Instruction and question pauses, explicit runtime pauses, and subsequent playback resume.
preventRewind Rejects backward seeks beyond a 0.1-second rounding tolerance. Forward seeking remains governed by preventScrubbing. rewindOnIncorrect, repeated checkpoint questions, and saved-position restoration.
preventScrubbing Keeps the existing disabled seek bar/shortcuts and blocks forward jumps into unwatched material. Authorized runtime seeks.

Enable all three restrictions to prevent participant pausing and seeking in either direction. Volume and fullscreen controls remain available. The existing fullscreen exit for questions and return on question completion are unchanged.

{
  "unitname": "Restricted Video",
  "videosession": {
    "videosource": "lecture.mp4",
    "questions": [],
    "questiontimes": [],
    "preventPause": "true",
    "preventRewind": "true",
    "preventScrubbing": "true"
  }
}

A participant restriction does not override an instructional action: for example, preventRewind can be combined with rewindOnIncorrect. A unit's restrictions and playback position start fresh on unit entry, including consecutive units using the same video URL.

When preventPause is enabled and playback is expected to continue, an unexpected pause triggers one resume attempt. If the browser rejects playback, the existing Play control remains available once the application permits playback; there is no repeated retry loop. Play cannot bypass instructions or an active question. End-of-video and teardown do not restart playback. Actual pause events remain in video history.

These controls govern the supported HTML5/YouTube player interface, not closing the browser, OS interruptions, or modified browser software. They do not set a question-set time limit or lock playback speed.

Wrong Answers and Replay

Field Default Current behavior
rewindOnIncorrect false A wrong checkpoint answer rewinds to 0.1 seconds after the latest anchor strictly before that question's timestamp. If no preceding anchor exists, playback returns to approximately the beginning. The player also resets its next-question pointer for the replayed interval. Correct answers do not trigger this rewind.

Rewinding resets the question pointer, so scheduled questions in the replayed interval can recur. There is no separate selective-repeat setting. Turning off rewindOnIncorrect stops the automatic replay without changing which questions the prequiz/adaptive rules select.

For a question at 60 seconds with the preceding rewind anchor at 30 seconds, automatic replay starts at approximately 30.1 seconds. preventRewind does not block this system-controlled replay.

This unit explicitly selects those replay boundaries while preventing participant backward seeking:

{
  "unitname": "Video With Wrong-Answer Replay",
  "videosession": {
    "videosource": "lecture.mp4",
    "questions": [2, 5],
    "questiontimes": [30, 60],
    "checkpointBehavior": "adaptive",
    "checkpoints": [{ "time": 0 }, { "time": 30 }],
    "preventRewind": true,
    "rewindOnIncorrect": true
  }
}

Here, adaptive chooses explicit rewind anchors; both questions are fixed and appear for every learner. A wrong answer at 30 seconds replays from approximately 0.1 seconds; a wrong answer at 60 seconds replays from approximately 30.1 seconds. Set rewindOnIncorrect to false to retain the fixed questions without automatic replay.

Declared Fields Without Active Video Behavior

The following are declared in the video-session schema but are not active controls for the dedicated video-unit flow. Their presence in an editor is not evidence that they affect playback.

Field inside videosession Declared purpose Current video-unit behavior
unitMode Selection algorithm The dedicated video engine selects explicit scheduled cluster indices; this field does not switch its playback or question-selection mode.
calculateProbability Probability formula The dedicated video engine performs no model/probability initialization or probability update. This formula does not select its checkpoint questions.
adaptiveLogic Adaptive question rules Nested videosession.adaptiveLogic is not read by the active adaptive transition coordinator. Put working rules on the controlling unit's top-level adaptiveLogic, alongside adaptive.
displayText Supplemental video text No active video rendering consumer. Use top-level unitinstructions for the opening video instruction overlay.

There are no dedicated authored video-session controls for autoplay, playback speed, looping, initial volume, or a fixed start/end segment. Resume position is derived from saved attempt history, rather than an authored start-time field.

Shared Unit and Delivery Settings

Video checkpoint questions are drill trials (d). Answer feedback is controlled by trial type and duration. Drill trials (d) use deliverySettings.correctprompt for correct responses and deliverySettings.reviewstudy for incorrect responses or timeouts; zero skips the applicable feedback phase. Tests (t and button tests h) do not show answer feedback regardless of those durations. Study trials (s) display the answer using purestudy. Separate correct/incorrect feedback visibility switches are not supported. History records leave feedback text and type empty when there is no answer-feedback phase. Playback resumes after the answer history and engine progress are saved. A missing required feedback message still reports a concrete error; a valid zero-duration question can complete without one.

These settings are outside videosession. deliverySettings may supply lesson defaults, unit overrides, or template defaults; see Content Creation Reference Tables for the complete shared settings reference.

Location / field Effect on a video unit
Unit unitinstructions Opening instruction text/HTML. The inline overlay blocks playback until the learner continues; it is not videosession.displayText.
deliverySettings.continueButtonText Label for opening and ending Continue controls. Default Continue.
deliverySettings.displayMinSeconds Default 0. Minimum elapsed unit time before the timed footer's Continue is enabled. It is not a measure of seconds actually watched and does not govern the separate end-of-video Continue button.
deliverySettings.displayMaxSeconds Default 0 disables it. Advances after the configured elapsed unit time, potentially before the video or its questions are finished. Pauses and question/feedback time are not subtracted.
deliverySettings.drill Response timeout in milliseconds for video questions; 0 means no configured timeout.
deliverySettings.correctprompt, deliverySettings.reviewstudy Correct-feedback and incorrect-review durations in milliseconds. These affect question/feedback phases, not video segment duration.
Unit buttontrial, buttonorder, buttonOptions, and shared feedback settings Control the checkpoint question's answer interface, answer order, and feedback presentation. They do not change the playback schedule.
Controlling unit adaptive, adaptiveLogic, adaptiveUnitTemplate Generate or modify later units, including video questions, timestamps, and rewind anchors. See Adaptive Logic System.

instructionminseconds and instructionmaxseconds govern the separate instruction-screen route. The inline video instruction overlay does not currently read them; they should not be described as enforcing a minimum or maximum delay on that overlay.

Elapsed-unit timers can expose a timed Continue before the video ends. Without those timers, the normal video path waits for playback to end and then for the learner to press Continue. Playback restrictions, question timers, elapsed-unit timers, and adaptive question selection are separate controls.


Unit Templates

Unit templates are reusable unit definitions stored in setspec.unitTemplate. They can be dynamically inserted into the learning sequence based on adaptive logic.

Defining Templates

Templates are defined in tutor.setspec.unitTemplate, outside tutor.unit. The examples below are illustrative TDF excerpts: replace placeholder video sources, supply the referenced stimulus clusters, and fill in omitted assessment/settings sections before upload.

{
  "tutor": {
    "setspec": {
      "lessonname": "Adaptive Video Study",
      "stimulusfile": "questions.json",
      "unitTemplate": [
        {
          "unitname": "Video 1: Producers",
          "unitinstructions": "Watch this video about producers.",
          "videosession": {
            "videosource": "https://www.youtube.com/watch?v=VIDEO1",
            "questions": [],
            "questiontimes": []
          },
          "deliverySettings": { ... }
        },
        {
          "unitname": "Video 2: Consumers",
          "unitinstructions": "Watch this video about consumers.",
          "videosession": {
            "videosource": "https://www.youtube.com/watch?v=VIDEO2",
            "questions": [],
            "questiontimes": []
          },
          "deliverySettings": { ... }
        }
      ]
    },
    "unit": [
      { "unitname": "pretest", ... },
      { "unitname": "Final", "countcompletion": true }
    ]
  }
}

Key points:

  • For wholly adaptive question selection, start with empty questions and questiontimes arrays
  • Questions will be added dynamically based on adaptive logic; a template may also contain fixed base questions
  • Templates are indexed: unitTemplate[0], unitTemplate[1], etc.

Adaptive Logic System

The adaptive logic system allows you to insert or modify units after a unit completes, based on student performance.

Core Concepts

When a unit with an adaptive property finishes:

  1. System evaluates the student's performance on previous questions
  2. Applies conditional logic rules (adaptiveLogic)
  3. Either:
    • Creates new units from templates (mode t)
    • Modifies existing units (mode f)
  4. Updates canonical experiment control state for the new unit sequence
  5. Moves to the next unit in the sequence

Required Properties

To enable adaptive logic, a unit needs three properties:

{
  "unitname": "pretest",
  "adaptive": ["2,t", "3,t"],
  "adaptiveUnitTemplate": [0, 1],
  "adaptiveLogic": {
    "2": [ /* rules for position 2 */ ],
    "3": [ /* rules for position 3 */ ]
  }
}

1. adaptive (array of strings)

Specifies where and how to insert/modify units.

Format: "position,mode"

  • position (number): The final position number in the unit sequence
  • mode (letter): t = template, f = modify existing

Example:

"adaptive": ["2,t", "3,t"]

Means: "After this unit finishes, insert template-based units at positions 2 and 3"

2. adaptiveUnitTemplate (array of numbers)

Maps which template to use for each adaptive entry.

Example:

"adaptiveUnitTemplate": [0, 1]

Means:

  • First adaptive entry ("2,t") uses unitTemplate[0]
  • Second adaptive entry ("3,t") uses unitTemplate[1]

3. adaptiveLogic (object)

Defines the conditional rules for when to add questions during videos.

Rules are parsed as data, not JavaScript. Conditions may contain C<cluster>S<stimulus> outcome references, NOT, AND, OR, parentheses, Boolean literals, and explicit numeric comparisons/arithmetic. Actions are typed C<cluster>S<stimulus> references with an optional non-negative AT time and optional CHECKPOINT; no action text is executed. Each rule is limited to 4 KiB, 256 syntax nodes, depth 32, and 256 scheduled actions. Malformed tokens or trailing input fail validation.

Example:

"adaptiveLogic": {
  "2": [
    "IF NOT C0S0 THEN C8S0 AT 66",
    "IF NOT C1S0 THEN C9S0 AT 132"
  ],
  "3": [
    "IF NOT C2S0 THEN C10S0 AT 87"
  ]
}

Keys ("2", "3") correspond to position numbers in the adaptive array.


Template Mode (t) vs Modify Mode (f)

The mode flag determines whether to create a new unit or modify an existing one.

Template Mode: "2,t"

Creates a NEW unit from a template and inserts it.

Starting state:

unit[0] = pretest
unit[1] = Final

After processing "2,t":

unit[0] = pretest
unit[1] = video (from template[0])  INSERTED
unit[2] = Final

Use case: When you want to dynamically add video units based on performance.

Modify Mode: "2,f"

Modifies an EXISTING unit that's already in the unit array.

Starting state:

unit[0] = pretest
unit[1] = video (with hardcoded questions)
unit[2] = Final

After processing "2,f":

unit[0] = pretest
unit[1] = video (with hardcoded + adaptive questions)  MODIFIED
unit[2] = Final

Use case: When you have a pre-existing video unit with hardcoded questions, and you want to add MORE questions based on student performance.

Comparison Example

Control Condition (Static):

{
  "unit": [
    { "unitname": "pretest", ... },
    {
      "unitname": "video",
      "videosession": {
        "videosource": "...",
        "questions": [25, 26, 27],      // Everyone sees these
        "questiontimes": [66, 92, 387]
      }
    },
    { "unitname": "Final", ... }
  ]
}

Experimental Condition (Adaptive with Templates):

{
  "setspec": {
    "unitTemplate": [
      {
        "unitname": "video",
        "videosession": {
          "videosource": "...",
          "questions": [],               // Start empty
          "questiontimes": []
        }
      }
    ]
  },
  "unit": [
    {
      "unitname": "pretest",
      "adaptive": ["2,t"],               // Insert template
      "adaptiveUnitTemplate": [0],
      "adaptiveLogic": {
        "2": [
          "IF NOT C0S0 THEN C25S0 AT 66",
          "IF NOT C1S0 THEN C26S0 AT 92"
        ]
      }
    },
    { "unitname": "Final", ... }
  ]
}

Adaptive Logic Syntax

Adaptive logic rules determine which questions to insert and when.

Rule Format

IF <condition> THEN <action> AT <timestamp>

Components:

  • IF: Keyword starting the condition
  • condition: Boolean expression testing student performance
  • THEN: Keyword separating condition from action
  • action: Which question to insert (cluster and stimulus)
  • AT: Keyword before timestamp
  • timestamp: When to pause the video (in seconds)

Condition Syntax

Cluster/Stimulus Notation:

  • C5S0 = Cluster 5, Stimulus 0
    • C = Cluster
    • 5 = Cluster index (0-based)
    • S = Stimulus
    • 0 = Stimulus index within cluster (usually 0 for single-question clusters)

Operators:

  • NOT CxSy = Student got this question WRONG
  • OR = Logical OR (at least one condition is true)
  • AND = Logical AND (all conditions must be true; write the operator explicitly)

Examples:

NOT C5S0               Student got cluster 5 wrong
NOT C2S0 OR NOT C4S0   Student got cluster 2 OR cluster 4 wrong (or both)

Action Syntax

Format: CxSy

  • Specifies which question cluster to insert

Example: C8S0 = Insert question from cluster 8, stimulus 0. The current video schedule stores cluster indices and the video engine selects stimulus 0; use S0 for video actions. A different stimulus index in an outcome condition can refer to a pretest result, but is not carried into the generated video question.

CHECKPOINT Actions

Add CHECKPOINT to an action to record its timestamp as a rewind anchor, for example:

IF NOT C5S0 THEN CHECKPOINT C8S0 AT 174

With checkpointBehavior: "adaptive", matching rules add these anchors to videosession.checkpoints. An anchor at the current question time does not become its own replay start: a wrong answer returns to the preceding anchor. If rewindOnIncorrect is enabled, provide at least one valid anchor through the template or matching rules; no matching CHECKPOINT rules with an empty list causes initialization to fail.

Timestamp

Format: Number of seconds into the video

Examples:

  • 66 = Pause at 1:06
  • 132 = Pause at 2:12
  • 387 = Pause at 6:27

Complete Rule Examples

Example 1: Simple condition

"IF NOT C5S0 THEN C8S0 AT 174"

Translation: If the student got question 5 (about "Producers") wrong on the pretest, pause the video at 2:54 (174 seconds) and ask remedial question 8.

Example 2: OR condition

"IF NOT C2S0 OR NOT C4S0 THEN C9S0 AT 215"

Translation: If the student got question 2 (Photosynthesis) OR question 4 (Carbon Cycle) wrong (or both), pause the video at 3:35 and ask question 9.

Example 3: Multiple concepts

"IF NOT C2S0 OR NOT C3S0 OR NOT C4S0 THEN C14S0 AT 87"

Translation: If the student missed any of questions 2, 3, or 4, pause at 1:27 and ask question 14.

Example 4: Always insert

"IF TRUE THEN C25S0 AT 66"

Translation: Always pause at 1:06 and ask question 25 (regardless of pretest performance).


Complete Examples

Example 1: Adaptive Video Experiment

Scenario: Students take a pretest, then watch 2 videos with adaptive questions based on their pretest performance.

TDF Structure:

{
  "tutor": {
    "setspec": {
      "lessonname": "Carbon Cycle Study",
      "stimulusfile": "carbon_questions.json",
      "unitTemplate": [
        {
          "unitname": "Video 1: Matter and Energy",
          "unitinstructions": "Watch the video. Answer questions that appear.",
          "videosession": {
            "videosource": "https://www.youtube.com/watch?v=TitrRpMUt0I",
            "questions": [],
            "questiontimes": []
          },
          "deliverySettings": {
            "drill": 2000000,
            "correctprompt": 2000,
            "reviewstudy": 12000
          }
        },
        {
          "unitname": "Video 2: Carbon Cycle",
          "unitinstructions": "Watch the second video. Answer questions that appear.",
          "videosession": {
            "videosource": "https://www.youtube.com/watch?v=_dYkByQ9Kmg",
            "questions": [],
            "questiontimes": []
          },
          "deliverySettings": {
            "drill": 2000000,
            "correctprompt": 2000,
            "reviewstudy": 12000
          }
        }
      ]
    },
    "unit": [
      {
        "unitname": "pretest",
        "unitinstructions": "Answer the following questions about the Carbon Cycle.",
        "adaptive": ["2,t", "3,t"],
        "adaptiveUnitTemplate": [0, 1],
        "buttontrial": "true",
        "assessmentsession": {
          "randomizegroups": "false",
          "clusterlist": "0-7",
          "permutefinalresult": "0-0",
          "assignrandomclusters": "false",
          "conditiontemplatesbygroup": {
            "groupnames": "A",
            "clustersrepeated": "1",
            "templatesrepeated": "8",
            "group": ["0,f,t,0 0,f,t,0 0,f,t,0 0,f,t,0 0,f,t,0 0,f,t,0 0,f,t,0 0,f,t,0"],
            "initialpositions": "A_1 A_2 A_3 A_4 A_5 A_6 A_7 A_8"
          }
        },
        "adaptiveLogic": {
          "2": [
            "IF NOT C5S0 THEN C8S0 AT 174",
            "IF NOT C2S0 OR NOT C4S0 THEN C9S0 AT 215",
            "IF NOT C6S0 THEN C10S0 AT 308",
            "IF NOT C3S0 THEN C13S0 AT 568"
          ],
          "3": [
            "IF NOT C0S0 THEN C15S0 AT 132",
            "IF NOT C1S0 THEN C16S0 AT 166",
            "IF NOT C4S0 THEN C19S0 AT 373"
          ]
        },
        "deliverySettings": {
          "drill": 2000000,
          "correctprompt": 2000,
          "reviewstudy": 2000
        }
      },
      {
        "unitname": "Final",
        "unitinstructions": "<h3>Thanks!</h3><p>Your answers have been submitted.</p>",
        "countcompletion": true
      }
    ]
  }
}

What Happens:

  1. Student takes pretest (questions C0-C7)
  2. System evaluates performance:
    • Student got C5 (Producer) wrong
    • Student got C2 (Photosynthesis) correct
    • Student got C4 (Carbon Cycle) wrong
  3. System builds Video 1 unit:
    • Takes unitTemplate[0]
    • Evaluates logic for position "2":
      • IF NOT C5S0 THEN C8S0 AT 174 TRUE (got C5 wrong) Add C8 at 174s
      • IF NOT C2S0 OR NOT C4S0 THEN C9S0 AT 215 TRUE (got C4 wrong) Add C9 at 215s
      • IF NOT C6S0 THEN C10S0 AT 308 FALSE (got C6 correct) Skip
    • Inserts video at position 2 with questions [C8, C9] at times [174s, 215s]
  4. System builds Video 2 unit (similar process for position "3")
  5. Final sequence:
    • Unit 0: Pretest
    • Unit 1: Video 1 (with adaptive questions)
    • Unit 2: Video 2 (with adaptive questions)
    • Unit 3: Final

Example 2: Decoding Adaptive Logic

Pretest Questions (Clusters 0-7):

  • C0S0: "What is Carbon?"
  • C1S0: "What is Carbon Dioxide?"
  • C2S0: "What is Photosynthesis?"
  • C3S0: "What is Cellular Respiration?"
  • C4S0: "What is the Carbon Cycle?"
  • C5S0: "What is a Producer?"
  • C6S0: "What is a Consumer?"
  • C7S0: "What is a Decomposer?"

Adaptive Logic for Video 1:

"2": [
  "IF NOT C5S0 THEN C8S0 AT 174",
  "IF NOT C2S0 OR NOT C4S0 THEN C9S0 AT 215",
  "IF NOT C6S0 THEN C10S0 AT 308",
  "IF NOT C4S0 OR NOT C6S0 THEN C11S0 AT 367",
  "IF NOT C4S0 OR NOT C7S0 THEN C12S0 AT 441",
  "IF NOT C3S0 THEN C13S0 AT 568"
]

Line-by-line translation:

Rule Translation
IF NOT C5S0 THEN C8S0 AT 174 If student missed "Producer" pause at 2:54, ask Q8
IF NOT C2S0 OR NOT C4S0 THEN C9S0 AT 215 If student missed "Photosynthesis" OR "Carbon Cycle" pause at 3:35, ask Q9
IF NOT C6S0 THEN C10S0 AT 308 If student missed "Consumer" pause at 5:08, ask Q10
IF NOT C4S0 OR NOT C6S0 THEN C11S0 AT 367 If student missed "Carbon Cycle" OR "Consumer" pause at 6:07, ask Q11
IF NOT C4S0 OR NOT C7S0 THEN C12S0 AT 441 If student missed "Carbon Cycle" OR "Decomposer" pause at 7:21, ask Q12
IF NOT C3S0 THEN C13S0 AT 568 If student missed "Cellular Respiration" pause at 9:28, ask Q13

Example Student Path:

Student gets C2, C4, and C6 wrong on pretest.

Video 1 will have:

  • At 2:54 (174s): No question (got C5 correct)
  • At 3:35 (215s): Q9 (got C4 wrong)
  • At 5:08 (308s): Q10 (got C6 wrong)
  • At 6:07 (367s): Q11 (got C4 AND C6 wrong)
  • At 7:21 (441s): Q12 (got C4 wrong)
  • At 9:28 (568s): No question (got C3 correct)

Total: 4 adaptive questions during the video.


Owner Updates and Adaptive Continuation

Structural update warnings belong to authoring: reducing clusters/questions (including a reduction within an existing cluster position), or changing the exact ordered authored unitname list, requires owner review. Owners may cancel or proceed after the warning that existing attempts may be disrupted. Runtime insertion of adaptive videos never enters that comparison. See Updating content for criteria and limitations.

Lesson launch, refresh and resume reuse the saved adaptiveUnitSequence, including generated videos and selected questions, rather than reevaluating an already completed pretest branch. The current authored template or adaptive rules do not replace a frozen sequence. Old stored mapping signatures are unused; a structurally valid saved permutation remains valid after shuffle/swap settings change.

Saved positions are retained after an owner-approved update. If a saved unit/question no longer exists, the mapping is missing or invalid, or the adaptive sequence is absent, malformed or belongs to another lesson, the runtime reports that concrete failure. It does not silently choose another unit, regenerate progressed mappings, reset an attempt or delete history.

Resume and Persistence Behavior

Video sessions now follow the same history-first rule as other unit types.

  • Committed checkpoint-question history is the canonical record of video question progress.
  • Resume position is derived from committed checkpoint-question count plus the checkpoint order and times in the active saved unit sequence. Both correct and incorrect ATTEMPT outcomes count as answered checkpoints; an incorrect response does not become unanswered after refresh.
  • With at least one committed checkpoint answer, playback resumes 0.1 seconds after the corresponding checkpoint time and the next checkpoint index comes from that count.
  • Ordinary checkpoint-question display state is not persisted after each question.
  • Displaying a question without answering it adds no committed answer. After reload, playback starts from the preceding committed checkpoint and reaches that unanswered question again; if no answers have been committed, playback starts at the beginning.
  • An empty-question video has no question-derived resume anchor. This contract does not save the continuously watched position every second.

Operational Validation

Video activity records describe the playing media: eventType and levelUnitType are video, and displayedStimulus is the playing source URL. This identity is independent of the checkpoint question display and its trial type, including during startup and resume. The ordinary TSV export includes video activity and its position, seek, speed, volume, and playing-state columns. Run pure identity/wire/export regressions from mofacts/ with node --test scripts/videoHistory.test.cjs. These checks do not establish that a deployed browser has committed events through DDP into the database.

Use synthetic content and attempts for acceptance checks.

  1. Run both empty-question playback and a static schedule; verify question indices/times, feedback, end-of-video Continue, and no blank transitions.
  2. Check participant pause/forward-seek/backward-seek restrictions independently and together on the selected provider. Initial Play, instructions, system question pauses, volume, and fullscreen must still work.
  3. Compare wrong answers with rewindOnIncorrect off/on; inspect the actual preceding anchor and repeated question order. Correct answers must not rewind.
  4. Verify pretest → generated videos → final sequence, including a no-matching-question branch, expected insertion positions, refresh, and resume. With adaptive rewind enabled, verify the resulting nonempty anchor list.
  5. Check elapsed-unit timers separately from watched-video duration and instruction-overlay timing.
  6. Confirm the lesson package and deployed application revision separately; source behavior is not proof of production behavior.

Advanced Topics

Position Numbering

Why do these examples insert at position "2"?

Initial unit array:

unit[0] = pretest (current unit)
unit[1] = Final

We want the final sequence to be:

Position 1 (unit[0]): pretest
Position 2 (unit[1]): video1   First insertion
Position 3 (unit[2]): video2   Second insertion
Position 4 (unit[3]): Final

The position numbers in adaptive are one-based target positions at the time each directive is applied. The code converts this to array indices using splice(position - 1, 0, unit).

Processing "2,t":

  • newUnitIndex = "2"
  • splice(2 - 1, 0, video1) = splice(1, 0, video1)
  • Inserts at index 1
  • Result: [pretest, video1, Final]

Processing "3,t":

  • newUnitIndex = "3"
  • splice(3 - 1, 0, video2) = splice(2, 0, video2)
  • Inserts at index 2
  • Result: [pretest, video1, video2, Final]

Multiple Adaptive Units

Can multiple units have adaptive properties?

Yes! Each unit can have its own adaptive logic that triggers when that unit completes.

Example:

{
  "unit": [
    {
      "unitname": "pretest",
      "adaptive": ["2,t", "3,t"],  // Inserts 2 videos after pretest
      "adaptiveUnitTemplate": [0, 1],
      "adaptiveLogic": { ... }
    },
    // After pretest: [pretest, video1, video2, Final]

    {
      "unitname": "midtest",
      "adaptive": ["5,t"],  // Could insert another unit after midtest
      "adaptiveUnitTemplate": [2],
      "adaptiveLogic": { ... }
    },
    // After midtest: [pretest, video1, video2, midtest, video3, Final]

    { "unitname": "Final", "countcompletion": true }
  ]
}

Important: Position numbers must account for previously inserted units! If pretest inserts units at positions 2 and 3, and you want to insert after the midtest (which is now at array index 3 (one-based position 4)), you need to calculate the new position carefully.

Best Practice: Keep it simple - usually only the first unit (pretest/diagnostic) has adaptive logic. Having multiple units with adaptive insertion can become difficult to manage.

Timing Best Practices

When choosing question timestamps:

  1. Match video content: Pause when the video is explaining the concept being tested
  2. After explanation: Pause after the explanation, not during
  3. Natural breaks: Choose moments when the speaker pauses or finishes a sentence
  4. Spacing: Don't cluster questions too close together (give 20-30 seconds between)

Example:

Video timeline:
0:00-1:45  Introduction to producers
1:46-2:54  Explanation of photosynthesis  Good time for producer question
2:55-4:20  Discussion of consumers
4:21-5:15  Examples of food chains  Good time for consumer question

Corresponding logic:

[
  "IF NOT C5S0 THEN C8S0 AT 174",   // At 2:54, after producer explanation
  "IF NOT C6S0 THEN C10S0 AT 315"   // At 5:15, after consumer explanation
]

Debugging Adaptive Logic

Inspect playback and adaptive-transition diagnostics using the deployment's configured client verbosity. Validate the authored fields and the generated unit/question schedule before interpreting logs; do not paste learner identifiers or raw history into shared diagnostic reports.

Common issues:

  1. Video doesn't insert: Check that adaptive uses strings ("2,t"), not numbers (2)
  2. Wrong questions appear: Verify cluster indices in adaptiveLogic match your stimulus file
  3. Questions at wrong time: Check timestamp values (they're in seconds, not minutes)
  4. Logic doesn't trigger: Ensure adaptiveLogic keys ("2", "3") match position numbers in adaptive

Summary

Key Takeaways:

  1. Basic videos use videosession with hardcoded questions/times
  2. Adaptive videos use unitTemplate + adaptive + adaptiveLogic
  3. Mode t creates new units from templates (most common)
  4. Mode f modifies existing units (less common)
  5. Adaptive logic syntax: IF <condition> THEN <action> AT <timestamp>
  6. C5S0 means Cluster 5, Stimulus 0 (first question in cluster 5)
  7. Target positions are one-based; these examples use position 2 to insert immediately after the pretest at array index 0.

When to use each approach:

Scenario Approach
All students see same video with same questions Static videosession unit
Students see different questions based on performance Adaptive with templates (t mode)
Everyone sees base questions + some get extra questions Adaptive with modify (f mode)
Control condition (no adaptation) Static videosession units in tutor.unit

See Also