UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

405 lines (402 loc) 16.4 kB
import { useState, useCallback, useEffect, useRef } from 'react'; /** * AI-Powered Personalization Engine * Advanced machine learning system for adaptive user experience personalization */ // AI Learning Engine Class class AIPersonalizationEngine { constructor() { this.interactions = []; this.patterns = []; this.profiles = new Map(); this.models = new Map(); this.featureCache = new Map(); } // Add user interaction to learning dataset addInteraction(interaction) { this.interactions.push(interaction); // Keep interactions buffer manageable (last 10,000 interactions) if (this.interactions.length > 10000) { this.interactions = this.interactions.slice(-10000); } // Trigger incremental learning this.incrementalLearning(interaction); } // Extract features from interaction data extractFeatures(interactions) { if (interactions.length === 0) return {}; // Temporal features const now = Date.now(); const recentInteractions = interactions.filter(i => now - i.timestamp < 3600000); // Last hour const features = { // Interaction frequency totalInteractions: interactions.length, recentInteractionRate: recentInteractions.length / 60, // Interactions per minute // Interaction types distribution clickRatio: interactions.filter(i => i.type === 'click').length / interactions.length, hoverRatio: interactions.filter(i => i.type === 'hover').length / interactions.length, scrollRatio: interactions.filter(i => i.type === 'scroll').length / interactions.length, // Duration patterns avgInteractionDuration: interactions.reduce((sum, i) => sum + i.duration, 0) / interactions.length, maxInteractionDuration: Math.max(...interactions.map(i => i.duration)), minInteractionDuration: Math.min(...interactions.map(i => i.duration)), // Temporal patterns hourOfDay: new Date().getHours(), dayOfWeek: new Date().getDay(), // Sequence patterns sequentialClicks: this.countSequentialPatterns(interactions, 'click'), rapidInteractions: interactions.filter(i => i.duration < 100).length, slowInteractions: interactions.filter(i => i.duration > 5000).length, // Spatial patterns (if position data available) avgPositionX: this.calculateAveragePosition(interactions, 'x'), avgPositionY: this.calculateAveragePosition(interactions, 'y'), positionVariance: this.calculatePositionVariance(interactions), // Context patterns uniqueContexts: new Set(interactions.map(i => i.context)).size, contextSwitchRate: this.calculateContextSwitchRate(interactions) }; return features; } // Incremental learning from new interaction incrementalLearning(interaction) { const recentInteractions = this.interactions.slice(-100); // Last 100 interactions const features = this.extractFeatures(recentInteractions); // Update behavior patterns this.updateBehaviorPatterns(interaction, features); // Update models incrementally this.updateModelsIncremental(features); } // Update behavior patterns based on new interaction updateBehaviorPatterns(interaction, features) { const patternId = `${interaction.type}-${interaction.context}`; let pattern = this.patterns.find(p => p.id === patternId); if (!pattern) { // Create new pattern pattern = { id: patternId, name: `${interaction.type} in ${interaction.context}`, confidence: 0.1, frequency: 1, contexts: [interaction.context], temporal: { timeOfDay: [new Date(interaction.timestamp).getHours()], dayOfWeek: [new Date(interaction.timestamp).getDay()] }, triggers: [], outcomes: [] }; this.patterns.push(pattern); } else { // Update existing pattern pattern.frequency += 1; pattern.confidence = Math.min(1, pattern.confidence + 0.01); // Update temporal data const hour = new Date(interaction.timestamp).getHours(); const day = new Date(interaction.timestamp).getDay(); if (!pattern.temporal.timeOfDay.includes(hour)) { pattern.temporal.timeOfDay.push(hour); } if (!pattern.temporal.dayOfWeek.includes(day)) { pattern.temporal.dayOfWeek.push(day); } } } // Generate personalization profile for user generatePersonalizationProfile(userId) { const userInteractions = this.interactions; // In real app, filter by userId const features = this.extractFeatures(userInteractions); // Analyze UI preferences from interaction patterns const uiPreferences = this.analyzeUIPreferences(userInteractions, features); const interactionStyle = this.analyzeInteractionStyle(userInteractions, features); const contentPreferences = this.analyzeContentPreferences(userInteractions, features); const temporalPatterns = this.analyzeTemporalPatterns(userInteractions, features); const cognitiveProfile = this.analyzeCognitiveProfile(userInteractions, features); const profile = { userId, created: Date.now(), lastUpdated: Date.now(), confidence: this.calculateOverallConfidence(userInteractions), uiPreferences, interactionStyle, contentPreferences, temporalPatterns, cognitiveProfile }; this.profiles.set(userId, profile); return profile; } // Analyze UI preferences from interaction data analyzeUIPreferences(interactions, features) { return { colorScheme: features.hourOfDay > 18 || features.hourOfDay < 6 ? 'dark' : 'light', animationSpeed: Math.max(0.1, Math.min(2.0, 1 + (features.rapidInteractions - features.slowInteractions) / 100)), density: features.avgInteractionDuration < 1000 ? 'compact' : features.avgInteractionDuration > 3000 ? 'spacious' : 'comfortable', complexity: features.uniqueContexts > 10 ? 'advanced' : features.uniqueContexts < 5 ? 'simple' : 'standard', fontScale: Math.max(0.8, Math.min(1.5, 1 + (features.avgInteractionDuration - 2000) / 10000)) }; } // Analyze interaction style preferences analyzeInteractionStyle(interactions, features) { const typeDistribution = { mouse: features.clickRatio + features.hoverRatio, touch: interactions.filter(i => i.metadata?.touch).length / interactions.length, keyboard: interactions.filter(i => i.type === 'type').length / interactions.length }; const primaryInput = Object.entries(typeDistribution).sort(([, a], [, b]) => b - a)[0][0]; return { primaryInput, preferredGestures: ['tap', 'swipe'], // Would analyze gesture interactions clickPressure: 0.5, // Would analyze from pressure data hoverDelay: features.avgInteractionDuration > 1000 ? 500 : 200, doubleClickSpeed: features.rapidInteractions > features.slowInteractions ? 300 : 500, scrollSensitivity: 1.0 // Would analyze scroll patterns }; } // Analyze content preferences analyzeContentPreferences(interactions, features) { const longInteractions = interactions.filter(i => i.duration > 3000).length; const totalInteractions = interactions.length; return { informationDensity: longInteractions / totalInteractions > 0.3 ? 'detailed' : 'moderate', explanationLevel: features.uniqueContexts > 15 ? 'comprehensive' : 'standard', examplePreference: features.contextSwitchRate < 0.5, // Less switching suggests preference for examples visualPreference: features.hoverRatio > features.clickRatio, // More hovering suggests visual preference progressIndicators: features.avgInteractionDuration > 2000 // Longer interactions benefit from progress }; } // Analyze temporal usage patterns analyzeTemporalPatterns(interactions, features) { const hourDistribution = this.calculateHourDistribution(interactions); const peakHour = hourDistribution.indexOf(Math.max(...hourDistribution)); return { mostActiveHours: hourDistribution.map((count, hour) => ({ hour, count })).filter(({ count }) => count > hourDistribution.length * 0.1).map(({ hour }) => hour), peakPerformanceTime: peakHour, preferredSessionDuration: features.avgInteractionDuration * 10, // Estimate breakFrequency: Math.max(15, 60 - features.recentInteractionRate * 5) // Minutes }; } // Analyze cognitive processing patterns analyzeCognitiveProfile(interactions, features) { return { processingSpeed: Math.max(0.1, Math.min(2.0, features.rapidInteractions / Math.max(1, features.slowInteractions))), workingMemoryCapacity: Math.max(4, Math.min(9, 7 - features.contextSwitchRate * 3)), attentionSpan: Math.max(1, features.avgInteractionDuration / 60000), // Minutes multitaskingPreference: features.contextSwitchRate > 0.3, interruptionTolerance: Math.max(0, Math.min(1, 1 - features.sequentialClicks / 100)) }; } // Generate personalization recommendations generateRecommendations(userId) { const profile = this.profiles.get(userId); if (!profile) return []; const recommendations = []; // UI recommendations if (profile.uiPreferences.animationSpeed < 0.7) { recommendations.push({ type: 'ui', component: 'animations', recommendation: 'Reduce animation speed to match user preference for slower interactions', confidence: 0.8, reasoning: ['User shows preference for slower interactions', 'Animation speed below threshold'], expectedImpact: 0.3, testable: true }); } // Content recommendations if (profile.contentPreferences.informationDensity === 'detailed' && profile.cognitiveProfile.attentionSpan > 5) { recommendations.push({ type: 'content', component: 'information-display', recommendation: 'Show more detailed information by default', confidence: 0.9, reasoning: ['User prefers detailed information', 'High attention span supports more content'], expectedImpact: 0.4, testable: true }); } // Interaction recommendations if (profile.interactionStyle.primaryInput === 'touch' && profile.uiPreferences.density !== 'spacious') { recommendations.push({ type: 'interaction', component: 'button-spacing', recommendation: 'Increase button spacing for touch interactions', confidence: 0.85, reasoning: ['Primary input is touch', 'Touch interfaces benefit from more spacing'], expectedImpact: 0.35, testable: true }); } return recommendations.sort((a, b) => b.expectedImpact - a.expectedImpact); } // Predict user behavior for given context predictBehavior(context, currentTime) { const time = currentTime || Date.now(); const hour = new Date(time).getHours(); const day = new Date(time).getDay(); const relevantPatterns = this.patterns.filter(pattern => pattern.contexts.includes(context) && pattern.temporal.timeOfDay.includes(hour) && pattern.temporal.dayOfWeek.includes(day)); return relevantPatterns.map(pattern => ({ action: pattern.name, probability: pattern.confidence * pattern.frequency / 100 })).sort((a, b) => b.probability - a.probability).slice(0, 5); } // Utility methods countSequentialPatterns(interactions, type) { let count = 0; let sequential = 0; for (let i = 0; i < interactions.length; i++) { if (interactions[i].type === type) { sequential++; } else { if (sequential > 1) count++; sequential = 0; } } return count; } calculateAveragePosition(interactions, axis) { const withPosition = interactions.filter(i => i.position); if (withPosition.length === 0) return 0; return withPosition.reduce((sum, i) => sum + i.position[axis], 0) / withPosition.length; } calculatePositionVariance(interactions) { const withPosition = interactions.filter(i => i.position); if (withPosition.length === 0) return 0; const avgX = this.calculateAveragePosition(interactions, 'x'); const avgY = this.calculateAveragePosition(interactions, 'y'); const variance = withPosition.reduce((sum, i) => { const dx = i.position.x - avgX; const dy = i.position.y - avgY; return sum + (dx * dx + dy * dy); }, 0) / withPosition.length; return Math.sqrt(variance); } calculateContextSwitchRate(interactions) { if (interactions.length < 2) return 0; let switches = 0; for (let i = 1; i < interactions.length; i++) { if (interactions[i].context !== interactions[i - 1].context) { switches++; } } return switches / (interactions.length - 1); } calculateHourDistribution(interactions) { const distribution = new Array(24).fill(0); interactions.forEach(interaction => { const hour = new Date(interaction.timestamp).getHours(); distribution[hour]++; }); return distribution; } calculateOverallConfidence(interactions) { if (interactions.length < 10) return 0.1; if (interactions.length < 50) return 0.3; if (interactions.length < 200) return 0.6; if (interactions.length < 500) return 0.8; return 0.9; } updateModelsIncremental(features) { // Simplified incremental learning - in production would use proper ML algorithms Object.entries(features).forEach(([feature, value]) => { let model = this.models.get(feature); if (!model) { model = { type: 'linear', features: [feature], weights: [1], bias: 0, accuracy: 0.5, lastTrained: Date.now() }; this.models.set(feature, model); } // Simple weight update (would use gradient descent in production) model.weights[0] = model.weights[0] * 0.99 + value * 0.01; model.lastTrained = Date.now(); }); } } // Global AI personalization engine const aiPersonalizationEngine = new AIPersonalizationEngine(); // React hooks for AI personalization const useAIPersonalization = userId => { const [profile, setProfile] = useState(null); const [recommendations, setRecommendations] = useState([]); const [isLearning, setIsLearning] = useState(false); const recordInteraction = useCallback(interaction => { const fullInteraction = { ...interaction, id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, timestamp: Date.now() }; aiPersonalizationEngine.addInteraction(fullInteraction); }, []); const updateProfile = useCallback(() => { setIsLearning(true); const newProfile = aiPersonalizationEngine.generatePersonalizationProfile(userId); setProfile(newProfile); const newRecommendations = aiPersonalizationEngine.generateRecommendations(userId); setRecommendations(newRecommendations); setIsLearning(false); }, [userId]); const predictBehavior = useCallback(context => { return aiPersonalizationEngine.predictBehavior(context); }, []); // Auto-update profile periodically useEffect(() => { const interval = setInterval(updateProfile, 30000); // Every 30 seconds updateProfile(); // Initial update return () => clearInterval(interval); }, [updateProfile]); return { profile, recommendations, isLearning, recordInteraction, updateProfile, predictBehavior }; }; // Hook for automatic interaction recording const useInteractionRecording = (componentId, userId) => { const { recordInteraction } = useAIPersonalization(userId); const startTime = useRef(0); const startInteraction = useCallback((type, context) => { startTime.current = Date.now(); return { type, target: componentId, context: context || window.location.pathname }; }, [componentId]); const endInteraction = useCallback((interactionStart, position) => { const duration = Date.now() - startTime.current; recordInteraction({ ...interactionStart, duration, position }); }, [recordInteraction]); return { startInteraction, endInteraction }; }; export { aiPersonalizationEngine as default, useAIPersonalization, useInteractionRecording }; //# sourceMappingURL=aiPersonalization.js.map