feat(help-system): add schema for progressive help and feedback loop
Phase 1 of help system implementation: Schema changes: - Add HelpLevel type (0-3) to session-plans.ts - Extend SlotResult with helpLevelUsed, incorrectAttempts, helpTrigger - Add REINFORCEMENT_CONFIG constants for mastery credit multipliers - Add reinforcement tracking columns to player_skill_mastery: - needsReinforcement: flag for skills needing extra practice - lastHelpLevel: track struggling patterns - reinforcementStreak: track progress toward clearing reinforcement - Add StudentHelpSettings interface and column to players: - helpMode: 'auto' | 'manual' | 'teacher-approved' - autoEscalationTimingMs: configurable help timing thresholds - beginnerFreeHelp: unlimited L1-L2 help without penalty - advancedRequiresApproval: require teacher auth for L2+ help This closes the feedback loop between help usage and session planning: - Help usage informs skill mastery scoring - Reinforcement flags guide session planner to include extra practice - Teacher has visibility into which skills need attention 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f153dddfce
commit
41c46038d8
|
|
@ -0,0 +1,12 @@
|
|||
-- Custom SQL migration file, put your code below! --
|
||||
|
||||
-- Add reinforcement tracking columns to player_skill_mastery table
|
||||
ALTER TABLE `player_skill_mastery` ADD `needs_reinforcement` integer DEFAULT 0 NOT NULL;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `player_skill_mastery` ADD `last_help_level` integer DEFAULT 0 NOT NULL;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `player_skill_mastery` ADD `reinforcement_streak` integer DEFAULT 0 NOT NULL;
|
||||
--> statement-breakpoint
|
||||
|
||||
-- Add help_settings column to players table
|
||||
ALTER TABLE `players` ADD `help_settings` text DEFAULT '{"helpMode":"auto","autoEscalationTimingMs":{"level1":30000,"level2":60000,"level3":90000},"beginnerFreeHelp":true,"advancedRequiresApproval":false}';
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -190,6 +190,13 @@
|
|||
"when": 1765035309900,
|
||||
"tag": "0026_add_practice_sessions",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"version": "6",
|
||||
"when": 1765055035935,
|
||||
"tag": "0027_help_system_schema",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,29 @@ export const playerSkillMastery = sqliteTable(
|
|||
updatedAt: integer('updated_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
|
||||
// ---- Reinforcement Tracking (for help system feedback loop) ----
|
||||
|
||||
/**
|
||||
* Whether this skill needs reinforcement
|
||||
* Set to true when student uses heavy help (level 2+) or has multiple incorrect attempts
|
||||
* Cleared after N consecutive correct answers without help
|
||||
*/
|
||||
needsReinforcement: integer('needs_reinforcement', { mode: 'boolean' })
|
||||
.notNull()
|
||||
.default(false),
|
||||
|
||||
/**
|
||||
* Last help level used on this skill (0-3)
|
||||
* Used to track struggling patterns
|
||||
*/
|
||||
lastHelpLevel: integer('last_help_level').notNull().default(0),
|
||||
|
||||
/**
|
||||
* Consecutive correct answers without heavy help since reinforcement was flagged
|
||||
* Resets to 0 when reinforcement is cleared or when help level 2+ is used
|
||||
*/
|
||||
reinforcementStreak: integer('reinforcement_streak').notNull().default(0),
|
||||
},
|
||||
(table) => ({
|
||||
/** Index for fast lookups by playerId */
|
||||
|
|
@ -110,6 +133,39 @@ export const MASTERY_CONFIG = {
|
|||
minimumForPracticing: 5,
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Reinforcement configuration constants
|
||||
*/
|
||||
export const REINFORCEMENT_CONFIG = {
|
||||
/**
|
||||
* Help level threshold that triggers reinforcement flag
|
||||
* Level 2+ (decomposition or bead arrows) indicates the student needed significant help
|
||||
*/
|
||||
helpLevelThreshold: 2,
|
||||
|
||||
/**
|
||||
* Number of consecutive correct answers without heavy help to clear reinforcement
|
||||
*/
|
||||
streakToClear: 3,
|
||||
|
||||
/**
|
||||
* Maximum help level that still counts toward clearing reinforcement
|
||||
* Level 1 (hints) is OK, but Level 2+ resets the streak
|
||||
*/
|
||||
maxHelpLevelToCount: 1,
|
||||
|
||||
/**
|
||||
* Mastery credit multipliers based on help level
|
||||
* Used when updating skill mastery after a correct answer
|
||||
*/
|
||||
creditMultipliers: {
|
||||
0: 1.0, // No help: full credit
|
||||
1: 1.0, // Hint only: full credit
|
||||
2: 0.5, // Decomposition: half credit
|
||||
3: 0.25, // Bead arrows: quarter credit
|
||||
} as Record<0 | 1 | 2 | 3, number>,
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Calculate the mastery level based on current stats
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,6 +2,49 @@ import { createId } from '@paralleldrive/cuid2'
|
|||
import { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
|
||||
import { users } from './users'
|
||||
|
||||
/**
|
||||
* Help mode for practice sessions
|
||||
* - 'auto': Help automatically appears after time thresholds
|
||||
* - 'manual': Help only appears when student clicks for it
|
||||
* - 'teacher-approved': Student can request help, but teacher must approve
|
||||
*/
|
||||
export type HelpMode = 'auto' | 'manual' | 'teacher-approved'
|
||||
|
||||
/**
|
||||
* Settings that control help behavior during practice sessions
|
||||
*/
|
||||
export interface StudentHelpSettings {
|
||||
/** How help is triggered */
|
||||
helpMode: HelpMode
|
||||
|
||||
/** For 'auto' mode: milliseconds before each help level appears */
|
||||
autoEscalationTimingMs: {
|
||||
level1: number // Default: 30000 (30s)
|
||||
level2: number // Default: 60000 (60s)
|
||||
level3: number // Default: 90000 (90s)
|
||||
}
|
||||
|
||||
/** For beginners: unlimited L1-L2 help without mastery penalty */
|
||||
beginnerFreeHelp: boolean
|
||||
|
||||
/** For advanced: L2+ help requires teacher approval */
|
||||
advancedRequiresApproval: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Default help settings for new students
|
||||
*/
|
||||
export const DEFAULT_HELP_SETTINGS: StudentHelpSettings = {
|
||||
helpMode: 'auto',
|
||||
autoEscalationTimingMs: {
|
||||
level1: 30000,
|
||||
level2: 60000,
|
||||
level3: 90000,
|
||||
},
|
||||
beginnerFreeHelp: true,
|
||||
advancedRequiresApproval: false,
|
||||
}
|
||||
|
||||
/**
|
||||
* Players table - user-created player profiles for games
|
||||
*
|
||||
|
|
@ -36,6 +79,14 @@ export const players = sqliteTable(
|
|||
createdAt: integer('created_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
|
||||
/**
|
||||
* Help settings for practice sessions
|
||||
* Controls how help is triggered and escalated
|
||||
*/
|
||||
helpSettings: text('help_settings', { mode: 'json' })
|
||||
.$type<StudentHelpSettings>()
|
||||
.default(JSON.stringify(DEFAULT_HELP_SETTINGS)),
|
||||
},
|
||||
(table) => ({
|
||||
/** Index for fast lookups by userId */
|
||||
|
|
|
|||
|
|
@ -128,6 +128,15 @@ export interface SessionAdjustment {
|
|||
previousHealth: SessionHealth
|
||||
}
|
||||
|
||||
/**
|
||||
* Help level used during a problem
|
||||
* - 0: No help requested
|
||||
* - 1: Coach hint only (e.g., "Add the tens digit first")
|
||||
* - 2: Decomposition shown (e.g., "45 + 27 = 45 + 20 + 7")
|
||||
* - 3: Bead highlighting (arrows showing which beads to move)
|
||||
*/
|
||||
export type HelpLevel = 0 | 1 | 2 | 3
|
||||
|
||||
/**
|
||||
* Result of a single problem slot
|
||||
*/
|
||||
|
|
@ -143,6 +152,17 @@ export interface SlotResult {
|
|||
skillsExercised: string[]
|
||||
usedOnScreenAbacus: boolean
|
||||
timestamp: Date
|
||||
|
||||
// ---- Help Tracking (for feedback loop) ----
|
||||
|
||||
/** Maximum help level used during this problem (0 = no help) */
|
||||
helpLevelUsed: HelpLevel
|
||||
|
||||
/** Number of incorrect attempts before getting the right answer */
|
||||
incorrectAttempts: number
|
||||
|
||||
/** How help was triggered */
|
||||
helpTrigger?: 'none' | 'manual' | 'auto-time' | 'auto-errors' | 'teacher-approved'
|
||||
}
|
||||
|
||||
export type SessionStatus = 'draft' | 'approved' | 'in_progress' | 'completed' | 'abandoned'
|
||||
|
|
|
|||
Loading…
Reference in New Issue