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:
Thomas Hallock
2025-10-19 12:36:24 -05:00
parent be68af0d56
commit 19b03bc77c
3 changed files with 247 additions and 129 deletions

View 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.)

View File

@@ -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

View File

@@ -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>
)
}