refactor: replace demo component with real TutorialPlayer system
Replaced the simple FriendsOfFiveDemo component with the actual TutorialPlayer from the existing tutorial system, showing the "Friends of 5" lesson (2+3=5). Changes: - Removed FriendsOfFiveDemo.tsx (redundant custom component) - Updated homepage to use TutorialPlayer with filtered tutorial steps - Added TUTORIAL_SYSTEM.md documentation explaining the full tutorial system - Homepage now demonstrates the real learning system instead of a mock The tutorial system includes: - Step-by-step guidance with bead highlighting - Real-time feedback and validation - Multi-step instruction support - Pedagogical decomposition - Auto-advancement on correct completion - Full tutorial editor at /tutorial-editor 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
222
apps/web/.claude/TUTORIAL_SYSTEM.md
Normal file
222
apps/web/.claude/TUTORIAL_SYSTEM.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# Tutorial System Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The tutorial system is a sophisticated interactive learning platform for teaching soroban abacus concepts. It features step-by-step guidance, bead highlighting, pedagogical decomposition, and progress tracking.
|
||||
|
||||
## Key Components
|
||||
|
||||
### 1. TutorialPlayer (`/src/components/tutorial/TutorialPlayer.tsx`)
|
||||
The main tutorial playback component that:
|
||||
- Displays tutorial steps progressively
|
||||
- Highlights specific beads users should interact with
|
||||
- Provides real-time feedback and tooltips
|
||||
- Shows step-by-step instructions for multi-step operations
|
||||
- Tracks user progress through the tutorial
|
||||
- Auto-advances to next step on correct completion
|
||||
|
||||
**Key Features:**
|
||||
- **Bead Highlighting**: Visual indicators showing which beads to manipulate
|
||||
- **Step Progress**: Shows current step out of total steps
|
||||
- **Error Feedback**: Provides hints when user makes mistakes
|
||||
- **Multi-Step Support**: Breaks complex operations into sequential sub-steps
|
||||
- **Pedagogical Decomposition**: Explains the "why" behind each operation
|
||||
|
||||
### 2. TutorialEditor (`/src/components/tutorial/TutorialEditor.tsx`)
|
||||
A full-featured editor for creating and editing tutorials:
|
||||
- Visual step editor
|
||||
- Bead highlight configuration
|
||||
- Multi-step instruction editor
|
||||
- Live preview
|
||||
- Import/export functionality
|
||||
- Access control
|
||||
|
||||
**Editor URL:** `/tutorial-editor`
|
||||
|
||||
### 3. Tutorial Data Structure (`/src/types/tutorial.ts`)
|
||||
|
||||
```typescript
|
||||
interface Tutorial {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
category: string
|
||||
difficulty: 'beginner' | 'intermediate' | 'advanced'
|
||||
estimatedDuration: number // minutes
|
||||
steps: TutorialStep[]
|
||||
tags: string[]
|
||||
author: string
|
||||
version: string
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
isPublished: boolean
|
||||
}
|
||||
|
||||
interface TutorialStep {
|
||||
id: string
|
||||
title: string
|
||||
problem: string // e.g. "2 + 3"
|
||||
description: string // User-facing explanation
|
||||
startValue: number // Initial abacus value
|
||||
targetValue: number // Goal value
|
||||
expectedAction: 'add' | 'remove' | 'multi-step'
|
||||
actionDescription: string
|
||||
|
||||
// Bead highlighting
|
||||
highlightBeads?: Array<{
|
||||
placeValue: number // 0=ones, 1=tens, etc.
|
||||
beadType: 'heaven' | 'earth'
|
||||
position?: number // For earth beads: 0-3
|
||||
}>
|
||||
|
||||
// Progressive step highlighting
|
||||
stepBeadHighlights?: Array<{
|
||||
placeValue: number
|
||||
beadType: 'heaven' | 'earth'
|
||||
position?: number
|
||||
stepIndex: number // Which instruction step
|
||||
direction: 'up' | 'down' | 'activate' | 'deactivate'
|
||||
order?: number // Order within step
|
||||
}>
|
||||
|
||||
totalSteps?: number // For multi-step operations
|
||||
multiStepInstructions?: string[] // Sequential instructions
|
||||
|
||||
// Tooltips and guidance
|
||||
tooltip: {
|
||||
content: string // Short title
|
||||
explanation: string // Detailed explanation
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Tutorial Converter (`/src/utils/tutorialConverter.ts`)
|
||||
|
||||
Utility that converts the original `GuidedAdditionTutorial` data into the new tutorial format:
|
||||
- `guidedAdditionSteps`: Array of tutorial steps from basic addition to complements
|
||||
- `convertGuidedAdditionTutorial()`: Converts to Tutorial object
|
||||
- `getTutorialForEditor()`: Main export used in the app
|
||||
|
||||
**Current Tutorial Steps:**
|
||||
1. Basic Addition (0+1, 1+1, 2+1, 3+1)
|
||||
2. Heaven Bead Introduction (0+5, 5+1)
|
||||
3. Five Complements (3+4, 2+3 using 5-complement method)
|
||||
4. Complex Operations (6+2, 7+4 with carrying)
|
||||
|
||||
### 5. Supporting Utilities
|
||||
|
||||
**`/src/utils/abacusInstructionGenerator.ts`**
|
||||
- Automatically generates step-by-step instructions from start/target values
|
||||
- Creates bead highlight data
|
||||
- Determines movement directions
|
||||
|
||||
**`/src/utils/beadDiff.ts`**
|
||||
- Calculates differences between abacus states
|
||||
- Generates visual feedback tooltips
|
||||
- Explains what changed and why
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Usage in a Page
|
||||
|
||||
```typescript
|
||||
import { TutorialPlayer } from '@/components/tutorial/TutorialPlayer'
|
||||
import { getTutorialForEditor } from '@/utils/tutorialConverter'
|
||||
|
||||
export function MyPage() {
|
||||
return (
|
||||
<TutorialPlayer
|
||||
tutorial={getTutorialForEditor()}
|
||||
isDebugMode={false}
|
||||
showDebugPanel={false}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Using a Subset of Steps
|
||||
|
||||
```typescript
|
||||
import { getTutorialForEditor } from '@/utils/tutorialConverter'
|
||||
|
||||
const fullTutorial = getTutorialForEditor()
|
||||
|
||||
// Extract specific steps (e.g., just "Friends of 5")
|
||||
const friendsOf5Tutorial = {
|
||||
...fullTutorial,
|
||||
id: 'friends-of-5-demo',
|
||||
title: 'Friends of 5',
|
||||
steps: fullTutorial.steps.filter(step =>
|
||||
step.id === 'complement-2' // The 2+3=5 step
|
||||
)
|
||||
}
|
||||
|
||||
return <TutorialPlayer tutorial={friendsOf5Tutorial} />
|
||||
```
|
||||
|
||||
### Creating a Custom Tutorial
|
||||
|
||||
```typescript
|
||||
const customTutorial: Tutorial = {
|
||||
id: 'my-tutorial',
|
||||
title: 'My Custom Tutorial',
|
||||
description: 'Learning something new',
|
||||
category: 'Custom',
|
||||
difficulty: 'beginner',
|
||||
estimatedDuration: 5,
|
||||
steps: [
|
||||
{
|
||||
id: 'step-1',
|
||||
title: 'Add 2',
|
||||
problem: '0 + 2',
|
||||
description: 'Move two earth beads up',
|
||||
startValue: 0,
|
||||
targetValue: 2,
|
||||
expectedAction: 'add',
|
||||
actionDescription: 'Add two earth beads',
|
||||
highlightBeads: [
|
||||
{ placeValue: 0, beadType: 'earth', position: 0 },
|
||||
{ placeValue: 0, beadType: 'earth', position: 1 }
|
||||
],
|
||||
tooltip: {
|
||||
content: 'Adding 2',
|
||||
explanation: 'Push two earth beads up to represent 2'
|
||||
}
|
||||
}
|
||||
],
|
||||
tags: ['custom'],
|
||||
author: 'Me',
|
||||
version: '1.0.0',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
isPublished: true
|
||||
}
|
||||
```
|
||||
|
||||
## Current Implementation Locations
|
||||
|
||||
**Live Tutorials:**
|
||||
- `/guide` - Second tab "Arithmetic Operations" contains the full guided addition tutorial
|
||||
|
||||
**Editor:**
|
||||
- `/tutorial-editor` - Full tutorial editing interface
|
||||
|
||||
**Storybook:**
|
||||
- Multiple tutorial stories in `/src/components/tutorial/*.stories.tsx`
|
||||
|
||||
## Key Design Principles
|
||||
|
||||
1. **Progressive Disclosure**: Users see one step at a time
|
||||
2. **Immediate Feedback**: Real-time validation and hints
|
||||
3. **Visual Guidance**: Bead highlighting shows exactly what to do
|
||||
4. **Pedagogical Decomposition**: Multi-step operations broken into atomic actions
|
||||
5. **Auto-Advancement**: Successful completion automatically moves to next step
|
||||
6. **Error Recovery**: Helpful hints when user makes mistakes
|
||||
|
||||
## Notes
|
||||
|
||||
- The tutorial system uses the existing `AbacusReact` component
|
||||
- Tutorials can be created/edited through the TutorialEditor
|
||||
- Tutorial data can be exported/imported as JSON
|
||||
- The system supports both single-step and multi-step operations
|
||||
- Bead highlighting uses place value indexing (0=ones, 1=tens, etc.)
|
||||
@@ -2,11 +2,21 @@
|
||||
|
||||
import Link from 'next/link'
|
||||
import { PageWithNav } from '@/components/PageWithNav'
|
||||
import { FriendsOfFiveDemo } from '@/components/FriendsOfFiveDemo'
|
||||
import { TutorialPlayer } from '@/components/tutorial/TutorialPlayer'
|
||||
import { getTutorialForEditor } from '@/utils/tutorialConverter'
|
||||
import { css } from '../../styled-system/css'
|
||||
import { container, grid, hstack, stack } from '../../styled-system/patterns'
|
||||
|
||||
export default function HomePage() {
|
||||
// Extract just the "Friends of 5" step (2+3=5) for homepage demo
|
||||
const fullTutorial = getTutorialForEditor()
|
||||
const friendsOf5Tutorial = {
|
||||
...fullTutorial,
|
||||
id: 'friends-of-5-demo',
|
||||
title: 'Friends of 5',
|
||||
description: 'Learn the "Friends of 5" technique: adding 3 to make 5',
|
||||
steps: fullTutorial.steps.filter((step) => step.id === 'complement-2'),
|
||||
}
|
||||
|
||||
return (
|
||||
<PageWithNav navTitle="Soroban Learning Platform" navEmoji="🧮">
|
||||
@@ -198,7 +208,20 @@ export default function HomePage() {
|
||||
|
||||
<div className={grid({ columns: { base: 1, lg: 2 }, gap: '8' })}>
|
||||
{/* Live demo */}
|
||||
<FriendsOfFiveDemo />
|
||||
<div
|
||||
className={css({
|
||||
bg: 'white',
|
||||
rounded: 'xl',
|
||||
p: '6',
|
||||
shadow: 'lg',
|
||||
})}
|
||||
>
|
||||
<TutorialPlayer
|
||||
tutorial={friendsOf5Tutorial}
|
||||
isDebugMode={false}
|
||||
showDebugPanel={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* What you'll learn */}
|
||||
<div
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { AbacusReact, useAbacusConfig } from '@soroban/abacus-react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { css } from '../../styled-system/css'
|
||||
import { stack } from '../../styled-system/patterns'
|
||||
|
||||
/**
|
||||
* Compact "Friends of 5" demo for the homepage
|
||||
* Shows an interactive example of learning soroban concepts
|
||||
*/
|
||||
export function FriendsOfFiveDemo() {
|
||||
const [currentValue, setCurrentValue] = useState(2)
|
||||
const [targetValue] = useState(5)
|
||||
const [feedback, setFeedback] = useState<string>('Try adding 3 more beads to make 5!')
|
||||
const [isCorrect, setIsCorrect] = useState(false)
|
||||
const appConfig = useAbacusConfig()
|
||||
|
||||
const handleValueChange = useCallback(
|
||||
(newValue: number) => {
|
||||
setCurrentValue(newValue)
|
||||
|
||||
if (newValue === targetValue) {
|
||||
setIsCorrect(true)
|
||||
setFeedback('Perfect! You made 5! This is the "Friends of 5" concept.')
|
||||
} else if (newValue > targetValue) {
|
||||
setFeedback('Oops! Too many beads. Try to make exactly 5.')
|
||||
} else {
|
||||
setFeedback(`Add ${targetValue - newValue} more to make 5!`)
|
||||
}
|
||||
},
|
||||
[targetValue]
|
||||
)
|
||||
|
||||
// Reset after 3 seconds when correct
|
||||
useEffect(() => {
|
||||
if (isCorrect) {
|
||||
const timeout = setTimeout(() => {
|
||||
setCurrentValue(2)
|
||||
setIsCorrect(false)
|
||||
setFeedback('Try adding 3 more beads to make 5!')
|
||||
}, 3000)
|
||||
return () => clearTimeout(timeout)
|
||||
}
|
||||
}, [isCorrect])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={stack({
|
||||
gap: '4',
|
||||
bg: 'rgba(255, 255, 255, 0.05)',
|
||||
p: '6',
|
||||
borderRadius: 'xl',
|
||||
border: '1px solid rgba(139, 92, 246, 0.2)',
|
||||
})}
|
||||
>
|
||||
{/* Title */}
|
||||
<div className={css({ textAlign: 'center' })}>
|
||||
<h4
|
||||
className={css({
|
||||
fontSize: 'lg',
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
mb: '2',
|
||||
})}
|
||||
>
|
||||
Try It Now: Friends of 5
|
||||
</h4>
|
||||
<p className={css({ fontSize: 'sm', color: 'gray.300' })}>Problem: 2 + 3 = ?</p>
|
||||
</div>
|
||||
|
||||
{/* Interactive Abacus */}
|
||||
<div
|
||||
className={css({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
bg: 'white',
|
||||
p: '4',
|
||||
borderRadius: 'lg',
|
||||
minHeight: '200px',
|
||||
alignItems: 'center',
|
||||
})}
|
||||
>
|
||||
<AbacusReact
|
||||
value={currentValue}
|
||||
columns={1}
|
||||
beadShape={appConfig.beadShape}
|
||||
colorScheme={appConfig.colorScheme}
|
||||
hideInactiveBeads={appConfig.hideInactiveBeads}
|
||||
interactive={true}
|
||||
animated={true}
|
||||
soundEnabled={true}
|
||||
soundVolume={0.3}
|
||||
scaleFactor={1.8}
|
||||
showNumbers={true}
|
||||
onValueChange={handleValueChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Feedback */}
|
||||
<div
|
||||
className={css({
|
||||
p: '3',
|
||||
bg: isCorrect ? 'rgba(34, 197, 94, 0.1)' : 'rgba(59, 130, 246, 0.1)',
|
||||
border: '1px solid',
|
||||
borderColor: isCorrect ? 'rgba(34, 197, 94, 0.3)' : 'rgba(59, 130, 246, 0.3)',
|
||||
borderRadius: 'md',
|
||||
textAlign: 'center',
|
||||
})}
|
||||
>
|
||||
<p
|
||||
className={css({
|
||||
fontSize: 'sm',
|
||||
color: isCorrect ? 'green.300' : 'blue.300',
|
||||
fontWeight: 'medium',
|
||||
})}
|
||||
>
|
||||
{feedback}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={css({ textAlign: 'center', fontSize: 'xs', color: 'gray.400' })}>
|
||||
Click the beads to move them up or down
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user