Timing Fields
When submitting answers, accurate timing data is critical for the learning algorithm to function correctly. The API uses this data to determine spaced repetition intervals, assess fluency progress, and calculate XP rewards.
Required Fields
timeTookToAnswerMs
Time in milliseconds for this specific question.
How to track it:
- Start timing when question is displayed
- Stop timing when user submits answer
- Include think time and interaction time for this question only
Example:
const questionStartTime = Date.now();
// ... show question, wait for user answer
const timeTookMs = Date.now() - questionStartTime;
activeSessionDurationSec
Total active play time in seconds since session started.
How to track it:
- Only count active learning time (when user is answering questions)
- Exclude: menu navigation, pauses, game-over screens, loading times, etc.
- Track using a game timer that pauses during non-learning activities
Example:
let activeSessionTime = 0; // seconds
function onQuestionDisplayed() {
const questionStartTime = Date.now();
// ... wait for user answer
const questionDurationMs = Date.now() - questionStartTime;
activeSessionTime += questionDurationMs / 1000; // Add to total
}
Full Example
const sessionId = crypto.randomUUID();
let activeSessionTime = 0;
async function askQuestion() {
const questionStartTime = Date.now();
// Get question
const questionRes = await fetch(`${API_URL}/learning/v1/skills/${skillId}/algorithms/practice/questions`, {
method: 'POST',
headers: { Authorization: `Bearer ${idToken}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionId }),
});
const { question } = await questionRes.json();
// Show question and wait for answer
const selectedChoiceId = await getUserAnswer(question);
// Calculate timing
const timeTookMs = Date.now() - questionStartTime;
activeSessionTime += timeTookMs / 1000;
// Submit answer with timing
const answerRes = await fetch(
`${API_URL}/learning/v1/skills/${skillId}/algorithms/practice/questions/${question.id}/answers`,
{
method: 'POST',
headers: { Authorization: `Bearer ${idToken}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId,
answer: { choiceId: selectedChoiceId },
timeTookToAnswerMs: timeTookMs,
state: 'Answered',
activeSessionDurationSec: activeSessionTime,
capabilities: { intervention: false },
}),
},
);
}
Common Mistakes
Including pause time in active session duration:
// ❌ Bad: Counts everything
const activeTime = Date.now() - sessionStart;
// ✅ Good: Only counts learning time
let activeTime = 0;
onQuestionShow(() => startTimer());
onPause(() => stopTimer());
Using fixed timing instead of actual measurements:
// ❌ Bad: Fake timing
const timeTookMs = 3000; // Breaks algorithm
// ✅ Good: Real timing
const start = Date.now();
const timeTookMs = Date.now() - start;
Related Docs
Getting Started
Authentication and basic learning loop showing where timing fields fit into answer submission.
Complete Example
Production code demonstrating proper timing tracking with pause/resume handling and state persistence.
API Reference
Complete schema documentation for the answer submission endpoint, including timing field requirements and validation rules.
