Skip to main content
Glama
educational-flow-optimizer.ts19.9 kB
/** * Educational Flow Optimizer * Task 3.3: Educational Flow Optimization Implementation * * Optimizes content flow and pacing for effective learning: * - Intelligent content sequencing based on educational principles * - Appropriate pacing with visual breaks and content segments * - Logical progression from introduction to assessment * - Optimized for 50-minute lesson duration * - Integration with Phase 2 content generation and Phase 3 widget mapping */ interface EducationalSegment { id: string; type: 'introduction' | 'concept' | 'example' | 'practice' | 'assessment' | 'summary'; widget_type: string; content: any; duration_minutes: number; cognitive_load: 'low' | 'medium' | 'high'; interaction_level: 'passive' | 'active' | 'interactive'; visual_break: boolean; } interface LessonFlow { total_duration: number; segments: EducationalSegment[]; pacing_strategy: string; cognitive_distribution: { low: number; medium: number; high: number; }; interaction_balance: { passive: number; active: number; interactive: number; }; } interface EducationalContext { subject: string; grade_level: string; topic: string; learning_objectives: string[]; content_complexity: 'basic' | 'intermediate' | 'advanced'; student_attention_span: number; // minutes } interface FlowOptimizationResult { optimized_flow: LessonFlow; educational_rationale: string; pacing_recommendations: string[]; engagement_strategies: string[]; assessment_placement: string; } export class EducationalFlowOptimizer { private readonly OPTIMAL_LESSON_DURATION = 50; // minutes private readonly ATTENTION_SPAN_MAPPING = { 'fundamental': 15, // Elementary: 15-minute focused segments 'médio': 20, // High school: 20-minute segments 'superior': 25 // College: 25-minute segments }; constructor() {} /** * Optimize educational content flow for maximum learning effectiveness */ public optimizeEducationalFlow( content: any, context: EducationalContext, assessmentComponents: any ): FlowOptimizationResult { // Step 1: Analyze content and determine segment structure const baseSegments = this.analyzeContentStructure(content, context); // Step 2: Apply educational flow principles const educationalSequence = this.applyEducationalPrinciples(baseSegments, context); // Step 3: Optimize timing and pacing const timedSegments = this.optimizeTiming(educationalSequence, context); // Step 4: Add visual breaks and interaction points const pacedSegments = this.addPacingElements(timedSegments, context); // Step 5: Integrate assessment components const finalFlow = this.integrateAssessments(pacedSegments, assessmentComponents, context); // Step 6: Validate and adjust for 50-minute duration const optimizedFlow = this.validateDuration(finalFlow, context); return { optimized_flow: optimizedFlow, educational_rationale: this.generateEducationalRationale(optimizedFlow, context), pacing_recommendations: this.generatePacingRecommendations(optimizedFlow, context), engagement_strategies: this.generateEngagementStrategies(optimizedFlow, context), assessment_placement: this.explainAssessmentPlacement(optimizedFlow, context) }; } /** * Analyze content structure and create base segments */ private analyzeContentStructure(content: any, context: EducationalContext): EducationalSegment[] { const segments: EducationalSegment[] = []; // Header/Introduction segment segments.push({ id: `intro-${Date.now()}`, type: 'introduction', widget_type: 'head-1', content: { title: content.metadata?.title || `Aula de ${context.subject}`, topic: context.topic, learning_objectives: context.learning_objectives }, duration_minutes: 3, cognitive_load: 'low', interaction_level: 'passive', visual_break: false }); // Main concept segments if (content.components?.introduction) { segments.push({ id: `concept-intro-${Date.now()}`, type: 'concept', widget_type: 'text-1', content: content.components.introduction, duration_minutes: this.calculateContentDuration(content.components.introduction, context), cognitive_load: 'medium', interaction_level: 'passive', visual_break: false }); } if (content.components?.explanation) { segments.push({ id: `concept-main-${Date.now()}`, type: 'concept', widget_type: 'text-1', content: content.components.explanation, duration_minutes: this.calculateContentDuration(content.components.explanation, context), cognitive_load: 'high', interaction_level: 'active', visual_break: true // Major concept gets visual break }); } // Examples segment if (content.components?.examples) { segments.push({ id: `examples-${Date.now()}`, type: 'example', widget_type: 'list-1', content: content.components.examples, duration_minutes: this.calculateContentDuration(content.components.examples, context), cognitive_load: 'medium', interaction_level: 'active', visual_break: false }); } // Summary segment if (content.components?.summary) { segments.push({ id: `summary-${Date.now()}`, type: 'summary', widget_type: 'text-1', content: content.components.summary, duration_minutes: this.calculateContentDuration(content.components.summary, context), cognitive_load: 'medium', interaction_level: 'passive', visual_break: false }); } return segments; } /** * Apply educational principles for optimal learning sequence */ private applyEducationalPrinciples( segments: EducationalSegment[], context: EducationalContext ): EducationalSegment[] { // Principle 1: Gradual complexity increase const sequenced = this.applyGradualComplexity(segments); // Principle 2: Attention span management const attentionOptimized = this.applyAttentionSpanPrinciples(sequenced, context); // Principle 3: Active learning integration const activeLearning = this.integrateActiveLearning(attentionOptimized, context); return activeLearning; } /** * Apply gradual complexity increase principle */ private applyGradualComplexity(segments: EducationalSegment[]): EducationalSegment[] { // Sort by cognitive load: introduction → low → medium → high const complexityOrder = { 'introduction': 1, 'concept': 2, 'example': 3, 'practice': 4, 'assessment': 5, 'summary': 6 }; return segments.sort((a, b) => { const orderA = complexityOrder[a.type] || 999; const orderB = complexityOrder[b.type] || 999; return orderA - orderB; }); } /** * Apply attention span management principles */ private applyAttentionSpanPrinciples( segments: EducationalSegment[], context: EducationalContext ): EducationalSegment[] { const attentionSpan = this.ATTENTION_SPAN_MAPPING[context.grade_level] || 15; let currentSegmentTime = 0; return segments.map((segment, index) => { currentSegmentTime += segment.duration_minutes; // Add visual break every attention span interval if (currentSegmentTime >= attentionSpan && index < segments.length - 1) { segment.visual_break = true; currentSegmentTime = 0; } // Reduce cognitive load for segments near attention span limit if (currentSegmentTime > attentionSpan * 0.8) { if (segment.cognitive_load === 'high') { segment.cognitive_load = 'medium'; } } return segment; }); } /** * Integrate active learning opportunities */ private integrateActiveLearning( segments: EducationalSegment[], context: EducationalContext ): EducationalSegment[] { let passiveCount = 0; return segments.map(segment => { // Convert every 3rd passive segment to active if (segment.interaction_level === 'passive') { passiveCount++; if (passiveCount % 3 === 0) { segment.interaction_level = 'active'; // Add interactive element for active segments if (segment.widget_type === 'text-1') { segment.widget_type = 'hotspots-1'; // Make text interactive } } } return segment; }); } /** * Optimize timing for each segment */ private optimizeTiming( segments: EducationalSegment[], context: EducationalContext ): EducationalSegment[] { const totalCurrentDuration = segments.reduce((sum, seg) => sum + seg.duration_minutes, 0); const targetDuration = this.OPTIMAL_LESSON_DURATION - 10; // Reserve 10 minutes for assessments if (totalCurrentDuration !== targetDuration) { const adjustmentRatio = targetDuration / totalCurrentDuration; segments.forEach(segment => { segment.duration_minutes = Math.round(segment.duration_minutes * adjustmentRatio); // Ensure minimum 2 minutes per segment segment.duration_minutes = Math.max(2, segment.duration_minutes); }); } return segments; } /** * Add pacing elements and visual breaks */ private addPacingElements( segments: EducationalSegment[], context: EducationalContext ): EducationalSegment[] { const pacedSegments: EducationalSegment[] = []; segments.forEach((segment, index) => { pacedSegments.push(segment); // Add visual break segment after high cognitive load if (segment.visual_break && segment.cognitive_load === 'high') { pacedSegments.push({ id: `visual-break-${index}`, type: 'example', widget_type: 'image-1', content: { type: 'visual_break', description: 'Momento de reflexão visual' }, duration_minutes: 1, cognitive_load: 'low', interaction_level: 'passive', visual_break: false }); } // Add interaction opportunity every 15 minutes const cumulativeDuration = pacedSegments.reduce((sum, seg) => sum + seg.duration_minutes, 0); if (cumulativeDuration % 15 === 0 && index < segments.length - 1) { pacedSegments.push({ id: `interaction-${index}`, type: 'practice', widget_type: 'hotspots-1', content: { type: 'quick_interaction', description: 'Momento de participação' }, duration_minutes: 2, cognitive_load: 'medium', interaction_level: 'interactive', visual_break: false }); } }); return pacedSegments; } /** * Integrate assessment components from Phase 2 */ private integrateAssessments( segments: EducationalSegment[], assessmentComponents: any, context: EducationalContext ): EducationalSegment[] { const assessmentSegments: EducationalSegment[] = []; // Add flashcards before final summary (for reinforcement) if (assessmentComponents?.flashcards) { assessmentSegments.push({ id: `flashcards-${Date.now()}`, type: 'practice', widget_type: 'flashcards-1', content: assessmentComponents.flashcards, duration_minutes: 5, cognitive_load: 'medium', interaction_level: 'interactive', visual_break: true }); } // Add quiz at the end (for assessment) if (assessmentComponents?.quiz) { assessmentSegments.push({ id: `quiz-${Date.now()}`, type: 'assessment', widget_type: 'quiz-1', content: assessmentComponents.quiz, duration_minutes: 5, cognitive_load: 'high', interaction_level: 'interactive', visual_break: false }); } // Insert assessments at optimal points const insertionPoint = Math.floor(segments.length * 0.8); // 80% through content return [ ...segments.slice(0, insertionPoint), ...assessmentSegments, ...segments.slice(insertionPoint) ]; } /** * Validate and adjust for 50-minute duration */ private validateDuration(segments: EducationalSegment[], context: EducationalContext): LessonFlow { const totalDuration = segments.reduce((sum, seg) => sum + seg.duration_minutes, 0); // Adjust if over/under duration if (totalDuration > this.OPTIMAL_LESSON_DURATION) { // Compress segments proportionally const compressionRatio = this.OPTIMAL_LESSON_DURATION / totalDuration; segments.forEach(segment => { segment.duration_minutes = Math.max(1, Math.floor(segment.duration_minutes * compressionRatio)); }); } else if (totalDuration < this.OPTIMAL_LESSON_DURATION - 5) { // Add buffer time to key segments const timeToAdd = this.OPTIMAL_LESSON_DURATION - totalDuration; const keySegments = segments.filter(s => s.type === 'concept' || s.type === 'example'); const timePerSegment = Math.floor(timeToAdd / keySegments.length); keySegments.forEach(segment => { segment.duration_minutes += timePerSegment; }); } // Calculate distribution metrics const cognitiveDistribution = this.calculateCognitiveDistribution(segments); const interactionBalance = this.calculateInteractionBalance(segments); return { total_duration: segments.reduce((sum, seg) => sum + seg.duration_minutes, 0), segments, pacing_strategy: this.determinePacingStrategy(segments, context), cognitive_distribution: cognitiveDistribution, interaction_balance: interactionBalance }; } /** * Calculate content duration based on complexity and grade level */ private calculateContentDuration(content: any, context: EducationalContext): number { if (!content) return 2; const baseMinutes = { 'fundamental': 5, 'médio': 7, 'superior': 10 }; const base = baseMinutes[context.grade_level] || 5; // Adjust based on content complexity const complexityMultiplier = { 'basic': 0.8, 'intermediate': 1.0, 'advanced': 1.3 }; return Math.round(base * (complexityMultiplier[context.content_complexity] || 1.0)); } /** * Calculate cognitive load distribution */ private calculateCognitiveDistribution(segments: EducationalSegment[]) { const total = segments.length; const low = segments.filter(s => s.cognitive_load === 'low').length; const medium = segments.filter(s => s.cognitive_load === 'medium').length; const high = segments.filter(s => s.cognitive_load === 'high').length; return { low: Math.round((low / total) * 100), medium: Math.round((medium / total) * 100), high: Math.round((high / total) * 100) }; } /** * Calculate interaction balance */ private calculateInteractionBalance(segments: EducationalSegment[]) { const total = segments.length; const passive = segments.filter(s => s.interaction_level === 'passive').length; const active = segments.filter(s => s.interaction_level === 'active').length; const interactive = segments.filter(s => s.interaction_level === 'interactive').length; return { passive: Math.round((passive / total) * 100), active: Math.round((active / total) * 100), interactive: Math.round((interactive / total) * 100) }; } /** * Determine pacing strategy based on flow analysis */ private determinePacingStrategy(segments: EducationalSegment[], context: EducationalContext): string { const interactiveRatio = segments.filter(s => s.interaction_level === 'interactive').length / segments.length; const highCognitiveRatio = segments.filter(s => s.cognitive_load === 'high').length / segments.length; if (interactiveRatio > 0.4) { return 'high-engagement'; } else if (highCognitiveRatio > 0.3) { return 'cognitive-intensive'; } else { return 'balanced-progression'; } } /** * Generate educational rationale */ private generateEducationalRationale(flow: LessonFlow, context: EducationalContext): string { return `Esta estrutura de aula de ${flow.total_duration} minutos foi otimizada para ${context.grade_level} ` + `seguindo princípios de atenção graduada e complexidade crescente. A distribuição cognitiva ` + `(${flow.cognitive_distribution.low}% baixa, ${flow.cognitive_distribution.medium}% média, ` + `${flow.cognitive_distribution.high}% alta) garante assimilação efetiva do conteúdo sobre ${context.topic}.`; } /** * Generate pacing recommendations */ private generatePacingRecommendations(flow: LessonFlow, context: EducationalContext): string[] { const recommendations = []; if (flow.cognitive_distribution.high > 40) { recommendations.push('Considere dividir conceitos complexos em segmentos menores'); } if (flow.interaction_balance.passive > 60) { recommendations.push('Adicione mais oportunidades de participação ativa dos estudantes'); } if (flow.total_duration > 45) { recommendations.push('Planeje pausas estratégicas para manter a atenção'); } recommendations.push(`Mantenha segmentos de no máximo ${this.ATTENTION_SPAN_MAPPING[context.grade_level]} minutos para este nível`); return recommendations; } /** * Generate engagement strategies */ private generateEngagementStrategies(flow: LessonFlow, context: EducationalContext): string[] { const strategies = []; strategies.push('Use elementos visuais para quebrar sequências de texto'); strategies.push('Intercale momentos de reflexão individual e discussão em grupo'); strategies.push('Conecte conceitos abstratos com exemplos práticos do cotidiano'); if (context.grade_level === 'fundamental') { strategies.push('Utilize jogos educativos e atividades lúdicas'); } else if (context.grade_level === 'médio') { strategies.push('Promova debates e análises críticas'); } else { strategies.push('Incentive pesquisa e aprofundamento autônomo'); } return strategies; } /** * Explain assessment placement strategy */ private explainAssessmentPlacement(flow: LessonFlow, context: EducationalContext): string { const assessmentSegments = flow.segments.filter(s => s.type === 'assessment' || s.type === 'practice'); return `Avaliações foram posicionadas estrategicamente: flashcards para reforço após ` + `apresentação do conteúdo principal, e quiz final para verificação da aprendizagem. ` + `Esta sequência permite consolidação antes da avaliação formal.`; } /** * Integration with Phase 2 content generation and Phase 3 widget mapping */ public integrateWithContentGeneration( baseAdapterOutput: any, assessmentEngineOutput: any, imageSelectionOutput: any, context: EducationalContext ): FlowOptimizationResult { // Combine all Phase 2 and Phase 3 outputs const combinedContent = { components: baseAdapterOutput, assessments: assessmentEngineOutput, images: imageSelectionOutput }; // Apply flow optimization to the complete educational package return this.optimizeEducationalFlow(combinedContent, context, assessmentEngineOutput); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rkm097git/euconquisto-composer-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server