educational-flow-optimizer.ts•19.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);
}
}