Overview
Interactive programming tutorials guide students through learning by executing code at each step. The system validates solutions, provides hints, tracks progress, and ensures students understand concepts before moving forward.Prerequisites
- HopX API key (Get one here)
- Python 3.8+ or Node.js 16+
- Understanding of educational content structure
- Basic knowledge of progress tracking
Architecture
┌──────────────┐
│ Student │ Submits code
└──────┬───────┘
│
▼
┌─────────────────┐
│ Tutorial │ Validate, provide hints
│ Engine │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Execute & validate
└─────────────────┘
Implementation
Step 1: Tutorial Step Execution
Execute and validate tutorial steps:from hopx_ai import Sandbox
import os
from typing import Dict, List, Any
class TutorialStep:
def __init__(self, step_id: str, instructions: str, solution: str, hints: List[str]):
self.step_id = step_id
self.instructions = instructions
self.solution = solution
self.hints = hints
class InteractiveTutorial:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
self.current_step = 0
self.steps = []
def initialize(self):
"""Initialize tutorial session"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=3600
)
def add_step(self, step: TutorialStep):
"""Add tutorial step"""
self.steps.append(step)
def validate_step(self, step_index: int, student_code: str) -> Dict[str, Any]:
"""Validate student code for a step"""
step = self.steps[step_index]
# Execute student code
result = self.sandbox.run_code(student_code, timeout=10)
# Check if solution matches
solution_result = self.sandbox.run_code(step.solution, timeout=10)
# Compare outputs
student_output = result.stdout.strip() if result.success else ""
solution_output = solution_result.stdout.strip() if solution_result.success else ""
passed = student_output == solution_output and result.success
return {
"passed": passed,
"student_output": student_output,
"expected_output": solution_output,
"hint": step.hints[0] if not passed and step.hints else None,
"success": result.success
}
def get_next_hint(self, step_index: int, hint_index: int) -> str:
"""Get hint for current step"""
step = self.steps[step_index]
if hint_index < len(step.hints):
return step.hints[hint_index]
return "No more hints available"
def cleanup(self):
"""Clean up tutorial session"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
tutorial = InteractiveTutorial(api_key=os.getenv("HOPX_API_KEY"))
tutorial.initialize()
# Add steps
tutorial.add_step(TutorialStep(
step_id="step_1",
instructions="Print 'Hello, World!'",
solution="print('Hello, World!')",
hints=["Use the print() function", "Remember to use quotes around the text"]
))
# Validate student code
result = tutorial.validate_step(0, "print('Hello, World!')")
print(f"Passed: {result['passed']}")
tutorial.cleanup()
import { Sandbox } from '@hopx-ai/sdk';
class TutorialStep {
constructor(stepId, instructions, solution, hints) {
this.stepId = stepId;
this.instructions = instructions;
this.solution = solution;
this.hints = hints;
}
}
class InteractiveTutorial {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
this.currentStep = 0;
this.steps = [];
}
async initialize() {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 3600
});
}
addStep(step) {
this.steps.push(step);
}
async validateStep(stepIndex, studentCode) {
const step = this.steps[stepIndex];
// Execute student code
const result = await this.sandbox.runCode(studentCode, { timeout: 10 });
// Check if solution matches
const solutionResult = await this.sandbox.runCode(step.solution, { timeout: 10 });
// Compare outputs
const studentOutput = result.success ? result.stdout.trim() : '';
const solutionOutput = solutionResult.success ? solutionResult.stdout.trim() : '';
const passed = studentOutput === solutionOutput && result.success;
return {
passed,
studentOutput,
expectedOutput: solutionOutput,
hint: !passed && step.hints.length > 0 ? step.hints[0] : null,
success: result.success
};
}
getNextHint(stepIndex, hintIndex) {
const step = this.steps[stepIndex];
if (hintIndex < step.hints.length) {
return step.hints[hintIndex];
}
return 'No more hints available';
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const tutorial = new InteractiveTutorial(process.env.HOPX_API_KEY);
await tutorial.initialize();
// Add steps
tutorial.addStep(new TutorialStep(
'step_1',
"Print 'Hello, World!'",
"print('Hello, World!')",
['Use the print() function', 'Remember to use quotes around the text']
));
// Validate student code
const result = await tutorial.validateStep(0, "print('Hello, World!')");
console.log(`Passed: ${result.passed}`);
await tutorial.cleanup();
Step 2: Progress Tracking
Track student progress through tutorials:class ProgressTracker:
def __init__(self):
self.progress = {}
def update_progress(self, student_id: str, step_id: str, passed: bool):
"""Update student progress"""
if student_id not in self.progress:
self.progress[student_id] = {
"completed_steps": [],
"current_step": 0,
"total_steps": 0
}
if passed and step_id not in self.progress[student_id]["completed_steps"]:
self.progress[student_id]["completed_steps"].append(step_id)
def get_progress(self, student_id: str) -> Dict[str, Any]:
"""Get student progress"""
if student_id not in self.progress:
return {
"completed_steps": [],
"current_step": 0,
"completion_percentage": 0
}
student_progress = self.progress[student_id]
total = student_progress.get("total_steps", 1)
completed = len(student_progress["completed_steps"])
return {
"completed_steps": student_progress["completed_steps"],
"current_step": student_progress["current_step"],
"completion_percentage": (completed / total * 100) if total > 0 else 0
}
# Usage
tracker = ProgressTracker()
tracker.update_progress("student_1", "step_1", True)
tracker.update_progress("student_1", "step_2", True)
progress = tracker.get_progress("student_1")
print(f"Completion: {progress['completion_percentage']:.1f}%")
class ProgressTracker {
constructor() {
this.progress = {};
}
updateProgress(studentId, stepId, passed) {
if (!this.progress[studentId]) {
this.progress[studentId] = {
completedSteps: [],
currentStep: 0,
totalSteps: 0
};
}
if (passed && !this.progress[studentId].completedSteps.includes(stepId)) {
this.progress[studentId].completedSteps.push(stepId);
}
}
getProgress(studentId) {
if (!this.progress[studentId]) {
return {
completedSteps: [],
currentStep: 0,
completionPercentage: 0
};
}
const studentProgress = this.progress[studentId];
const total = studentProgress.totalSteps || 1;
const completed = studentProgress.completedSteps.length;
return {
completedSteps: studentProgress.completedSteps,
currentStep: studentProgress.currentStep,
completionPercentage: total > 0 ? (completed / total * 100) : 0
};
}
}
// Usage
const tracker = new ProgressTracker();
tracker.updateProgress('student_1', 'step_1', true);
tracker.updateProgress('student_1', 'step_2', true);
const progress = tracker.getProgress('student_1');
console.log(`Completion: ${progress.completionPercentage.toFixed(1)}%`);
Best Practices
- Step-by-Step Learning: Break concepts into small, digestible steps
- Immediate Feedback: Provide instant validation feedback
- Progressive Hints: Offer hints that guide without giving away solutions
- Progress Persistence: Save progress so students can resume
Related Cookbooks
- Online Coding Platform - Full coding platform
- Coding Interview Platform - Interview preparation
Next Steps
- Create tutorial content management system
- Implement hint system with multiple levels
- Add progress persistence
- Create tutorial authoring tools
- Add analytics and reporting

